]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This class prints an Mips MCInst to a .s file. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #define DEBUG_TYPE "asm-printer" | |
15 | #include "MipsInstPrinter.h" | |
16 | #include "MipsInstrInfo.h" | |
17 | #include "llvm/ADT/StringExtras.h" | |
18 | #include "llvm/MC/MCExpr.h" | |
19 | #include "llvm/MC/MCInst.h" | |
20 | #include "llvm/MC/MCInstrInfo.h" | |
21 | #include "llvm/MC/MCSymbol.h" | |
22 | #include "llvm/Support/ErrorHandling.h" | |
23 | #include "llvm/Support/raw_ostream.h" | |
24 | using namespace llvm; | |
25 | ||
970d7e83 | 26 | #define PRINT_ALIAS_INSTR |
223e47cc LB |
27 | #include "MipsGenAsmWriter.inc" |
28 | ||
29 | const char* Mips::MipsFCCToString(Mips::CondCode CC) { | |
30 | switch (CC) { | |
31 | case FCOND_F: | |
32 | case FCOND_T: return "f"; | |
33 | case FCOND_UN: | |
34 | case FCOND_OR: return "un"; | |
35 | case FCOND_OEQ: | |
36 | case FCOND_UNE: return "eq"; | |
37 | case FCOND_UEQ: | |
38 | case FCOND_ONE: return "ueq"; | |
39 | case FCOND_OLT: | |
40 | case FCOND_UGE: return "olt"; | |
41 | case FCOND_ULT: | |
42 | case FCOND_OGE: return "ult"; | |
43 | case FCOND_OLE: | |
44 | case FCOND_UGT: return "ole"; | |
45 | case FCOND_ULE: | |
46 | case FCOND_OGT: return "ule"; | |
47 | case FCOND_SF: | |
48 | case FCOND_ST: return "sf"; | |
49 | case FCOND_NGLE: | |
50 | case FCOND_GLE: return "ngle"; | |
51 | case FCOND_SEQ: | |
52 | case FCOND_SNE: return "seq"; | |
53 | case FCOND_NGL: | |
54 | case FCOND_GL: return "ngl"; | |
55 | case FCOND_LT: | |
56 | case FCOND_NLT: return "lt"; | |
57 | case FCOND_NGE: | |
58 | case FCOND_GE: return "nge"; | |
59 | case FCOND_LE: | |
60 | case FCOND_NLE: return "le"; | |
61 | case FCOND_NGT: | |
62 | case FCOND_GT: return "ngt"; | |
63 | } | |
64 | llvm_unreachable("Impossible condition code!"); | |
65 | } | |
66 | ||
67 | void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { | |
68 | OS << '$' << StringRef(getRegisterName(RegNo)).lower(); | |
69 | } | |
70 | ||
71 | void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, | |
72 | StringRef Annot) { | |
73 | switch (MI->getOpcode()) { | |
74 | default: | |
75 | break; | |
76 | case Mips::RDHWR: | |
77 | case Mips::RDHWR64: | |
78 | O << "\t.set\tpush\n"; | |
79 | O << "\t.set\tmips32r2\n"; | |
80 | } | |
81 | ||
970d7e83 LB |
82 | // Try to print any aliases first. |
83 | if (!printAliasInstr(MI, O)) | |
84 | printInstruction(MI, O); | |
223e47cc LB |
85 | printAnnotation(O, Annot); |
86 | ||
87 | switch (MI->getOpcode()) { | |
88 | default: | |
89 | break; | |
90 | case Mips::RDHWR: | |
91 | case Mips::RDHWR64: | |
92 | O << "\n\t.set\tpop"; | |
93 | } | |
94 | } | |
95 | ||
96 | static void printExpr(const MCExpr *Expr, raw_ostream &OS) { | |
97 | int Offset = 0; | |
98 | const MCSymbolRefExpr *SRE; | |
99 | ||
100 | if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { | |
101 | SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); | |
102 | const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); | |
103 | assert(SRE && CE && "Binary expression must be sym+const."); | |
104 | Offset = CE->getValue(); | |
105 | } | |
106 | else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr))) | |
107 | assert(false && "Unexpected MCExpr type."); | |
108 | ||
109 | MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); | |
110 | ||
111 | switch (Kind) { | |
112 | default: llvm_unreachable("Invalid kind!"); | |
113 | case MCSymbolRefExpr::VK_None: break; | |
114 | case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; | |
115 | case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; | |
116 | case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; | |
117 | case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; | |
118 | case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; | |
119 | case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; | |
120 | case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; | |
121 | case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; | |
122 | case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi("; break; | |
123 | case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo("; break; | |
124 | case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; | |
125 | case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; | |
126 | case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; | |
127 | case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; | |
128 | case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; | |
129 | case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; | |
130 | case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; | |
131 | case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; | |
132 | case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break; | |
133 | case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break; | |
970d7e83 LB |
134 | case MCSymbolRefExpr::VK_Mips_GOT_HI16: OS << "%got_hi("; break; |
135 | case MCSymbolRefExpr::VK_Mips_GOT_LO16: OS << "%got_lo("; break; | |
136 | case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break; | |
137 | case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break; | |
223e47cc LB |
138 | } |
139 | ||
140 | OS << SRE->getSymbol(); | |
141 | ||
142 | if (Offset) { | |
143 | if (Offset > 0) | |
144 | OS << '+'; | |
145 | OS << Offset; | |
146 | } | |
147 | ||
148 | if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) || | |
149 | (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO)) | |
150 | OS << ")))"; | |
151 | else if (Kind != MCSymbolRefExpr::VK_None) | |
152 | OS << ')'; | |
153 | } | |
154 | ||
970d7e83 LB |
155 | void MipsInstPrinter::printCPURegs(const MCInst *MI, unsigned OpNo, |
156 | raw_ostream &O) { | |
157 | printRegName(O, MI->getOperand(OpNo).getReg()); | |
158 | } | |
159 | ||
223e47cc LB |
160 | void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
161 | raw_ostream &O) { | |
162 | const MCOperand &Op = MI->getOperand(OpNo); | |
163 | if (Op.isReg()) { | |
164 | printRegName(O, Op.getReg()); | |
165 | return; | |
166 | } | |
167 | ||
168 | if (Op.isImm()) { | |
169 | O << Op.getImm(); | |
170 | return; | |
171 | } | |
172 | ||
173 | assert(Op.isExpr() && "unknown operand kind in printOperand"); | |
174 | printExpr(Op.getExpr(), O); | |
175 | } | |
176 | ||
177 | void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, | |
178 | raw_ostream &O) { | |
179 | const MCOperand &MO = MI->getOperand(opNum); | |
180 | if (MO.isImm()) | |
181 | O << (unsigned short int)MO.getImm(); | |
182 | else | |
183 | printOperand(MI, opNum, O); | |
184 | } | |
185 | ||
186 | void MipsInstPrinter:: | |
187 | printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { | |
188 | // Load/Store memory operands -- imm($reg) | |
189 | // If PIC target the target is loaded as the | |
190 | // pattern lw $25,%call16($28) | |
191 | printOperand(MI, opNum+1, O); | |
192 | O << "("; | |
193 | printOperand(MI, opNum, O); | |
194 | O << ")"; | |
195 | } | |
196 | ||
197 | void MipsInstPrinter:: | |
198 | printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { | |
199 | // when using stack locations for not load/store instructions | |
200 | // print the same way as all normal 3 operand instructions. | |
201 | printOperand(MI, opNum, O); | |
202 | O << ", "; | |
203 | printOperand(MI, opNum+1, O); | |
204 | return; | |
205 | } | |
206 | ||
207 | void MipsInstPrinter:: | |
208 | printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { | |
209 | const MCOperand& MO = MI->getOperand(opNum); | |
210 | O << MipsFCCToString((Mips::CondCode)MO.getImm()); | |
211 | } |