Finally, the entire instruction asmprinter is now generated from tblgen, woo!

llvm-svn: 15658
This commit is contained in:
Chris Lattner 2004-08-11 07:02:04 +00:00
parent a0bafce127
commit d1bee6ee12
1 changed files with 8 additions and 296 deletions

View File

@ -438,8 +438,8 @@ static bool isMem(const MachineInstr *MI, unsigned Op) {
if (MI->getOperand(Op).isFrameIndex()) return true; if (MI->getOperand(Op).isFrameIndex()) return true;
if (MI->getOperand(Op).isConstantPoolIndex()) return true; if (MI->getOperand(Op).isConstantPoolIndex()) return true;
return Op+4 <= MI->getNumOperands() && return Op+4 <= MI->getNumOperands() &&
MI->getOperand(Op ).isRegister() &&isScale(MI->getOperand(Op+1)) && MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) &&
MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate(); 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) { void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
assert(isMem(MI, Op) && "Invalid memory reference!"); assert(isMem(MI, Op) && "Invalid memory reference!");
@ -619,289 +608,12 @@ void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
O << "\t# "; O << "\t# ";
} }
if (printInstruction(MI)) // Call the autogenerated instruction printer routines.
return; // Printer was automatically generated bool Handled = printInstruction(MI);
if (!Handled) {
MI->dump(); MI->dump();
abort(); 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;
} }
} }