+/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized
+/// register, then move it to wherever the result should be.
+/// We handle FP setcc instructions by pushing them, doing a
+/// compare-and-pop-twice, and then copying the concodes to the main
+/// processor's concodes (I didn't make this up, it's in the Intel manual)
+///
+void ISel::visitSetCCInst(SetCondInst &I, unsigned OpNum) {
+ // The arguments are already supposed to be of the same type.
+ const Type *CompTy = I.getOperand(0)->getType();
+ unsigned reg1 = getReg(I.getOperand(0));
+ unsigned reg2 = getReg(I.getOperand(1));
+
+ unsigned Class = getClass(CompTy);
+ switch (Class) {
+ // Emit: cmp <var1>, <var2> (do the comparison). We can
+ // compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with
+ // 32-bit.
+ case cByte:
+ BuildMI (BB, X86::CMPrr8, 2).addReg (reg1).addReg (reg2);
+ break;
+ case cShort:
+ BuildMI (BB, X86::CMPrr16, 2).addReg (reg1).addReg (reg2);
+ break;
+ case cInt:
+ BuildMI (BB, X86::CMPrr32, 2).addReg (reg1).addReg (reg2);
+ break;
+
+ // Push the variables on the stack with fldl opcodes.
+ // FIXME: assuming var1, var2 are in memory, if not, spill to
+ // stack first
+ case cFloat: // Floats
+ BuildMI (BB, X86::FLDr4, 1).addReg (reg1);
+ BuildMI (BB, X86::FLDr4, 1).addReg (reg2);
+ break;
+ case cDouble: // Doubles
+ BuildMI (BB, X86::FLDr8, 1).addReg (reg1);
+ BuildMI (BB, X86::FLDr8, 1).addReg (reg2);
+ break;
+ case cLong:
+ default:
+ visitInstruction(I);
+ }
+
+ if (CompTy->isFloatingPoint()) {
+ // (Non-trapping) compare and pop twice.
+ BuildMI (BB, X86::FUCOMPP, 0);
+ // Move fp status word (concodes) to ax.
+ BuildMI (BB, X86::FNSTSWr8, 1, X86::AX);
+ // Load real concodes from ax.
+ BuildMI (BB, X86::SAHF, 1).addReg(X86::AH);
+ }
+
+ // Emit setOp instruction (extract concode; clobbers ax),
+ // using the following mapping:
+ // LLVM -> X86 signed X86 unsigned
+ // ----- ----- -----
+ // seteq -> sete sete
+ // setne -> setne setne
+ // setlt -> setl setb
+ // setgt -> setg seta
+ // setle -> setle setbe
+ // setge -> setge setae
+
+ static const unsigned OpcodeTab[2][6] = {
+ {X86::SETEr, X86::SETNEr, X86::SETBr, X86::SETAr, X86::SETBEr, X86::SETAEr},
+ {X86::SETEr, X86::SETNEr, X86::SETLr, X86::SETGr, X86::SETLEr, X86::SETGEr},
+ };
+
+ BuildMI(BB, OpcodeTab[CompTy->isSigned()][OpNum], 0, X86::AL);
+
+ // Put it in the result using a move.
+ BuildMI (BB, X86::MOVrr8, 1, getReg(I)).addReg(X86::AL);
+}
+
+/// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide
+/// operand, in the specified target register.
+void
+ISel::promote32 (const unsigned targetReg, Value *v)
+{
+ unsigned vReg = getReg (v);
+ unsigned Class = getClass (v->getType ());
+ bool isUnsigned = v->getType ()->isUnsigned ();
+ assert (((Class == cByte) || (Class == cShort) || (Class == cInt))
+ && "Unpromotable operand class in promote32");
+ switch (Class)
+ {
+ case cByte:
+ // Extend value into target register (8->32)
+ if (isUnsigned)
+ BuildMI (BB, X86::MOVZXr32r8, 1, targetReg).addReg (vReg);
+ else
+ BuildMI (BB, X86::MOVSXr32r8, 1, targetReg).addReg (vReg);
+ break;
+ case cShort:
+ // Extend value into target register (16->32)
+ if (isUnsigned)
+ BuildMI (BB, X86::MOVZXr32r16, 1, targetReg).addReg (vReg);
+ else
+ BuildMI (BB, X86::MOVSXr32r16, 1, targetReg).addReg (vReg);
+ break;
+ case cInt:
+ // Move value into target register (32->32)
+ BuildMI (BB, X86::MOVrr32, 1, targetReg).addReg (vReg);
+ break;
+ }
+}