mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-23 14:25:07 +00:00
shuffle code around a bit, implement and, or, xor
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4502 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -55,11 +55,23 @@ namespace {
|
|||||||
// Visitation methods for various instructions. These methods simply emit
|
// Visitation methods for various instructions. These methods simply emit
|
||||||
// fixed X86 code for each instruction.
|
// fixed X86 code for each instruction.
|
||||||
//
|
//
|
||||||
void visitPHINode(PHINode &I);
|
|
||||||
void visitReturnInst(ReturnInst &RI);
|
void visitReturnInst(ReturnInst &RI);
|
||||||
void visitBranchInst(BranchInst &BI);
|
void visitBranchInst(BranchInst &BI);
|
||||||
|
|
||||||
|
// Arithmetic operators
|
||||||
void visitAdd(BinaryOperator &B);
|
void visitAdd(BinaryOperator &B);
|
||||||
|
|
||||||
|
// Bitwise operators
|
||||||
|
void visitAnd(BinaryOperator &B) { visitBitwise(B, 0); }
|
||||||
|
void visitOr (BinaryOperator &B) { visitBitwise(B, 1); }
|
||||||
|
void visitXor(BinaryOperator &B) { visitBitwise(B, 2); }
|
||||||
|
void visitBitwise(BinaryOperator &B, unsigned OpcodeClass);
|
||||||
|
|
||||||
|
// Binary comparison operators
|
||||||
|
|
||||||
|
// Other operators
|
||||||
void visitShiftInst(ShiftInst &I);
|
void visitShiftInst(ShiftInst &I);
|
||||||
|
void visitPHINode(PHINode &I);
|
||||||
|
|
||||||
void visitInstruction(Instruction &I) {
|
void visitInstruction(Instruction &I) {
|
||||||
std::cerr << "Cannot instruction select: " << I;
|
std::cerr << "Cannot instruction select: " << I;
|
||||||
@@ -142,19 +154,6 @@ void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
|
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
|
||||||
@@ -192,6 +191,50 @@ void ISel::visitBranchInst(BranchInst &BI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction.
|
||||||
|
void ISel::visitAdd(BinaryOperator &B) {
|
||||||
|
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
||||||
|
unsigned DestReg = getReg(B);
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
|
||||||
|
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
||||||
|
|
||||||
|
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
||||||
|
visitInstruction(B); // Not handled class yet...
|
||||||
|
|
||||||
|
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
||||||
|
|
||||||
|
// For Longs: 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.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// visitBitwise - Implement the three bitwise operators for integral types...
|
||||||
|
/// OperatorClass is one of: 0 for And, 1 for Or, 2 for Xor.
|
||||||
|
void ISel::visitBitwise(BinaryOperator &B, unsigned OperatorClass) {
|
||||||
|
if (B.getType() == Type::BoolTy) // FIXME: Handle bools
|
||||||
|
visitInstruction(B);
|
||||||
|
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
if (Class > 2) // FIXME: Handle longs
|
||||||
|
visitInstruction(B);
|
||||||
|
|
||||||
|
static const unsigned OpcodeTab[][4] = {
|
||||||
|
{ X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND
|
||||||
|
{ X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR
|
||||||
|
{ X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned Opcode = OpcodeTab[OperatorClass][Class];
|
||||||
|
unsigned Op0r = getReg(B.getOperand(0));
|
||||||
|
unsigned Op1r = getReg(B.getOperand(1));
|
||||||
|
BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// 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,
|
||||||
@@ -255,28 +298,21 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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));
|
||||||
|
|
||||||
/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction.
|
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
|
||||||
void ISel::visitAdd(BinaryOperator &B) {
|
// FIXME: This will put constants after the PHI nodes in the block, which
|
||||||
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
// is invalid. They should be put inline into the PHI node eventually.
|
||||||
unsigned DestReg = getReg(B);
|
//
|
||||||
unsigned Class = getClass(B.getType());
|
MI->addRegOperand(getReg(PN.getIncomingValue(i)));
|
||||||
|
MI->addPCDispOperand(PN.getIncomingBlock(i));
|
||||||
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
}
|
||||||
|
|
||||||
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
|
||||||
visitInstruction(B); // Not handled class yet...
|
|
||||||
|
|
||||||
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
|
||||||
|
|
||||||
// For Longs: 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
||||||
/// into a machine code representation is a very simple peep-hole fashion. The
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
||||||
/// generated code sucks but the implementation is nice and simple.
|
/// generated code sucks but the implementation is nice and simple.
|
||||||
|
@@ -55,11 +55,23 @@ namespace {
|
|||||||
// Visitation methods for various instructions. These methods simply emit
|
// Visitation methods for various instructions. These methods simply emit
|
||||||
// fixed X86 code for each instruction.
|
// fixed X86 code for each instruction.
|
||||||
//
|
//
|
||||||
void visitPHINode(PHINode &I);
|
|
||||||
void visitReturnInst(ReturnInst &RI);
|
void visitReturnInst(ReturnInst &RI);
|
||||||
void visitBranchInst(BranchInst &BI);
|
void visitBranchInst(BranchInst &BI);
|
||||||
|
|
||||||
|
// Arithmetic operators
|
||||||
void visitAdd(BinaryOperator &B);
|
void visitAdd(BinaryOperator &B);
|
||||||
|
|
||||||
|
// Bitwise operators
|
||||||
|
void visitAnd(BinaryOperator &B) { visitBitwise(B, 0); }
|
||||||
|
void visitOr (BinaryOperator &B) { visitBitwise(B, 1); }
|
||||||
|
void visitXor(BinaryOperator &B) { visitBitwise(B, 2); }
|
||||||
|
void visitBitwise(BinaryOperator &B, unsigned OpcodeClass);
|
||||||
|
|
||||||
|
// Binary comparison operators
|
||||||
|
|
||||||
|
// Other operators
|
||||||
void visitShiftInst(ShiftInst &I);
|
void visitShiftInst(ShiftInst &I);
|
||||||
|
void visitPHINode(PHINode &I);
|
||||||
|
|
||||||
void visitInstruction(Instruction &I) {
|
void visitInstruction(Instruction &I) {
|
||||||
std::cerr << "Cannot instruction select: " << I;
|
std::cerr << "Cannot instruction select: " << I;
|
||||||
@@ -142,19 +154,6 @@ void ISel::copyConstantToRegister(Constant *C, unsigned R) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
|
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
|
||||||
@@ -192,6 +191,50 @@ void ISel::visitBranchInst(BranchInst &BI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction.
|
||||||
|
void ISel::visitAdd(BinaryOperator &B) {
|
||||||
|
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
||||||
|
unsigned DestReg = getReg(B);
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
|
||||||
|
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
||||||
|
|
||||||
|
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
||||||
|
visitInstruction(B); // Not handled class yet...
|
||||||
|
|
||||||
|
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
||||||
|
|
||||||
|
// For Longs: 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.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// visitBitwise - Implement the three bitwise operators for integral types...
|
||||||
|
/// OperatorClass is one of: 0 for And, 1 for Or, 2 for Xor.
|
||||||
|
void ISel::visitBitwise(BinaryOperator &B, unsigned OperatorClass) {
|
||||||
|
if (B.getType() == Type::BoolTy) // FIXME: Handle bools
|
||||||
|
visitInstruction(B);
|
||||||
|
|
||||||
|
unsigned Class = getClass(B.getType());
|
||||||
|
if (Class > 2) // FIXME: Handle longs
|
||||||
|
visitInstruction(B);
|
||||||
|
|
||||||
|
static const unsigned OpcodeTab[][4] = {
|
||||||
|
{ X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND
|
||||||
|
{ X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR
|
||||||
|
{ X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned Opcode = OpcodeTab[OperatorClass][Class];
|
||||||
|
unsigned Op0r = getReg(B.getOperand(0));
|
||||||
|
unsigned Op1r = getReg(B.getOperand(1));
|
||||||
|
BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// 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,
|
||||||
@@ -255,28 +298,21 @@ ISel::visitShiftInst (ShiftInst & I)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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));
|
||||||
|
|
||||||
/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction.
|
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
|
||||||
void ISel::visitAdd(BinaryOperator &B) {
|
// FIXME: This will put constants after the PHI nodes in the block, which
|
||||||
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
|
// is invalid. They should be put inline into the PHI node eventually.
|
||||||
unsigned DestReg = getReg(B);
|
//
|
||||||
unsigned Class = getClass(B.getType());
|
MI->addRegOperand(getReg(PN.getIncomingValue(i)));
|
||||||
|
MI->addPCDispOperand(PN.getIncomingBlock(i));
|
||||||
static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 };
|
}
|
||||||
|
|
||||||
if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0]))
|
|
||||||
visitInstruction(B); // Not handled class yet...
|
|
||||||
|
|
||||||
BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r);
|
|
||||||
|
|
||||||
// For Longs: 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
||||||
/// into a machine code representation is a very simple peep-hole fashion. The
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
||||||
/// generated code sucks but the implementation is nice and simple.
|
/// generated code sucks but the implementation is nice and simple.
|
||||||
|
@@ -48,7 +48,18 @@ I(MOVir32 , "movl", 0, 0) // R32 = imm32 B8+ rd
|
|||||||
// Arithmetic instructions
|
// Arithmetic instructions
|
||||||
I(ADDrr8 , "addb", 0, 0) // R8 += R8 00/r
|
I(ADDrr8 , "addb", 0, 0) // R8 += R8 00/r
|
||||||
I(ADDrr16 , "addw", 0, 0) // R16 += R16 01/r
|
I(ADDrr16 , "addw", 0, 0) // R16 += R16 01/r
|
||||||
I(ADDrr32 , "addl", 0, 0) // R32 += R32 02/r
|
I(ADDrr32 , "addl", 0, 0) // R32 += R32 01/r
|
||||||
|
|
||||||
|
// Logical operators
|
||||||
|
I(ANDrr8 , "andb", 0, 0) // R8 &= R8 20/r
|
||||||
|
I(ANDrr16 , "andw", 0, 0) // R16 &= R16 21/r
|
||||||
|
I(ANDrr32 , "andl", 0, 0) // R32 &= R32 21/r
|
||||||
|
I(ORrr8 , "orb", 0, 0) // R8 |= R8 08/r
|
||||||
|
I(ORrr16 , "orw", 0, 0) // R16 |= R16 09/r
|
||||||
|
I(ORrr32 , "orl", 0, 0) // R32 |= R32 09/r
|
||||||
|
I(XORrr8 , "xorb", 0, 0) // R8 ^= R8 30/r
|
||||||
|
I(XORrr16 , "xorw", 0, 0) // R16 ^= R16 31/r
|
||||||
|
I(XORrr32 , "xorl", 0, 0) // R32 ^= R32 31/r
|
||||||
|
|
||||||
// Shift instructions
|
// Shift instructions
|
||||||
I(SHLrr8 , "shlb", 0, 0) // R8 <<= cl D2/4
|
I(SHLrr8 , "shlb", 0, 0) // R8 <<= cl D2/4
|
||||||
|
Reference in New Issue
Block a user