+ case Type::ULongTyID:
+ assert("FIXME: not implemented: cast ulong X to fp type!");
+ default: // No promotion needed...
+ break;
+ }
+
+ if (PromoteType) {
+ unsigned TmpReg = makeAnotherReg(PromoteType);
+ BMI(BB, IP, SrcTy->isSigned() ? X86::MOVSXr16r8 : X86::MOVZXr16r8,
+ 1, TmpReg).addReg(SrcReg);
+ SrcTy = PromoteType;
+ SrcClass = getClass(PromoteType);
+ SrcReg = TmpReg;
+ }
+
+ // Spill the integer to memory and reload it from there...
+ int FrameIdx =
+ F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
+
+ if (SrcClass == cLong) {
+ addFrameReference(BMI(BB, IP, X86::MOVrm32, 5), FrameIdx).addReg(SrcReg);
+ addFrameReference(BMI(BB, IP, X86::MOVrm32, 5),
+ FrameIdx, 4).addReg(SrcReg+1);
+ } else {
+ static const unsigned Op1[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
+ addFrameReference(BMI(BB, IP, Op1[SrcClass], 5), FrameIdx).addReg(SrcReg);
+ }
+
+ static const unsigned Op2[] =
+ { 0/*byte*/, X86::FILDr16, X86::FILDr32, 0/*FP*/, X86::FILDr64 };
+ addFrameReference(BMI(BB, IP, Op2[SrcClass], 5, DestReg), FrameIdx);
+ return;
+ }
+
+ // Handle casts from floating point to integer now...
+ if (SrcClass == cFP) {
+ // Change the floating point control register to use "round towards zero"
+ // mode when truncating to an integer value.
+ //
+ int CWFrameIdx = F->getFrameInfo()->CreateStackObject(2, 2);
+ addFrameReference(BMI(BB, IP, X86::FNSTCWm16, 4), CWFrameIdx);
+
+ // Load the old value of the high byte of the control word...
+ unsigned HighPartOfCW = makeAnotherReg(Type::UByteTy);
+ addFrameReference(BMI(BB, IP, X86::MOVmr8, 4, HighPartOfCW), CWFrameIdx, 1);
+
+ // Set the high part to be round to zero...
+ addFrameReference(BMI(BB, IP, X86::MOVim8, 5), CWFrameIdx, 1).addZImm(12);
+
+ // Reload the modified control word now...
+ addFrameReference(BMI(BB, IP, X86::FLDCWm16, 4), CWFrameIdx);
+
+ // Restore the memory image of control word to original value
+ addFrameReference(BMI(BB, IP, X86::MOVrm8, 5),
+ CWFrameIdx, 1).addReg(HighPartOfCW);
+
+ // We don't have the facilities for directly storing byte sized data to
+ // memory. Promote it to 16 bits. We also must promote unsigned values to
+ // larger classes because we only have signed FP stores.
+ unsigned StoreClass = DestClass;
+ const Type *StoreTy = DestTy;
+ if (StoreClass == cByte || DestTy->isUnsigned())
+ switch (StoreClass) {
+ case cByte: StoreTy = Type::ShortTy; StoreClass = cShort; break;
+ case cShort: StoreTy = Type::IntTy; StoreClass = cInt; break;
+ case cInt: StoreTy = Type::LongTy; StoreClass = cLong; break;
+ // The following treatment of cLong may not be perfectly right,
+ // but it survives chains of casts of the form
+ // double->ulong->double.
+ case cLong: StoreTy = Type::LongTy; StoreClass = cLong; break;
+ default: assert(0 && "Unknown store class!");
+ }
+
+ // Spill the integer to memory and reload it from there...
+ int FrameIdx =
+ F->getFrameInfo()->CreateStackObject(StoreTy, TM.getTargetData());
+
+ static const unsigned Op1[] =
+ { 0, X86::FISTr16, X86::FISTr32, 0, X86::FISTPr64 };
+ addFrameReference(BMI(BB, IP, Op1[StoreClass], 5), FrameIdx).addReg(SrcReg);
+
+ if (DestClass == cLong) {
+ addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg), FrameIdx);
+ addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg+1), FrameIdx, 4);
+ } else {
+ static const unsigned Op2[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
+ addFrameReference(BMI(BB, IP, Op2[DestClass], 4, DestReg), FrameIdx);
+ }
+
+ // Reload the original control word now...
+ addFrameReference(BMI(BB, IP, X86::FLDCWm16, 4), CWFrameIdx);
+ return;
+ }
+