// Copy the value into the register pair.
// R = top(more-significant) half, R+1 = bottom(less-significant) half
uint64_t Val = cast<ConstantInt>(C)->getRawValue();
- unsigned topHalf = Val & 0xffffffffU;
- unsigned bottomHalf = Val >> 32;
+ unsigned bottomHalf = Val & 0xffffffffU;
+ unsigned topHalf = Val >> 32;
unsigned HH = topHalf >> 10;
unsigned HM = topHalf & 0x03ff;
unsigned LM = bottomHalf >> 10;
} else if (isa<ConstantPointerNull>(C)) {
// Copy zero (null pointer) to the register.
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0);
- } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
+ } else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
// Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize
// that SETHI %reg,global == SETHI %reg,%hi(global) and
// OR %reg,global,%reg == OR %reg,%lo(global),%reg.
unsigned TmpReg = makeAnotherReg (C->getType ());
- BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress (CPR->getValue());
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg)
- .addGlobalAddress (CPR->getValue ());
+ BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV);
+ BuildMI (*MBB, IP, V8::ORri, 2, R).addReg(TmpReg).addGlobalAddress(GV);
} else {
std::cerr << "Offending constant: " << *C << "\n";
assert (0 && "Can't copy this kind of constant into register yet");
}
}
-void V8ISel::LoadArgumentsToVirtualRegs (Function *F) {
- unsigned ArgOffset = 0;
+void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
+ unsigned ArgOffset;
static const unsigned IncomingArgRegs[] = { V8::I0, V8::I1, V8::I2,
V8::I3, V8::I4, V8::I5 };
- assert (F->asize () < 7
+ assert (LF->asize () < 7
&& "Can't handle loading excess call args off the stack yet");
- for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I) {
+ // Add IMPLICIT_DEFs of input regs.
+ ArgOffset = 0;
+ for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
+ unsigned Reg = getReg(*I);
+ switch (getClassB(I->getType())) {
+ case cByte:
+ case cShort:
+ case cInt:
+ case cFloat:
+ BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]);
+ break;
+ default:
+ // FIXME: handle cDouble, cLong
+ assert (0 && "64-bit (double, long, etc.) function args not handled");
+ return;
+ }
+ ++ArgOffset;
+ }
+
+ ArgOffset = 0;
+ for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
unsigned Reg = getReg(*I);
switch (getClassB(I->getType())) {
case cByte:
BuildMI(BB, V8::ORrr, 2, Reg).addReg (V8::G0)
.addReg (IncomingArgRegs[ArgOffset]);
break;
+ case cFloat: {
+ // Single-fp args are passed in integer registers; go through
+ // memory to get them into FP registers. (Bleh!)
+ unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+ int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+ BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (IncomingArgRegs[ArgOffset]);
+ BuildMI (BB, V8::LDFri, 2, Reg).addFrameIndex (FI).addSImm (0);
+ break;
+ }
default:
- assert (0 && "Only <=32-bit, integral arguments currently handled");
+ // FIXME: handle cDouble, cLong
+ assert (0 && "64-bit (double, long, etc.) function args not handled");
return;
}
++ArgOffset;
}
+
}
void V8ISel::SelectPHINodes() {
break;
}
}
+ } else if (newTyClass == cLong) {
+ if (oldTyClass == cLong) {
+ // Just copy it
+ BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
+ BuildMI (*BB, IP, V8::ORrr, 2, DestReg+1).addReg (V8::G0)
+ .addReg (SrcReg+1);
+ } else {
+ std::cerr << "Cast still unsupported: SrcTy = "
+ << *SrcTy << ", DestTy = " << *DestTy << "\n";
+ abort ();
+ }
} else {
std::cerr << "Cast still unsupported: SrcTy = "
<< *SrcTy << ", DestTy = " << *DestTy << "\n";
V8::O4, V8::O5 };
for (unsigned i = 1; i < 7; ++i)
if (i < I.getNumOperands ()) {
- assert (getClassB (I.getOperand (i)->getType ()) < cLong
- && "Can't handle long or fp function call arguments yet");
unsigned ArgReg = getReg (I.getOperand (i));
- // Schlep it over into the incoming arg register
- BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
- .addReg (ArgReg);
+ if (getClassB (I.getOperand (i)->getType ()) < cLong) {
+ // Schlep it over into the incoming arg register
+ BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
+ .addReg (ArgReg);
+ } else if (getClassB (I.getOperand (i)->getType ()) == cFloat) {
+ // Single-fp args are passed in integer registers; go through
+ // memory to get them out of FP registers. (Bleh!)
+ unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+ int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+ BuildMI (BB, V8::STFri, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (ArgReg);
+ BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i - 1]).addFrameIndex (FI)
+ .addSImm (0);
+ } else {
+ assert (0 && "64-bit (double, long, etc.) 'call' opnds not handled");
+ }
}
// Emit call instruction
// Schlep it over into i0 (where it will become o0 after restore).
BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
break;
+ case cFloat:
+ BuildMI (BB, V8::FMOVS, 2, V8::F0).addReg(RetValReg);
+ break;
+ case cDouble: {
+ unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
+ int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
+ BuildMI (BB, V8::STDFri, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (RetValReg);
+ BuildMI (BB, V8::LDDFri, 2, V8::F0).addFrameIndex (FI).addSImm (0);
+ break;
+ }
+ case cLong:
+ BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
+ BuildMI (BB, V8::ORrr, 2, V8::I1).addReg(V8::G0).addReg(RetValReg+1);
+ break;
default:
std::cerr << "Return instruction of this type not handled: " << I;
abort ();
BuildMI (BB, Opcodes[OpCase], 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
}
- switch (getClass (I.getType ())) {
+ switch (getClassB (I.getType ())) {
case cByte:
if (I.getType ()->isSigned ()) { // add byte
BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
}
break;
case cInt:
- // Nothing todo here.
+ // Nothing to do here.
break;
case cLong:
// Only support and, or, xor.
unsigned DestReg = getReg (I);
const Type *Ty = I.getOperand (0)->getType ();
- assert (getClass (Ty) < cLong && "can't setcc on longs or fp yet");
// Compare the two values.
- BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
+ assert (getClass (Ty) != cLong && "can't setcc on longs yet");
+ if (getClass (Ty) < cLong) {
+ BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
+ } else if (getClass (Ty) == cFloat) {
+ BuildMI(BB, V8::FCMPS, 2).addReg(Op0Reg).addReg(Op1Reg);
+ } else if (getClass (Ty) == cDouble) {
+ BuildMI(BB, V8::FCMPD, 2).addReg(Op0Reg).addReg(Op1Reg);
+ }
unsigned BranchIdx;
switch (I.getOpcode()) {
case Instruction::SetLE: BranchIdx = 4; break;
case Instruction::SetGE: BranchIdx = 5; break;
}
- static unsigned OpcodeTab[12] = {
- // LLVM SparcV8
- // unsigned signed
- V8::BE, V8::BE, // seteq = be be
- V8::BNE, V8::BNE, // setne = bne bne
- V8::BCS, V8::BL, // setlt = bcs bl
- V8::BGU, V8::BG, // setgt = bgu bg
- V8::BLEU, V8::BLE, // setle = bleu ble
- V8::BCC, V8::BGE // setge = bcc bge
+ unsigned Column = 0;
+ if (Ty->isSigned()) ++Column;
+ if (Ty->isFloatingPoint()) ++Column;
+ static unsigned OpcodeTab[3*6] = {
+ // LLVM SparcV8
+ // unsigned signed fp
+ V8::BE, V8::BE, V8::FBE, // seteq = be be fbe
+ V8::BNE, V8::BNE, V8::FBNE, // setne = bne bne fbne
+ V8::BCS, V8::BL, V8::FBL, // setlt = bcs bl fbl
+ V8::BGU, V8::BG, V8::FBG, // setgt = bgu bg fbg
+ V8::BLEU, V8::BLE, V8::FBLE, // setle = bleu ble fble
+ V8::BCC, V8::BGE, V8::FBGE // setge = bcc bge fbge
};
- unsigned Opcode = OpcodeTab[2*BranchIdx + (Ty->isSigned() ? 1 : 0)];
+ unsigned Opcode = OpcodeTab[3*BranchIdx + Column];
MachineBasicBlock *thisMBB = BB;
const BasicBlock *LLVM_BB = BB->getBasicBlock ();