[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86InstrInfo.def
Chris Lattner
lattner at cs.uiuc.edu
Sat Nov 2 14:55:08 PST 2002
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.20 -> 1.21
X86InstrInfo.def updated: 1.11 -> 1.12
---
Log message:
Implement signed and unsigned division and remainder
---
Diffs of the changes:
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.20 llvm/lib/Target/X86/InstSelectSimple.cpp:1.21
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.20 Sat Nov 2 14:28:58 2002
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Sat Nov 2 14:54:46 2002
@@ -59,15 +59,19 @@
void visitBranchInst(BranchInst &BI);
// Arithmetic operators
+ void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); }
void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); }
void visitMul(BinaryOperator &B);
+ void visitDiv(BinaryOperator &B) { visitDivRem(B); }
+ void visitRem(BinaryOperator &B) { visitDivRem(B); }
+ void visitDivRem(BinaryOperator &B);
+
// Bitwise operators
void visitAnd(BinaryOperator &B) { visitSimpleBinary(B, 2); }
void visitOr (BinaryOperator &B) { visitSimpleBinary(B, 3); }
void visitXor(BinaryOperator &B) { visitSimpleBinary(B, 4); }
- void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
// Binary comparison operators
@@ -247,7 +251,55 @@
// Put the result into the destination register...
BuildMI(BB, MovOpcode[Class], 1, getReg(I)).addReg(Reg);
+}
+
+/// visitDivRem - Handle division and remainder instructions... these
+/// instruction both require the same instructions to be generated, they just
+/// select the result from a different register. Note that both of these
+/// instructions work differently for signed and unsigned operands.
+///
+void ISel::visitDivRem(BinaryOperator &I) {
+ unsigned Class = getClass(I.getType());
+ if (Class > 2) // FIXME: Handle longs
+ visitInstruction(I);
+ static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
+ static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
+ static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CWQ };
+ static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
+ static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
+
+ static const unsigned DivOpcode[][4] = {
+ { X86::DIVrr8 , X86::DIVrr16 , X86::DIVrr32 , 0 }, // Unsigned division
+ { X86::IDIVrr8, X86::IDIVrr16, X86::IDIVrr32, 0 }, // Signed division
+ };
+
+ bool isSigned = I.getType()->isSigned();
+ unsigned Reg = Regs[Class];
+ unsigned ExtReg = ExtRegs[Class];
+ unsigned Op0Reg = getReg(I.getOperand(1));
+ unsigned Op1Reg = getReg(I.getOperand(1));
+
+ // Put the first operand into one of the A registers...
+ BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
+
+ if (isSigned) {
+ // Emit a sign extension instruction...
+ BuildMI(BB, ExtOpcode[Class], 1, ExtReg).addReg(Reg);
+ } else {
+ // If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
+ BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
+ }
+
+ // Figure out which register we want to pick the result out of...
+ unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg;
+
+ // Emit the appropriate multiple instruction...
+ // FIXME: We need to mark that this modified AH, DX, or EDX also!!
+ BuildMI(BB,DivOpcode[isSigned][Class], 2, DestReg).addReg(Reg).addReg(Op1Reg);
+
+ // Put the result into the destination register...
+ BuildMI(BB, MovOpcode[Class], 1, getReg(I)).addReg(DestReg);
}
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
@@ -255,11 +307,9 @@
/// 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);
+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());
Index: llvm/lib/Target/X86/X86InstrInfo.def
diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.11 llvm/lib/Target/X86/X86InstrInfo.def:1.12
--- llvm/lib/Target/X86/X86InstrInfo.def:1.11 Sat Nov 2 14:28:58 2002
+++ llvm/lib/Target/X86/X86InstrInfo.def Sat Nov 2 14:54:46 2002
@@ -56,6 +56,16 @@
I(MULrr16 , "mulw", 0, 0) // DX:AX= AX*R16 F7/4
I(MULrr32 , "mull", 0, 0) // ED:EA= EA*R32 F7/4
+// unsigned division/remainder
+I(DIVrr8 , "divb", 0, 0) // AX/r8= AL&AH F6/6
+I(DIVrr16 , "divw", 0, 0) // DA/r16=AX&DX F7/6
+I(DIVrr32 , "divl", 0, 0) // DA/r32=EAX&DX F7/6
+
+// signed division/remainder
+I(IDIVrr8 , "idivb", 0, 0) // AX/r8= AL&AH F6/6
+I(IDIVrr16 , "idivw", 0, 0) // DA/r16=AX&DX F7/6
+I(IDIVrr32 , "idivl", 0, 0) // DA/r32=EAX&DX F7/6
+
// Logical operators
I(ANDrr8 , "andb", 0, 0) // R8 &= R8 20/r
@@ -87,6 +97,12 @@
I(SARir16 , "sarw", 0, 0) // R16 >>= imm8 C1/7 ib
I(SARrr32 , "sarl", 0, 0) // R32 >>= cl D3/7
I(SARir32 , "sarl", 0, 0) // R32 >>= imm8 C1/7 ib
+
+
+// Miscellaneous instructions...
+I(CBW , "cbw", 0, 0) // AH = signext(AL) 98
+I(CWD , "cwd", 0, 0) // DX = signext(AX) 99
+I(CWQ , "cwq", 0, 0) // EDX= signext(EAX) 99
// At this point, I is dead, so undefine the macro
#undef I
More information about the llvm-commits
mailing list