blob: 29e8b3a5c9c665e6d8eb770613461c852325f2e1 [file] [log] [blame]
Chris Lattner72614082002-10-25 22:55:53 +00001//===-- X86/Printer.cpp - Convert X86 code to human readable rep. ---------===//
2//
3// This file contains a printer that converts from our internal representation
4// of LLVM code to a nice human readable form that is suitable for debuggging.
5//
6//===----------------------------------------------------------------------===//
7
8#include "X86.h"
Brian Gaeke6559bb92002-11-14 22:32:30 +00009#include "X86InstrInfo.h"
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000010#include "llvm/Pass.h"
Brian Gaeke6559bb92002-11-14 22:32:30 +000011#include "llvm/Function.h"
12#include "llvm/Target/TargetMachine.h"
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000013#include "llvm/CodeGen/MachineFunction.h"
Chris Lattnerdbb61c62002-11-17 22:53:13 +000014#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner233ad712002-11-21 01:33:44 +000015#include "Support/Statistic.h"
Chris Lattner72614082002-10-25 22:55:53 +000016
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000017namespace {
18 struct Printer : public FunctionPass {
19 TargetMachine &TM;
20 std::ostream &O;
Chris Lattner72614082002-10-25 22:55:53 +000021
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000022 Printer(TargetMachine &tm, std::ostream &o) : TM(tm), O(o) {}
23
24 bool runOnFunction(Function &F);
25 };
26}
27
Chris Lattnerdbb61c62002-11-17 22:53:13 +000028/// createX86CodePrinterPass - Print out the specified machine code function to
29/// the specified stream. This function should work regardless of whether or
30/// not the function is in SSA form or not.
31///
32Pass *createX86CodePrinterPass(TargetMachine &TM, std::ostream &O) {
33 return new Printer(TM, O);
34}
35
36
Brian Gaeke6559bb92002-11-14 22:32:30 +000037/// runOnFunction - This uses the X86InstructionInfo::print method
38/// to print assembly for each instruction.
39bool Printer::runOnFunction (Function & F)
40{
41 static unsigned bbnumber = 0;
42 MachineFunction & MF = MachineFunction::get (&F);
43 const MachineInstrInfo & MII = TM.getInstrInfo ();
Brian Gaeke6559bb92002-11-14 22:32:30 +000044
Chris Lattner927dd092002-11-17 23:20:37 +000045 O << "; x86 printing only sorta implemented so far!\n";
Brian Gaeke6559bb92002-11-14 22:32:30 +000046
47 // Print out labels for the function.
48 O << "\t.globl\t" << F.getName () << "\n";
49 O << "\t.type\t" << F.getName () << ", @function\n";
50 O << F.getName () << ":\n";
51
52 // Print out code for the function.
53 for (MachineFunction::const_iterator bb_i = MF.begin (), bb_e = MF.end ();
54 bb_i != bb_e; ++bb_i)
55 {
56 // Print a label for the basic block.
57 O << ".BB" << bbnumber++ << ":\n";
58 for (MachineBasicBlock::const_iterator i_i = bb_i->begin (), i_e =
59 bb_i->end (); i_i != i_e; ++i_i)
60 {
61 // Print the assembly for the instruction.
62 O << "\t";
Chris Lattner927dd092002-11-17 23:20:37 +000063 MII.print(*i_i, O, TM);
Brian Gaeke6559bb92002-11-14 22:32:30 +000064 }
65 }
66
67 // We didn't modify anything.
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000068 return false;
69}
70
Chris Lattnerf9f60882002-11-18 06:56:51 +000071static void printOp(std::ostream &O, const MachineOperand &MO,
72 const MRegisterInfo &RI) {
73 switch (MO.getType()) {
74 case MachineOperand::MO_VirtualRegister:
Misha Brukmane1f0d812002-11-20 18:56:41 +000075 case MachineOperand::MO_MachineRegister:
Chris Lattnerf9f60882002-11-18 06:56:51 +000076 if (MO.getReg() < MRegisterInfo::FirstVirtualRegister)
77 O << RI.get(MO.getReg()).Name;
78 else
79 O << "%reg" << MO.getReg();
80 return;
81
82 default:
83 O << "<unknown op ty>"; return;
84 }
85}
86
87static inline void toHexDigit(std::ostream &O, unsigned char V) {
88 if (V >= 10)
89 O << (char)('A'+V-10);
90 else
91 O << (char)('0'+V);
92}
93
94static std::ostream &toHex(std::ostream &O, unsigned char V) {
95 toHexDigit(O, V >> 4);
96 toHexDigit(O, V & 0xF);
97 return O;
98}
99
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000100
Chris Lattner644e1ab2002-11-21 00:30:01 +0000101static bool isReg(const MachineOperand &MO) {
102 return MO.getType()==MachineOperand::MO_VirtualRegister ||
103 MO.getType()==MachineOperand::MO_MachineRegister;
104}
105
106
Chris Lattner233ad712002-11-21 01:33:44 +0000107// getX86RegNum - This function maps LLVM register identifiers to their X86
108// specific numbering, which is used in various places encoding instructions.
109//
110static unsigned getX86RegNum(unsigned RegNo) {
111 switch(RegNo) {
112 case X86::EAX: case X86::AX: case X86::AL: return 0;
113 case X86::ECX: case X86::CX: case X86::CL: return 1;
114 case X86::EDX: case X86::DX: case X86::DL: return 2;
115 case X86::EBX: case X86::BX: case X86::BL: return 3;
116 case X86::ESP: case X86::SP: case X86::AH: return 4;
117 case X86::EBP: case X86::BP: case X86::CH: return 5;
118 case X86::ESI: case X86::SI: case X86::DH: return 6;
119 case X86::EDI: case X86::DI: case X86::BH: return 7;
120 default:
121 assert(RegNo >= MRegisterInfo::FirstVirtualRegister &&
122 "Unknown physical register!");
123 DEBUG(std::cerr << "Register allocator hasn't allocated " << RegNo
124 << " correctly yet!\n");
125 return 0;
126 }
127}
128
129inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
130 unsigned RM) {
131 assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!");
132 return RM | (RegOpcode << 3) | (Mod << 6);
133}
134
135static unsigned char regModRMByte(unsigned ModRMReg, unsigned RegOpcodeField) {
136 return ModRMByte(3, RegOpcodeField, getX86RegNum(ModRMReg));
137}
138
139
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000140// print - Print out an x86 instruction in intel syntax
Chris Lattner927dd092002-11-17 23:20:37 +0000141void X86InstrInfo::print(const MachineInstr *MI, std::ostream &O,
142 const TargetMachine &TM) const {
Chris Lattnerf9f60882002-11-18 06:56:51 +0000143 unsigned Opcode = MI->getOpcode();
144 const MachineInstrDescriptor &Desc = get(Opcode);
145
Chris Lattner233ad712002-11-21 01:33:44 +0000146 // Print instruction prefixes if neccesary
147
148 if (Desc.TSFlags & X86II::OpSize) O << "66 "; // Operand size...
149 if (Desc.TSFlags & X86II::TB) O << "0F "; // Two-byte opcode prefix
Chris Lattnerf9f60882002-11-18 06:56:51 +0000150
151 switch (Desc.TSFlags & X86II::FormMask) {
152 case X86II::OtherFrm:
Chris Lattner233ad712002-11-21 01:33:44 +0000153 O << "\t\t";
Chris Lattnerf9f60882002-11-18 06:56:51 +0000154 O << "-"; MI->print(O, TM);
155 break;
156 case X86II::RawFrm:
Chris Lattner233ad712002-11-21 01:33:44 +0000157 toHex(O, getBaseOpcodeFor(Opcode)) << "\t\t";
Chris Lattnerf9f60882002-11-18 06:56:51 +0000158 O << getName(MI->getOpCode()) << " ";
159
160 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
161 if (i) O << ", ";
162 printOp(O, MI->getOperand(i), RI);
163 }
164 O << "\n";
165 return;
166
167
168 case X86II::AddRegFrm:
Chris Lattner233ad712002-11-21 01:33:44 +0000169 O << "\t\t-"; MI->print(O, TM); break;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000170
Chris Lattner233ad712002-11-21 01:33:44 +0000171 case X86II::MRMDestReg: {
Chris Lattnerf9f60882002-11-18 06:56:51 +0000172 // There are two acceptable forms of MRMDestReg instructions, those with 3
173 // and 2 operands:
174 //
175 // 3 Operands: in this form, the first two registers (the destination, and
176 // the first operand) should be the same, post register allocation. The 3rd
177 // operand is an additional input. This should be for things like add
178 // instructions.
179 //
180 // 2 Operands: this is for things like mov that do not read a second input
181 //
Chris Lattner644e1ab2002-11-21 00:30:01 +0000182 assert(isReg(MI->getOperand(0)) &&
183 (MI->getNumOperands() == 2 ||
184 (MI->getNumOperands() == 3 && isReg(MI->getOperand(1)))) &&
185 isReg(MI->getOperand(MI->getNumOperands()-1))
Misha Brukmane1f0d812002-11-20 18:56:41 +0000186 && "Bad format for MRMDestReg!");
Chris Lattnerf9f60882002-11-18 06:56:51 +0000187 if (MI->getNumOperands() == 3 &&
188 MI->getOperand(0).getReg() != MI->getOperand(1).getReg())
189 O << "**";
190
Chris Lattner233ad712002-11-21 01:33:44 +0000191 toHex(O, getBaseOpcodeFor(Opcode)) << " ";
192 unsigned ModRMReg = MI->getOperand(0).getReg();
193 unsigned ExtraReg = MI->getOperand(MI->getNumOperands()-1).getReg();
194 toHex(O, regModRMByte(ModRMReg, getX86RegNum(ExtraReg)));
195
196 O << "\t\t";
Chris Lattnerf9f60882002-11-18 06:56:51 +0000197 O << getName(MI->getOpCode()) << " ";
198 printOp(O, MI->getOperand(0), RI);
199 O << ", ";
200 printOp(O, MI->getOperand(MI->getNumOperands()-1), RI);
201 O << "\n";
202 return;
Chris Lattner233ad712002-11-21 01:33:44 +0000203 }
204 case X86II::MRMSrcReg: {
Chris Lattner644e1ab2002-11-21 00:30:01 +0000205 // There is a two forms that are acceptable for MRMSrcReg instructions,
206 // those with 3 and 2 operands:
207 //
208 // 3 Operands: in this form, the last register (the second input) is the
209 // ModR/M input. The first two operands should be the same, post register
210 // allocation. This is for things like: add r32, r/m32
211 //
212 // 2 Operands: this is for things like mov that do not read a second input
213 //
214 assert(isReg(MI->getOperand(0)) &&
215 isReg(MI->getOperand(1)) &&
216 (MI->getNumOperands() == 2 ||
217 (MI->getNumOperands() == 3 && isReg(MI->getOperand(2))))
218 && "Bad format for MRMDestReg!");
219 if (MI->getNumOperands() == 3 &&
220 MI->getOperand(0).getReg() != MI->getOperand(1).getReg())
221 O << "**";
222
Chris Lattner233ad712002-11-21 01:33:44 +0000223 toHex(O, getBaseOpcodeFor(Opcode)) << " ";
224 unsigned ModRMReg = MI->getOperand(MI->getNumOperands()-1).getReg();
225 unsigned ExtraReg = MI->getOperand(0).getReg();
226 toHex(O, regModRMByte(ModRMReg, getX86RegNum(ExtraReg)));
227
Chris Lattner644e1ab2002-11-21 00:30:01 +0000228 O << "\t";
229 O << getName(MI->getOpCode()) << " ";
230 printOp(O, MI->getOperand(0), RI);
231 O << ", ";
232 printOp(O, MI->getOperand(MI->getNumOperands()-1), RI);
233 O << "\n";
234 return;
Chris Lattner233ad712002-11-21 01:33:44 +0000235 }
Chris Lattner644e1ab2002-11-21 00:30:01 +0000236 case X86II::MRMDestMem:
Chris Lattnerf9f60882002-11-18 06:56:51 +0000237 case X86II::MRMSrcMem:
238 default:
Chris Lattner233ad712002-11-21 01:33:44 +0000239 O << "\t\t-"; MI->print(O, TM); break;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000240 }
Chris Lattner72614082002-10-25 22:55:53 +0000241}