mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Finally, the entire instruction asmprinter is now generated from tblgen, woo!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15658 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e4ead0ce62
commit
2a998bdc7c
@ -438,8 +438,8 @@ static bool isMem(const MachineInstr *MI, unsigned Op) {
|
||||
if (MI->getOperand(Op).isFrameIndex()) return true;
|
||||
if (MI->getOperand(Op).isConstantPoolIndex()) return true;
|
||||
return Op+4 <= MI->getNumOperands() &&
|
||||
MI->getOperand(Op ).isRegister() &&isScale(MI->getOperand(Op+1)) &&
|
||||
MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate();
|
||||
MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) &&
|
||||
MI->getOperand(Op+2).isRegister() && MI->getOperand(Op+3).isImmediate();
|
||||
}
|
||||
|
||||
|
||||
@ -490,17 +490,6 @@ void X86AsmPrinter::printOp(const MachineOperand &MO,
|
||||
}
|
||||
}
|
||||
|
||||
static const char* const sizePtr(const TargetInstrDescriptor &Desc) {
|
||||
switch (Desc.TSFlags & X86II::MemMask) {
|
||||
default: assert(0 && "Unknown arg size!");
|
||||
case X86II::Mem8: return "BYTE PTR";
|
||||
case X86II::Mem16: return "WORD PTR";
|
||||
case X86II::Mem32: return "DWORD PTR";
|
||||
case X86II::Mem64: return "QWORD PTR";
|
||||
case X86II::Mem80: return "XWORD PTR";
|
||||
}
|
||||
}
|
||||
|
||||
void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
|
||||
assert(isMem(MI, Op) && "Invalid memory reference!");
|
||||
|
||||
@ -619,289 +608,12 @@ void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
O << "\t# ";
|
||||
}
|
||||
|
||||
if (printInstruction(MI))
|
||||
return; // Printer was automatically generated
|
||||
|
||||
// Call the autogenerated instruction printer routines.
|
||||
bool Handled = printInstruction(MI);
|
||||
if (!Handled) {
|
||||
MI->dump();
|
||||
assert(0 && "Do not know how to print this instruction!");
|
||||
abort();
|
||||
|
||||
unsigned Opcode = MI->getOpcode();
|
||||
const TargetInstrInfo &TII = *TM.getInstrInfo();
|
||||
const TargetInstrDescriptor &Desc = TII.get(Opcode);
|
||||
|
||||
switch (Desc.TSFlags & X86II::FormMask) {
|
||||
case X86II::Pseudo:
|
||||
// Print pseudo-instructions as comments; either they should have been
|
||||
// turned into real instructions by now, or they don't need to be
|
||||
// seen by the assembler (e.g., IMPLICIT_USEs.)
|
||||
O << "# ";
|
||||
if (Opcode == X86::PHI) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = phi ";
|
||||
for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) {
|
||||
if (i != 1) O << ", ";
|
||||
O << "[";
|
||||
printOp(MI->getOperand(i));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(i+1));
|
||||
O << "]";
|
||||
}
|
||||
} else {
|
||||
unsigned i = 0;
|
||||
if (MI->getNumOperands() && MI->getOperand(0).isDef()) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = ";
|
||||
++i;
|
||||
}
|
||||
O << TII.getName(MI->getOpcode());
|
||||
|
||||
for (unsigned e = MI->getNumOperands(); i != e; ++i) {
|
||||
O << " ";
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
printOp(MI->getOperand(i));
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
}
|
||||
}
|
||||
O << "\n";
|
||||
return;
|
||||
|
||||
case X86II::RawFrm:
|
||||
{
|
||||
// The accepted forms of Raw instructions are:
|
||||
// 1. jmp foo - MachineBasicBlock operand
|
||||
// 2. call bar - GlobalAddress Operand or External Symbol Operand
|
||||
// 3. in AL, imm - Immediate operand
|
||||
//
|
||||
assert(MI->getNumOperands() == 1 &&
|
||||
(MI->getOperand(0).isMachineBasicBlock() ||
|
||||
MI->getOperand(0).isGlobalAddress() ||
|
||||
MI->getOperand(0).isExternalSymbol() ||
|
||||
MI->getOperand(0).isImmediate()) &&
|
||||
"Illegal raw instruction!");
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
|
||||
bool LeadingComma = false;
|
||||
if (MI->getNumOperands() == 1) {
|
||||
printOp(MI->getOperand(0), true); // Don't print "OFFSET"...
|
||||
LeadingComma = true;
|
||||
}
|
||||
printImplUsesAfter(Desc, LeadingComma);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::AddRegFrm: {
|
||||
// There are currently two forms of acceptable AddRegFrm instructions.
|
||||
// Either the instruction JUST takes a single register (like inc, dec, etc),
|
||||
// or it takes a register and an immediate of the same size as the register
|
||||
// (move immediate f.e.). Note that this immediate value might be stored as
|
||||
// an LLVM value, to represent, for example, loading the address of a global
|
||||
// into a register. The initial register might be duplicated if this is a
|
||||
// M_2_ADDR_REG instruction
|
||||
//
|
||||
assert(MI->getOperand(0).isRegister() &&
|
||||
(MI->getNumOperands() == 1 ||
|
||||
(MI->getNumOperands() == 2 &&
|
||||
(MI->getOperand(1).getVRegValueOrNull() ||
|
||||
MI->getOperand(1).isImmediate() ||
|
||||
MI->getOperand(1).isRegister() ||
|
||||
MI->getOperand(1).isGlobalAddress() ||
|
||||
MI->getOperand(1).isExternalSymbol()))) &&
|
||||
"Illegal form for AddRegFrm instruction!");
|
||||
|
||||
unsigned Reg = MI->getOperand(0).getReg();
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
|
||||
printOp(MI->getOperand(0));
|
||||
if (MI->getNumOperands() == 2 &&
|
||||
(!MI->getOperand(1).isRegister() ||
|
||||
MI->getOperand(1).getVRegValueOrNull() ||
|
||||
MI->getOperand(1).isGlobalAddress() ||
|
||||
MI->getOperand(1).isExternalSymbol())) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(1));
|
||||
}
|
||||
printImplUsesAfter(Desc);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
case X86II::MRMDestReg: {
|
||||
// There are three forms of MRMDestReg instructions, those with 2
|
||||
// or 3 operands:
|
||||
//
|
||||
// 2 Operands: this is for things like mov that do not read a
|
||||
// second input.
|
||||
//
|
||||
// 2 Operands: two address instructions which def&use the first
|
||||
// argument and use the second as input.
|
||||
//
|
||||
// 3 Operands: in this form, two address instructions are the same
|
||||
// as in 2 but have a constant argument as well.
|
||||
//
|
||||
bool isTwoAddr = TII.isTwoAddrInstr(Opcode);
|
||||
assert(MI->getOperand(0).isRegister() &&
|
||||
(MI->getNumOperands() == 2 ||
|
||||
(MI->getNumOperands() == 3 && MI->getOperand(2).isImmediate()))
|
||||
&& "Bad format for MRMDestReg!");
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
printOp(MI->getOperand(0));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(1));
|
||||
if (MI->getNumOperands() == 3) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(2));
|
||||
}
|
||||
printImplUsesAfter(Desc);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::MRMDestMem: {
|
||||
// These instructions are the same as MRMDestReg, but instead of having a
|
||||
// register reference for the mod/rm field, it's a memory reference.
|
||||
//
|
||||
assert(isMem(MI, 0) &&
|
||||
(MI->getNumOperands() == 4+1 ||
|
||||
(MI->getNumOperands() == 4+2 && MI->getOperand(5).isImmediate()))
|
||||
&& "Bad format for MRMDestMem!");
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " " << sizePtr(Desc) << " ";
|
||||
printMemReference(MI, 0);
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(4));
|
||||
if (MI->getNumOperands() == 4+2) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(5));
|
||||
}
|
||||
printImplUsesAfter(Desc);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::MRMSrcReg: {
|
||||
// There are three forms that are acceptable for MRMSrcReg
|
||||
// instructions, those with 2 or 3 operands:
|
||||
//
|
||||
// 2 Operands: this is for things like mov that do not read a
|
||||
// second input.
|
||||
//
|
||||
// 2 Operands: in this form, the last register is the ModR/M
|
||||
// input. The first operand is a def&use. This is for things
|
||||
// like: add r32, r/m32
|
||||
//
|
||||
// 3 Operands: in this form, we can have 'INST R1, R2, imm', which is used
|
||||
// for instructions like the IMULrri instructions.
|
||||
//
|
||||
//
|
||||
assert(MI->getOperand(0).isRegister() &&
|
||||
MI->getOperand(1).isRegister() &&
|
||||
(MI->getNumOperands() == 2 ||
|
||||
(MI->getNumOperands() == 3 &&
|
||||
(MI->getOperand(2).isImmediate())))
|
||||
&& "Bad format for MRMSrcReg!");
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
printOp(MI->getOperand(0));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(1));
|
||||
if (MI->getNumOperands() == 3) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(2));
|
||||
}
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::MRMSrcMem: {
|
||||
// These instructions are the same as MRMSrcReg, but instead of having a
|
||||
// register reference for the mod/rm field, it's a memory reference.
|
||||
//
|
||||
assert(MI->getOperand(0).isRegister() &&
|
||||
((MI->getNumOperands() == 1+4 && isMem(MI, 1)) ||
|
||||
(MI->getNumOperands() == 2+4 && MI->getOperand(5).isImmediate() &&
|
||||
isMem(MI, 1)))
|
||||
&& "Bad format for MRMSrcMem!");
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
printOp(MI->getOperand(0));
|
||||
O << ", " << sizePtr(Desc) << " ";
|
||||
printMemReference(MI, 1);
|
||||
if (MI->getNumOperands() == 2+4) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(5));
|
||||
}
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::MRM0r: case X86II::MRM1r:
|
||||
case X86II::MRM2r: case X86II::MRM3r:
|
||||
case X86II::MRM4r: case X86II::MRM5r:
|
||||
case X86II::MRM6r: case X86II::MRM7r: {
|
||||
// In this form, the following are valid formats:
|
||||
// 1. sete r
|
||||
// 2. cmp reg, immediate
|
||||
// 2. shl rdest, rinput <implicit CL or 1>
|
||||
// 3. sbb rdest, rinput, immediate [rdest = rinput]
|
||||
//
|
||||
assert(MI->getNumOperands() > 0 && MI->getNumOperands() < 4 &&
|
||||
MI->getOperand(0).isRegister() && "Bad MRMSxR format!");
|
||||
assert((MI->getNumOperands() != 2 ||
|
||||
MI->getOperand(1).isRegister() || MI->getOperand(1).isImmediate())&&
|
||||
"Bad MRMSxR format!");
|
||||
assert((MI->getNumOperands() < 3 ||
|
||||
(MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate())) &&
|
||||
"Bad MRMSxR format!");
|
||||
|
||||
if (MI->getNumOperands() > 1 && MI->getOperand(1).isRegister() &&
|
||||
MI->getOperand(0).getReg() != MI->getOperand(1).getReg())
|
||||
O << "**";
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
printOp(MI->getOperand(0));
|
||||
if (MI->getOperand(MI->getNumOperands()-1).isImmediate()) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(MI->getNumOperands()-1));
|
||||
}
|
||||
printImplUsesAfter(Desc);
|
||||
O << "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::MRM0m: case X86II::MRM1m:
|
||||
case X86II::MRM2m: case X86II::MRM3m:
|
||||
case X86II::MRM4m: case X86II::MRM5m:
|
||||
case X86II::MRM6m: case X86II::MRM7m: {
|
||||
// In this form, the following are valid formats:
|
||||
// 1. sete [m]
|
||||
// 2. cmp [m], immediate
|
||||
// 2. shl [m], rinput <implicit CL or 1>
|
||||
// 3. sbb [m], immediate
|
||||
//
|
||||
assert(MI->getNumOperands() >= 4 && MI->getNumOperands() <= 5 &&
|
||||
isMem(MI, 0) && "Bad MRMSxM format!");
|
||||
assert((MI->getNumOperands() != 5 ||
|
||||
(MI->getOperand(4).isImmediate() ||
|
||||
MI->getOperand(4).isGlobalAddress())) &&
|
||||
"Bad MRMSxM format!");
|
||||
|
||||
const MachineOperand &Op3 = MI->getOperand(3);
|
||||
|
||||
O << TII.getName(MI->getOpcode()) << " ";
|
||||
O << sizePtr(Desc) << " ";
|
||||
printMemReference(MI, 0);
|
||||
if (MI->getNumOperands() == 5) {
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(4));
|
||||
}
|
||||
printImplUsesAfter(Desc);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
default:
|
||||
O << "\tUNKNOWN FORM:\t\t-"; MI->print(O, &TM); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user