+/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
+/// for constant immediate shift values, and for constant immediate
+/// shift values equal to 1. Even the general case is sort of special,
+/// because the shift amount has to be in CL, not just any old register.
+///
+void ISel::visitShiftInst (ShiftInst &I) {
+ unsigned Op0r = getReg (I.getOperand(0));
+ unsigned DestReg = getReg(I);
+ bool isLeftShift = I.getOpcode() == Instruction::Shl;
+ bool isOperandSigned = I.getType()->isUnsigned();
+ unsigned OperandClass = getClass(I.getType());
+
+ if (OperandClass > 2)
+ visitInstruction(I); // Can't handle longs yet!
+
+ if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
+ {
+ // The shift amount is constant, guaranteed to be a ubyte. Get its value.
+ assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
+ unsigned char shAmt = CUI->getValue();
+
+ static const unsigned ConstantOperand[][4] = {
+ { X86::SHRir8, X86::SHRir16, X86::SHRir32, 0 }, // SHR
+ { X86::SARir8, X86::SARir16, X86::SARir32, 0 }, // SAR
+ { X86::SHLir8, X86::SHLir16, X86::SHLir32, 0 }, // SHL
+ { X86::SHLir8, X86::SHLir16, X86::SHLir32, 0 }, // SAL = SHL
+ };
+
+ const unsigned *OpTab = // Figure out the operand table to use
+ ConstantOperand[isLeftShift*2+isOperandSigned];
+
+ // Emit: <insn> reg, shamt (shift-by-immediate opcode "ir" form.)
+ BuildMI(BB, OpTab[OperandClass], 2, DestReg).addReg(Op0r).addZImm(shAmt);
+ }
+ else
+ {
+ // The shift amount is non-constant.
+ //
+ // In fact, you can only shift with a variable shift amount if
+ // that amount is already in the CL register, so we have to put it
+ // there first.
+ //
+
+ // Emit: move cl, shiftAmount (put the shift amount in CL.)
+ BuildMI(BB, X86::MOVrr8, 1, X86::CL).addReg(getReg(I.getOperand(1)));
+
+ // This is a shift right (SHR).
+ static const unsigned NonConstantOperand[][4] = {
+ { X86::SHRrr8, X86::SHRrr16, X86::SHRrr32, 0 }, // SHR
+ { X86::SARrr8, X86::SARrr16, X86::SARrr32, 0 }, // SAR
+ { X86::SHLrr8, X86::SHLrr16, X86::SHLrr32, 0 }, // SHL
+ { X86::SHLrr8, X86::SHLrr16, X86::SHLrr32, 0 }, // SAL = SHL
+ };
+
+ const unsigned *OpTab = // Figure out the operand table to use
+ NonConstantOperand[isLeftShift*2+isOperandSigned];
+
+ BuildMI(BB, OpTab[OperandClass], 1, DestReg).addReg(Op0r);
+ }
+}
+
+
+/// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov'
+/// instruction.
+///
+void ISel::visitLoadInst(LoadInst &I) {
+ unsigned Class = getClass(I.getType());
+ if (Class > 2) // FIXME: Handle longs and others...
+ visitInstruction(I);
+
+ static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
+
+ unsigned AddressReg = getReg(I.getOperand(0));
+ addDirectMem(BuildMI(BB, Opcode[Class], 4, getReg(I)), AddressReg);
+}
+
+
+/// visitStoreInst - Implement LLVM store instructions in terms of the x86 'mov'
+/// instruction.
+///
+void ISel::visitStoreInst(StoreInst &I) {
+ unsigned Class = getClass(I.getOperand(0)->getType());
+ if (Class > 2) // FIXME: Handle longs and others...
+ visitInstruction(I);
+
+ static const unsigned Opcode[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
+
+ unsigned ValReg = getReg(I.getOperand(0));
+ unsigned AddressReg = getReg(I.getOperand(1));
+ addDirectMem(BuildMI(BB, Opcode[Class], 1+4), AddressReg).addReg(ValReg);
+}
+
+
+/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node...
+///
+void ISel::visitPHINode(PHINode &PN) {
+ MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN));
+
+ for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
+ // FIXME: This will put constants after the PHI nodes in the block, which
+ // is invalid. They should be put inline into the PHI node eventually.
+ //
+ MI->addRegOperand(getReg(PN.getIncomingValue(i)));
+ MI->addPCDispOperand(PN.getIncomingBlock(i));
+ }
+}
+
+/// visitCastInst - Here we have various kinds of copying with or without
+/// sign extension going on.
+void
+ISel::visitCastInst (CastInst &CI)
+{
+ const Type *targetType = CI.getType ();
+ Value *operand = CI.getOperand (0);
+ unsigned int operandReg = getReg (operand);
+ const Type *sourceType = operand->getType ();
+ unsigned int destReg = getReg (CI);
+ //
+ // Currently we handle:
+ //
+ // 1) cast * to bool
+ //
+ // 2) cast {sbyte, ubyte} to {sbyte, ubyte}
+ // cast {short, ushort} to {ushort, short}
+ // cast {int, uint, ptr} to {int, uint, ptr}
+ //
+ // 3) cast {sbyte, ubyte} to {ushort, short}
+ // cast {sbyte, ubyte} to {int, uint, ptr}
+ // cast {short, ushort} to {int, uint, ptr}
+ //
+ // 4) cast {int, uint, ptr} to {short, ushort}
+ // cast {int, uint, ptr} to {sbyte, ubyte}
+ // cast {short, ushort} to {sbyte, ubyte}
+ //
+ // 1) Implement casts to bool by using compare on the operand followed
+ // by set if not zero on the result.
+ if (targetType == Type::BoolTy)
+ {
+ BuildMI (BB, X86::CMPri8, 2).addReg (operandReg).addZImm (0);
+ BuildMI (BB, X86::SETNEr, 1, destReg);
+ return;
+ }
+ // 2) Implement casts between values of the same type class (as determined
+ // by getClass) by using a register-to-register move.
+ unsigned int srcClass = getClass (sourceType);
+ unsigned int targClass = getClass (targetType);
+ static const unsigned regRegMove[] = {
+ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32
+ };
+ if ((srcClass < 3) && (targClass < 3) && (srcClass == targClass))
+ {
+ BuildMI (BB, regRegMove[srcClass], 1, destReg).addReg (operandReg);
+ return;
+ }
+ // 3) Handle cast of SMALLER int to LARGER int using a move with sign
+ // extension or zero extension, depending on whether the source type
+ // was signed.
+ if ((srcClass < 3) && (targClass < 3) && (srcClass < targClass))
+ {
+ static const unsigned ops[] = {
+ X86::MOVSXr16r8, X86::MOVSXr32r8, X86::MOVSXr32r16,
+ X86::MOVZXr16r8, X86::MOVZXr32r8, X86::MOVZXr32r16
+ };
+ unsigned srcSigned = sourceType->isSigned ();
+ BuildMI (BB, ops[3 * srcSigned + srcClass + targClass - 1], 1,
+ destReg).addReg (operandReg);
+ return;
+ }
+ // 4) Handle cast of LARGER int to SMALLER int using a move to EAX
+ // followed by a move out of AX or AL.
+ if ((srcClass < 3) && (targClass < 3) && (srcClass > targClass))
+ {
+ static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX };
+ BuildMI (BB, regRegMove[srcClass], 1,
+ AReg[srcClass]).addReg (operandReg);
+ BuildMI (BB, regRegMove[targClass], 1, destReg).addReg (AReg[srcClass]);
+ return;
+ }
+ // Anything we haven't handled already, we can't (yet) handle at all.
+ visitInstruction (CI);
+}