+void V8ISel::visitCastInst(CastInst &I) {
+ Value *Op = I.getOperand(0);
+ unsigned DestReg = getReg(I);
+ MachineBasicBlock::iterator MI = BB->end();
+ emitCastOperation(BB, MI, Op, I.getType(), DestReg);
+}
+
+/// emitCastOperation - Common code shared between visitCastInst and constant
+/// expression cast support.
+///
+void V8ISel::emitCastOperation(MachineBasicBlock *BB,
+ MachineBasicBlock::iterator IP,
+ Value *Src, const Type *DestTy,
+ unsigned DestReg) {
+ const Type *SrcTy = Src->getType();
+ unsigned SrcClass = getClassB(SrcTy);
+ unsigned DestClass = getClassB(DestTy);
+ unsigned SrcReg = getReg(Src, BB, IP);
+
+ const Type *oldTy = SrcTy;
+ const Type *newTy = DestTy;
+ unsigned oldTyClass = SrcClass;
+ unsigned newTyClass = DestClass;
+
+ if (oldTyClass < cLong && newTyClass < cLong) {
+ if (oldTyClass >= newTyClass) {
+ // Emit a reg->reg copy to do a equal-size or narrowing cast,
+ // and do sign/zero extension (necessary if we change signedness).
+ unsigned TmpReg1 = makeAnotherReg (newTy);
+ unsigned TmpReg2 = makeAnotherReg (newTy);
+ BuildMI (*BB, IP, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
+ unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
+ BuildMI (*BB, IP, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
+ if (newTy->isSigned ()) { // sign-extend with SRA
+ BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
+ } else { // zero-extend with SRL
+ BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
+ }
+ } else {
+ unsigned TmpReg1 = makeAnotherReg (oldTy);
+ unsigned TmpReg2 = makeAnotherReg (newTy);
+ unsigned TmpReg3 = makeAnotherReg (newTy);
+ // Widening integer cast. Make sure it's fully sign/zero-extended
+ // wrt the input type, then make sure it's fully sign/zero-extended wrt
+ // the output type. Kind of stupid, but simple...
+ unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
+ BuildMI (*BB, IP, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
+ if (oldTy->isSigned ()) { // sign-extend with SRA
+ BuildMI(*BB, IP, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
+ } else { // zero-extend with SRL
+ BuildMI(*BB, IP, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
+ }
+ shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
+ BuildMI (*BB, IP, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
+ if (newTy->isSigned ()) { // sign-extend with SRA
+ BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
+ } else { // zero-extend with SRL
+ BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
+ }
+ }
+ } else {
+ if (newTyClass == cFloat) {
+ assert (oldTyClass != cLong && "cast long to float not implemented yet");
+ switch (oldTyClass) {
+ case cFloat:
+ BuildMI (*BB, IP, V8::FMOVS, 1, DestReg).addReg (SrcReg);
+ break;
+ case cDouble:
+ BuildMI (*BB, IP, V8::FDTOS, 1, DestReg).addReg (SrcReg);
+ break;
+ default: {
+ unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+ // cast int to float. Store it to a stack slot and then load
+ // it using ldf into a floating point register. then do fitos.
+ unsigned TmpReg = makeAnotherReg (newTy);
+ int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+ BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (SrcReg);
+ BuildMI (*BB, IP, V8::LDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0);
+ BuildMI (*BB, IP, V8::FITOS, 1, DestReg).addReg(TmpReg);
+ break;
+ }
+ }
+ } else if (newTyClass == cDouble) {
+ assert (oldTyClass != cLong && "cast long to double not implemented yet");
+ switch (oldTyClass) {
+ case cFloat:
+ BuildMI (*BB, IP, V8::FSTOD, 1, DestReg).addReg (SrcReg);
+ break;
+ case cDouble: // use double move pseudo-instr
+ BuildMI (*BB, IP, V8::FpMOVD, 1, DestReg).addReg (SrcReg);
+ break;
+ default: {
+ unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
+ unsigned TmpReg = makeAnotherReg (newTy);
+ int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
+ BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0)
+ .addReg (SrcReg);
+ BuildMI (*BB, IP, V8::LDDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0);
+ BuildMI (*BB, IP, V8::FITOD, 1, DestReg).addReg(TmpReg);
+ 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";
+ abort ();
+ }
+ }
+}
+
+void V8ISel::visitLoadInst(LoadInst &I) {