mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 22:28:18 +00:00
Use a more table driven approach to handling types. Seems to simplify the
code a bit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4493 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -90,6 +90,28 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getClass - Turn a primitive type into a "class" number which is based on the
|
||||||
|
/// size of the type, and whether or not it is floating point.
|
||||||
|
///
|
||||||
|
static inline unsigned getClass(const Type *Ty) {
|
||||||
|
switch (Ty->getPrimitiveID()) {
|
||||||
|
case Type::SByteTyID:
|
||||||
|
case Type::UByteTyID: return 0; // Byte operands are class #0
|
||||||
|
case Type::ShortTyID:
|
||||||
|
case Type::UShortTyID: return 1; // Short operands are class #1
|
||||||
|
case Type::IntTyID:
|
||||||
|
case Type::UIntTyID:
|
||||||
|
case Type::PointerTyID: return 2; // Int's and pointers are class #2
|
||||||
|
|
||||||
|
case Type::LongTyID:
|
||||||
|
case Type::ULongTyID: return 3; // Longs are class #3
|
||||||
|
case Type::FloatTyID: return 4; // Float is class #4
|
||||||
|
case Type::DoubleTyID: return 5; // Doubles are class #5
|
||||||
|
default:
|
||||||
|
assert(0 && "Invalid type to getClass!");
|
||||||
|
return 0; // not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// copyConstantToRegister - Output the instructions required to put the
|
/// copyConstantToRegister - Output the instructions required to put the
|
||||||
/// specified constant into the specified register.
|
/// specified constant into the specified register.
|
||||||
@@ -97,26 +119,23 @@ namespace {
|
|||||||
void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
||||||
assert (!isa<ConstantExpr>(C) && "Constant expressions not yet handled!\n");
|
assert (!isa<ConstantExpr>(C) && "Constant expressions not yet handled!\n");
|
||||||
|
|
||||||
switch (C->getType()->getPrimitiveID()) {
|
if (C->getType()->isIntegral()) {
|
||||||
case Type::SByteTyID:
|
unsigned Class = getClass(C->getType());
|
||||||
BuildMI(BB, X86::MOVir8, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
assert(Class != 3 && "Type not handled yet!");
|
||||||
break;
|
|
||||||
case Type::UByteTyID:
|
static const unsigned IntegralOpcodeTab[] = {
|
||||||
BuildMI(BB, X86::MOVir8, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
X86::MOVir8, X86::MOVir16, X86::MOVir32
|
||||||
break;
|
};
|
||||||
case Type::ShortTyID:
|
|
||||||
BuildMI(BB, X86::MOVir16, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
if (C->getType()->isSigned()) {
|
||||||
break;
|
ConstantSInt *CSI = cast<ConstantSInt>(C);
|
||||||
case Type::UShortTyID:
|
BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue());
|
||||||
BuildMI(BB, X86::MOVir16, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
} else {
|
||||||
break;
|
ConstantUInt *CUI = cast<ConstantUInt>(C);
|
||||||
case Type::IntTyID:
|
BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
|
||||||
BuildMI(BB, X86::MOVir32, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
}
|
||||||
break;
|
} else {
|
||||||
case Type::UIntTyID:
|
assert(0 && "Type not handled yet!");
|
||||||
BuildMI(BB, X86::MOVir32, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
|
||||||
break;
|
|
||||||
default: assert(0 && "Type not handled yet!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,20 +162,6 @@ void ISel::visitReturnInst(ReturnInst &I) {
|
|||||||
BuildMI(BB, X86::RET, 0);
|
BuildMI(BB, X86::RET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SimpleLog2 - Compute and return Log2 of the input, valid only for inputs 1,
|
|
||||||
/// 2, 4, & 8. Used to convert operand size into dense classes.
|
|
||||||
///
|
|
||||||
static inline unsigned SimpleLog2(unsigned N) {
|
|
||||||
switch (N) {
|
|
||||||
case 1: return 0;
|
|
||||||
case 2: return 1;
|
|
||||||
case 4: return 2;
|
|
||||||
case 8: return 3;
|
|
||||||
default: assert(0 && "Invalid operand to SimpleLog2!");
|
|
||||||
}
|
|
||||||
return 0; // not reached
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
|
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
|
||||||
/// for constant immediate shift values, and for constant immediate
|
/// for constant immediate shift values, and for constant immediate
|
||||||
/// shift values equal to 1. Even the general case is sort of special,
|
/// shift values equal to 1. Even the general case is sort of special,
|
||||||
@@ -169,7 +174,10 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
unsigned DestReg = getReg (I);
|
unsigned DestReg = getReg (I);
|
||||||
bool isRightShift = (I.getOpcode () == Instruction::Shr);
|
bool isRightShift = (I.getOpcode () == Instruction::Shr);
|
||||||
bool isOperandUnsigned = I.getType ()->isUnsigned ();
|
bool isOperandUnsigned = I.getType ()->isUnsigned ();
|
||||||
unsigned OperandClass = SimpleLog2(I.getType()->getPrimitiveSize());
|
unsigned OperandClass = getClass(I.getType());
|
||||||
|
|
||||||
|
if (OperandClass > 2)
|
||||||
|
visitInstruction(I); // Can't handle longs yet!
|
||||||
|
|
||||||
if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
|
if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
|
||||||
{
|
{
|
||||||
@@ -177,79 +185,34 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
|
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
|
||||||
unsigned char shAmt = CUI->getValue();
|
unsigned char shAmt = CUI->getValue();
|
||||||
|
|
||||||
|
// This is a shift right (SHR).
|
||||||
|
static const unsigned SHRUnsignedConstantOperand[] = {
|
||||||
|
X86::SHRir8, X86::SHRir16, X86::SHRir32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift right arithmetic (SAR).
|
||||||
|
static const unsigned SHRSignedConstantOperand[] = {
|
||||||
|
X86::SARir8, X86::SARir16, X86::SARir32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift left (SHL).
|
||||||
|
static const unsigned SHLConstantOperand[] = {
|
||||||
|
X86::SHLir8, X86::SHLir16, X86::SHLir32
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned *OpTab = 0; // Figure out the operand table to use
|
||||||
|
if (isRightShift) {
|
||||||
|
if (isOperandUnsigned)
|
||||||
|
OpTab = SHRUnsignedConstantOperand;
|
||||||
|
else
|
||||||
|
OpTab = SHRSignedConstantOperand;
|
||||||
|
} else {
|
||||||
|
// This is a left shift (SHL).
|
||||||
|
OpTab = SHLConstantOperand;
|
||||||
|
}
|
||||||
|
|
||||||
// Emit: <insn> reg, shamt (shift-by-immediate opcode "ir" form.)
|
// Emit: <insn> reg, shamt (shift-by-immediate opcode "ir" form.)
|
||||||
if (isRightShift)
|
BuildMI(BB, OpTab[OperandClass], 2, DestReg).addReg(Op0r).addZImm(shAmt);
|
||||||
{
|
|
||||||
if (isOperandUnsigned)
|
|
||||||
{
|
|
||||||
// This is a shift right logical (SHR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHRir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHRir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHRir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a shift right arithmetic (SAR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SARir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SARir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SARir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a left shift (SHL).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHLir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHLir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHLir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -263,79 +226,37 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
unsigned Op1r = getReg (I.getOperand (1));
|
unsigned Op1r = getReg (I.getOperand (1));
|
||||||
// Emit: move cl, shiftAmount (put the shift amount in CL.)
|
// Emit: move cl, shiftAmount (put the shift amount in CL.)
|
||||||
BuildMI (BB, X86::MOVrr8, 2, X86::CL).addReg (Op1r);
|
BuildMI (BB, X86::MOVrr8, 2, X86::CL).addReg (Op1r);
|
||||||
|
|
||||||
|
// This is a shift right (SHR).
|
||||||
|
static const unsigned SHRUnsignedOperand[] = {
|
||||||
|
X86::SHRrr8, X86::SHRrr16, X86::SHRrr32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift right arithmetic (SAR).
|
||||||
|
static const unsigned SHRSignedOperand[] = {
|
||||||
|
X86::SARrr8, X86::SARrr16, X86::SARrr32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift left (SHL).
|
||||||
|
static const unsigned SHLOperand[] = {
|
||||||
|
X86::SHLrr8, X86::SHLrr16, X86::SHLrr32
|
||||||
|
};
|
||||||
|
|
||||||
// Emit: <insn> reg, cl (shift-by-CL opcode; "rr" form.)
|
// Emit: <insn> reg, cl (shift-by-CL opcode; "rr" form.)
|
||||||
if (isRightShift)
|
const unsigned *OpTab = 0; // Figure out the operand table to use
|
||||||
{
|
if (isRightShift) {
|
||||||
if (OperandClass)
|
if (isOperandUnsigned)
|
||||||
{
|
OpTab = SHRUnsignedOperand;
|
||||||
// This is a shift right logical (SHR).
|
else
|
||||||
switch (OperandClass)
|
OpTab = SHRSignedOperand;
|
||||||
{
|
} else {
|
||||||
case 0:
|
// This is a left shift (SHL).
|
||||||
BuildMI (BB, X86::SHRrr8, 2,
|
OpTab = SHLOperand;
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
}
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHRrr16, 2,
|
BuildMI (BB, X86::SHLrr32, 2,
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
DestReg).addReg (Op0r).addReg (X86::CL);
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHRrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a shift right arithmetic (SAR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SARrr8, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SARrr16, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SARrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a left shift (SHL).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHLrr8, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHLrr16, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHLrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,25 +265,19 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
void ISel::visitAdd(BinaryOperator &B) {
|
void ISel::visitAdd(BinaryOperator &B) {
|
||||||
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
||||||
unsigned DestReg = getReg(B);
|
unsigned DestReg = getReg(B);
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
|
||||||
switch (B.getType()->getPrimitiveSize()) {
|
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
||||||
case 1: // UByte, SByte
|
|
||||||
BuildMI(BB, X86::ADDrr8, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
||||||
break;
|
visitInstruction(B); // Not handled class yet...
|
||||||
case 2: // UShort, Short
|
|
||||||
BuildMI(BB, X86::ADDrr16, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
||||||
break;
|
|
||||||
case 4: // UInt, Int
|
// For Longs: Here we have a pair of operands each occupying a pair of
|
||||||
BuildMI(BB, X86::ADDrr32, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
// registers. We need to do an ADDrr32 of the least-significant pair
|
||||||
break;
|
// immediately followed by an ADCrr32 (Add with Carry) of the most-significant
|
||||||
case 8: // ULong, Long
|
// pair. I don't know how we are representing these multi-register arguments.
|
||||||
// Here we have a pair of operands each occupying a pair of registers.
|
|
||||||
// We need to do an ADDrr32 of the least-significant pair immediately
|
|
||||||
// followed by an ADCrr32 (Add with Carry) of the most-significant pair.
|
|
||||||
// I don't know how we are representing these multi-register arguments.
|
|
||||||
default:
|
|
||||||
visitInstruction(B); // abort
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -90,6 +90,28 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getClass - Turn a primitive type into a "class" number which is based on the
|
||||||
|
/// size of the type, and whether or not it is floating point.
|
||||||
|
///
|
||||||
|
static inline unsigned getClass(const Type *Ty) {
|
||||||
|
switch (Ty->getPrimitiveID()) {
|
||||||
|
case Type::SByteTyID:
|
||||||
|
case Type::UByteTyID: return 0; // Byte operands are class #0
|
||||||
|
case Type::ShortTyID:
|
||||||
|
case Type::UShortTyID: return 1; // Short operands are class #1
|
||||||
|
case Type::IntTyID:
|
||||||
|
case Type::UIntTyID:
|
||||||
|
case Type::PointerTyID: return 2; // Int's and pointers are class #2
|
||||||
|
|
||||||
|
case Type::LongTyID:
|
||||||
|
case Type::ULongTyID: return 3; // Longs are class #3
|
||||||
|
case Type::FloatTyID: return 4; // Float is class #4
|
||||||
|
case Type::DoubleTyID: return 5; // Doubles are class #5
|
||||||
|
default:
|
||||||
|
assert(0 && "Invalid type to getClass!");
|
||||||
|
return 0; // not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// copyConstantToRegister - Output the instructions required to put the
|
/// copyConstantToRegister - Output the instructions required to put the
|
||||||
/// specified constant into the specified register.
|
/// specified constant into the specified register.
|
||||||
@@ -97,26 +119,23 @@ namespace {
|
|||||||
void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
||||||
assert (!isa<ConstantExpr>(C) && "Constant expressions not yet handled!\n");
|
assert (!isa<ConstantExpr>(C) && "Constant expressions not yet handled!\n");
|
||||||
|
|
||||||
switch (C->getType()->getPrimitiveID()) {
|
if (C->getType()->isIntegral()) {
|
||||||
case Type::SByteTyID:
|
unsigned Class = getClass(C->getType());
|
||||||
BuildMI(BB, X86::MOVir8, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
assert(Class != 3 && "Type not handled yet!");
|
||||||
break;
|
|
||||||
case Type::UByteTyID:
|
static const unsigned IntegralOpcodeTab[] = {
|
||||||
BuildMI(BB, X86::MOVir8, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
X86::MOVir8, X86::MOVir16, X86::MOVir32
|
||||||
break;
|
};
|
||||||
case Type::ShortTyID:
|
|
||||||
BuildMI(BB, X86::MOVir16, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
if (C->getType()->isSigned()) {
|
||||||
break;
|
ConstantSInt *CSI = cast<ConstantSInt>(C);
|
||||||
case Type::UShortTyID:
|
BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addSImm(CSI->getValue());
|
||||||
BuildMI(BB, X86::MOVir16, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
} else {
|
||||||
break;
|
ConstantUInt *CUI = cast<ConstantUInt>(C);
|
||||||
case Type::IntTyID:
|
BuildMI(BB, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
|
||||||
BuildMI(BB, X86::MOVir32, 1, R).addSImm(cast<ConstantSInt>(C)->getValue());
|
}
|
||||||
break;
|
} else {
|
||||||
case Type::UIntTyID:
|
assert(0 && "Type not handled yet!");
|
||||||
BuildMI(BB, X86::MOVir32, 1, R).addZImm(cast<ConstantUInt>(C)->getValue());
|
|
||||||
break;
|
|
||||||
default: assert(0 && "Type not handled yet!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,20 +162,6 @@ void ISel::visitReturnInst(ReturnInst &I) {
|
|||||||
BuildMI(BB, X86::RET, 0);
|
BuildMI(BB, X86::RET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SimpleLog2 - Compute and return Log2 of the input, valid only for inputs 1,
|
|
||||||
/// 2, 4, & 8. Used to convert operand size into dense classes.
|
|
||||||
///
|
|
||||||
static inline unsigned SimpleLog2(unsigned N) {
|
|
||||||
switch (N) {
|
|
||||||
case 1: return 0;
|
|
||||||
case 2: return 1;
|
|
||||||
case 4: return 2;
|
|
||||||
case 8: return 3;
|
|
||||||
default: assert(0 && "Invalid operand to SimpleLog2!");
|
|
||||||
}
|
|
||||||
return 0; // not reached
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
|
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
|
||||||
/// for constant immediate shift values, and for constant immediate
|
/// for constant immediate shift values, and for constant immediate
|
||||||
/// shift values equal to 1. Even the general case is sort of special,
|
/// shift values equal to 1. Even the general case is sort of special,
|
||||||
@@ -169,7 +174,10 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
unsigned DestReg = getReg (I);
|
unsigned DestReg = getReg (I);
|
||||||
bool isRightShift = (I.getOpcode () == Instruction::Shr);
|
bool isRightShift = (I.getOpcode () == Instruction::Shr);
|
||||||
bool isOperandUnsigned = I.getType ()->isUnsigned ();
|
bool isOperandUnsigned = I.getType ()->isUnsigned ();
|
||||||
unsigned OperandClass = SimpleLog2(I.getType()->getPrimitiveSize());
|
unsigned OperandClass = getClass(I.getType());
|
||||||
|
|
||||||
|
if (OperandClass > 2)
|
||||||
|
visitInstruction(I); // Can't handle longs yet!
|
||||||
|
|
||||||
if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
|
if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
|
||||||
{
|
{
|
||||||
@@ -177,79 +185,34 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
|
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
|
||||||
unsigned char shAmt = CUI->getValue();
|
unsigned char shAmt = CUI->getValue();
|
||||||
|
|
||||||
|
// This is a shift right (SHR).
|
||||||
|
static const unsigned SHRUnsignedConstantOperand[] = {
|
||||||
|
X86::SHRir8, X86::SHRir16, X86::SHRir32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift right arithmetic (SAR).
|
||||||
|
static const unsigned SHRSignedConstantOperand[] = {
|
||||||
|
X86::SARir8, X86::SARir16, X86::SARir32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift left (SHL).
|
||||||
|
static const unsigned SHLConstantOperand[] = {
|
||||||
|
X86::SHLir8, X86::SHLir16, X86::SHLir32
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned *OpTab = 0; // Figure out the operand table to use
|
||||||
|
if (isRightShift) {
|
||||||
|
if (isOperandUnsigned)
|
||||||
|
OpTab = SHRUnsignedConstantOperand;
|
||||||
|
else
|
||||||
|
OpTab = SHRSignedConstantOperand;
|
||||||
|
} else {
|
||||||
|
// This is a left shift (SHL).
|
||||||
|
OpTab = SHLConstantOperand;
|
||||||
|
}
|
||||||
|
|
||||||
// Emit: <insn> reg, shamt (shift-by-immediate opcode "ir" form.)
|
// Emit: <insn> reg, shamt (shift-by-immediate opcode "ir" form.)
|
||||||
if (isRightShift)
|
BuildMI(BB, OpTab[OperandClass], 2, DestReg).addReg(Op0r).addZImm(shAmt);
|
||||||
{
|
|
||||||
if (isOperandUnsigned)
|
|
||||||
{
|
|
||||||
// This is a shift right logical (SHR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHRir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHRir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHRir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a shift right arithmetic (SAR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SARir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SARir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SARir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a left shift (SHL).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHLir8, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHLir16, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHLir32, 2,
|
|
||||||
DestReg).addReg (Op0r).addZImm (shAmt);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -263,79 +226,37 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
unsigned Op1r = getReg (I.getOperand (1));
|
unsigned Op1r = getReg (I.getOperand (1));
|
||||||
// Emit: move cl, shiftAmount (put the shift amount in CL.)
|
// Emit: move cl, shiftAmount (put the shift amount in CL.)
|
||||||
BuildMI (BB, X86::MOVrr8, 2, X86::CL).addReg (Op1r);
|
BuildMI (BB, X86::MOVrr8, 2, X86::CL).addReg (Op1r);
|
||||||
|
|
||||||
|
// This is a shift right (SHR).
|
||||||
|
static const unsigned SHRUnsignedOperand[] = {
|
||||||
|
X86::SHRrr8, X86::SHRrr16, X86::SHRrr32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift right arithmetic (SAR).
|
||||||
|
static const unsigned SHRSignedOperand[] = {
|
||||||
|
X86::SARrr8, X86::SARrr16, X86::SARrr32
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a shift left (SHL).
|
||||||
|
static const unsigned SHLOperand[] = {
|
||||||
|
X86::SHLrr8, X86::SHLrr16, X86::SHLrr32
|
||||||
|
};
|
||||||
|
|
||||||
// Emit: <insn> reg, cl (shift-by-CL opcode; "rr" form.)
|
// Emit: <insn> reg, cl (shift-by-CL opcode; "rr" form.)
|
||||||
if (isRightShift)
|
const unsigned *OpTab = 0; // Figure out the operand table to use
|
||||||
{
|
if (isRightShift) {
|
||||||
if (OperandClass)
|
if (isOperandUnsigned)
|
||||||
{
|
OpTab = SHRUnsignedOperand;
|
||||||
// This is a shift right logical (SHR).
|
else
|
||||||
switch (OperandClass)
|
OpTab = SHRSignedOperand;
|
||||||
{
|
} else {
|
||||||
case 0:
|
// This is a left shift (SHL).
|
||||||
BuildMI (BB, X86::SHRrr8, 2,
|
OpTab = SHLOperand;
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
}
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHRrr16, 2,
|
BuildMI (BB, X86::SHLrr32, 2,
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
DestReg).addReg (Op0r).addReg (X86::CL);
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHRrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a shift right arithmetic (SAR).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SARrr8, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SARrr16, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SARrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is a left shift (SHL).
|
|
||||||
switch (OperandClass)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
BuildMI (BB, X86::SHLrr8, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
BuildMI (BB, X86::SHLrr16, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
BuildMI (BB, X86::SHLrr32, 2,
|
|
||||||
DestReg).addReg (Op0r).addReg (X86::CL);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
visitInstruction (I);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,25 +265,19 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
void ISel::visitAdd(BinaryOperator &B) {
|
void ISel::visitAdd(BinaryOperator &B) {
|
||||||
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
||||||
unsigned DestReg = getReg(B);
|
unsigned DestReg = getReg(B);
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
|
||||||
switch (B.getType()->getPrimitiveSize()) {
|
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
||||||
case 1: // UByte, SByte
|
|
||||||
BuildMI(BB, X86::ADDrr8, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
||||||
break;
|
visitInstruction(B); // Not handled class yet...
|
||||||
case 2: // UShort, Short
|
|
||||||
BuildMI(BB, X86::ADDrr16, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
||||||
break;
|
|
||||||
case 4: // UInt, Int
|
// For Longs: Here we have a pair of operands each occupying a pair of
|
||||||
BuildMI(BB, X86::ADDrr32, 2, DestReg).addReg(Op0r).addReg(Op1r);
|
// registers. We need to do an ADDrr32 of the least-significant pair
|
||||||
break;
|
// immediately followed by an ADCrr32 (Add with Carry) of the most-significant
|
||||||
case 8: // ULong, Long
|
// pair. I don't know how we are representing these multi-register arguments.
|
||||||
// Here we have a pair of operands each occupying a pair of registers.
|
|
||||||
// We need to do an ADDrr32 of the least-significant pair immediately
|
|
||||||
// followed by an ADCrr32 (Add with Carry) of the most-significant pair.
|
|
||||||
// I don't know how we are representing these multi-register arguments.
|
|
||||||
default:
|
|
||||||
visitInstruction(B); // abort
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user