/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// |
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 file includes code for rendering MCInst instances as AT&T-style |
11 | | // assembly. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "X86ATTInstPrinter.h" |
16 | | #include "MCTargetDesc/X86BaseInfo.h" |
17 | | #include "X86InstComments.h" |
18 | | #include "llvm/MC/MCExpr.h" |
19 | | #include "llvm/MC/MCInst.h" |
20 | | #include "llvm/MC/MCInstrDesc.h" |
21 | | #include "llvm/MC/MCInstrInfo.h" |
22 | | #include "llvm/MC/MCSubtargetInfo.h" |
23 | | #include "llvm/Support/Casting.h" |
24 | | #include "llvm/Support/ErrorHandling.h" |
25 | | #include "llvm/Support/Format.h" |
26 | | #include "llvm/Support/raw_ostream.h" |
27 | | #include <cassert> |
28 | | #include <cinttypes> |
29 | | #include <cstdint> |
30 | | |
31 | | using namespace llvm; |
32 | | |
33 | | #define DEBUG_TYPE "asm-printer" |
34 | | |
35 | | // Include the auto-generated portion of the assembly writer. |
36 | | #define PRINT_ALIAS_INSTR |
37 | | #include "X86GenAsmWriter.inc" |
38 | | |
39 | 1.01M | void X86ATTInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { |
40 | 1.01M | OS << markup("<reg:") << '%' << getRegisterName(RegNo) << markup(">"); |
41 | 1.01M | } |
42 | | |
43 | | void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, |
44 | 659k | StringRef Annot, const MCSubtargetInfo &STI) { |
45 | 659k | const MCInstrDesc &Desc = MII.get(MI->getOpcode()); |
46 | 659k | uint64_t TSFlags = Desc.TSFlags; |
47 | 659k | |
48 | 659k | // If verbose assembly is enabled, we can print some informative comments. |
49 | 659k | if (CommentStream) |
50 | 486k | HasCustomInstComment = |
51 | 486k | EmitAnyX86InstComments(MI, *CommentStream, getRegisterName); |
52 | 659k | |
53 | 659k | if (TSFlags & X86II::LOCK) |
54 | 843 | OS << "\tlock\t"; |
55 | 659k | |
56 | 659k | // Output CALLpcrel32 as "callq" in 64-bit mode. |
57 | 659k | // In Intel annotation it's always emitted as "call". |
58 | 659k | // |
59 | 659k | // TODO: Probably this hack should be redesigned via InstAlias in |
60 | 659k | // InstrInfo.td as soon as Requires clause is supported properly |
61 | 659k | // for InstAlias. |
62 | 659k | if (MI->getOpcode() == X86::CALLpcrel32 && |
63 | 659k | (STI.getFeatureBits()[X86::Mode64Bit])3.11k ) { |
64 | 37 | OS << "\tcallq\t"; |
65 | 37 | printPCRelImm(MI, 0, OS); |
66 | 37 | } |
67 | 659k | // data16 and data32 both have the same encoding of 0x66. While data32 is |
68 | 659k | // valid only in 16 bit systems, data16 is valid in the rest. |
69 | 659k | // There seems to be some lack of support of the Requires clause that causes |
70 | 659k | // 0x66 to be interpreted as "data16" by the asm printer. |
71 | 659k | // Thus we add an adjustment here in order to print the "right" instruction. |
72 | 659k | else if (659k MI->getOpcode() == X86::DATA16_PREFIX && |
73 | 659k | (STI.getFeatureBits()[X86::Mode16Bit])45 ) { |
74 | 1 | MCInst Data32MI(*MI); |
75 | 1 | Data32MI.setOpcode(X86::DATA32_PREFIX); |
76 | 1 | printInstruction(&Data32MI, OS); |
77 | 1 | } |
78 | 659k | // Try to print any aliases first. |
79 | 659k | else if (659k !printAliasInstr(MI, OS)659k ) |
80 | 659k | printInstruction(MI, OS); |
81 | 659k | |
82 | 659k | // Next always print the annotation. |
83 | 659k | printAnnotation(OS, Annot); |
84 | 659k | } |
85 | | |
86 | | void X86ATTInstPrinter::printSSEAVXCC(const MCInst *MI, unsigned Op, |
87 | 3.89k | raw_ostream &O) { |
88 | 3.89k | int64_t Imm = MI->getOperand(Op).getImm(); |
89 | 3.89k | switch (Imm) { |
90 | 0 | default: 0 llvm_unreachable0 ("Invalid ssecc/avxcc argument!"); |
91 | 556 | case 0: O << "eq"; break; |
92 | 1.07k | case 1: O << "lt"; break; |
93 | 554 | case 2: O << "le"; break; |
94 | 131 | case 3: O << "unord"; break; |
95 | 487 | case 4: O << "neq"; break; |
96 | 275 | case 5: O << "nlt"; break; |
97 | 261 | case 6: O << "nle"; break; |
98 | 117 | case 7: O << "ord"; break; |
99 | 20 | case 8: O << "eq_uq"; break; |
100 | 21 | case 9: O << "nge"; break; |
101 | 14 | case 0xa: O << "ngt"; break; |
102 | 18 | case 0xb: O << "false"; break; |
103 | 14 | case 0xc: O << "neq_oq"; break; |
104 | 35 | case 0xd: O << "ge"; break; |
105 | 19 | case 0xe: O << "gt"; break; |
106 | 70 | case 0xf: O << "true"; break; |
107 | 14 | case 0x10: O << "eq_os"; break; |
108 | 14 | case 0x11: O << "lt_oq"; break; |
109 | 14 | case 0x12: O << "le_oq"; break; |
110 | 14 | case 0x13: O << "unord_s"; break; |
111 | 14 | case 0x14: O << "neq_us"; break; |
112 | 14 | case 0x15: O << "nlt_uq"; break; |
113 | 14 | case 0x16: O << "nle_uq"; break; |
114 | 14 | case 0x17: O << "ord_s"; break; |
115 | 14 | case 0x18: O << "eq_us"; break; |
116 | 14 | case 0x19: O << "nge_uq"; break; |
117 | 14 | case 0x1a: O << "ngt_uq"; break; |
118 | 14 | case 0x1b: O << "false_os"; break; |
119 | 14 | case 0x1c: O << "neq_os"; break; |
120 | 14 | case 0x1d: O << "ge_oq"; break; |
121 | 14 | case 0x1e: O << "gt_oq"; break; |
122 | 18 | case 0x1f: O << "true_us"; break; |
123 | 3.89k | } |
124 | 3.89k | } |
125 | | |
126 | | void X86ATTInstPrinter::printXOPCC(const MCInst *MI, unsigned Op, |
127 | 227 | raw_ostream &O) { |
128 | 227 | int64_t Imm = MI->getOperand(Op).getImm(); |
129 | 227 | switch (Imm) { |
130 | 0 | default: 0 llvm_unreachable0 ("Invalid xopcc argument!"); |
131 | 60 | case 0: O << "lt"; break; |
132 | 28 | case 1: O << "le"; break; |
133 | 28 | case 2: O << "gt"; break; |
134 | 28 | case 3: O << "ge"; break; |
135 | 30 | case 4: O << "eq"; break; |
136 | 29 | case 5: O << "neq"; break; |
137 | 12 | case 6: O << "false"; break; |
138 | 12 | case 7: O << "true"; break; |
139 | 227 | } |
140 | 227 | } |
141 | | |
142 | | void X86ATTInstPrinter::printRoundingControl(const MCInst *MI, unsigned Op, |
143 | 722 | raw_ostream &O) { |
144 | 722 | int64_t Imm = MI->getOperand(Op).getImm() & 0x3; |
145 | 722 | switch (Imm) { |
146 | 204 | case 0: O << "{rn-sae}"; break; |
147 | 166 | case 1: O << "{rd-sae}"; break; |
148 | 169 | case 2: O << "{ru-sae}"; break; |
149 | 183 | case 3: O << "{rz-sae}"; break; |
150 | 722 | } |
151 | 722 | } |
152 | | |
153 | | /// printPCRelImm - This is used to print an immediate value that ends up |
154 | | /// being encoded as a pc-relative value (e.g. for jumps and calls). These |
155 | | /// print slightly differently than normal immediates. For example, a $ is not |
156 | | /// emitted. |
157 | | void X86ATTInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo, |
158 | 44.4k | raw_ostream &O) { |
159 | 44.4k | const MCOperand &Op = MI->getOperand(OpNo); |
160 | 44.4k | if (Op.isImm()) |
161 | 28.3k | O << formatImm(Op.getImm()); |
162 | 16.1k | else { |
163 | 16.1k | assert(Op.isExpr() && "unknown pcrel immediate operand"); |
164 | 16.1k | // If a symbolic branch target was added as a constant expression then print |
165 | 16.1k | // that address in hex. |
166 | 16.1k | const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr()); |
167 | 16.1k | int64_t Address; |
168 | 16.1k | if (BranchTarget && 16.1k BranchTarget->evaluateAsAbsolute(Address)102 ) { |
169 | 102 | O << formatHex((uint64_t)Address); |
170 | 16.1k | } else { |
171 | 16.0k | // Otherwise, just print the expression. |
172 | 16.0k | Op.getExpr()->print(O, &MAI); |
173 | 16.0k | } |
174 | 16.1k | } |
175 | 44.4k | } |
176 | | |
177 | | void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
178 | 1.07M | raw_ostream &O) { |
179 | 1.07M | const MCOperand &Op = MI->getOperand(OpNo); |
180 | 1.07M | if (Op.isReg()1.07M ) { |
181 | 1.01M | printRegName(O, Op.getReg()); |
182 | 1.07M | } else if (58.4k Op.isImm()58.4k ) { |
183 | 57.2k | // Print immediates as signed values. |
184 | 57.2k | int64_t Imm = Op.getImm(); |
185 | 57.2k | O << markup("<imm:") << '$' << formatImm(Imm) << markup(">"); |
186 | 57.2k | |
187 | 57.2k | // TODO: This should be in a helper function in the base class, so it can |
188 | 57.2k | // be used by other printers. |
189 | 57.2k | |
190 | 57.2k | // If there are no instruction-specific comments, add a comment clarifying |
191 | 57.2k | // the hex value of the immediate operand when it isn't in the range |
192 | 57.2k | // [-256,255]. |
193 | 57.2k | if (CommentStream && 57.2k !HasCustomInstComment32.4k && (Imm > 255 || 32.4k Imm < -25629.1k )) { |
194 | 4.05k | // Don't print unnecessary hex sign bits. |
195 | 4.05k | if (Imm == (int16_t)(Imm)) |
196 | 2.09k | *CommentStream << format("imm = 0x%" PRIX16 "\n", (uint16_t)Imm); |
197 | 1.95k | else if (1.95k Imm == (int32_t)(Imm)1.95k ) |
198 | 1.37k | *CommentStream << format("imm = 0x%" PRIX32 "\n", (uint32_t)Imm); |
199 | 1.95k | else |
200 | 588 | *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Imm); |
201 | 4.05k | } |
202 | 58.4k | } else { |
203 | 1.19k | assert(Op.isExpr() && "unknown operand kind in printOperand"); |
204 | 1.19k | O << markup("<imm:") << '$'; |
205 | 1.19k | Op.getExpr()->print(O, &MAI); |
206 | 1.19k | O << markup(">"); |
207 | 1.19k | } |
208 | 1.07M | } |
209 | | |
210 | | void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, |
211 | 183k | raw_ostream &O) { |
212 | 183k | const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg); |
213 | 183k | const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg); |
214 | 183k | const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp); |
215 | 183k | const MCOperand &SegReg = MI->getOperand(Op + X86::AddrSegmentReg); |
216 | 183k | |
217 | 183k | O << markup("<mem:"); |
218 | 183k | |
219 | 183k | // If this has a segment register, print it. |
220 | 183k | if (SegReg.getReg()183k ) { |
221 | 1.30k | printOperand(MI, Op + X86::AddrSegmentReg, O); |
222 | 1.30k | O << ':'; |
223 | 1.30k | } |
224 | 183k | |
225 | 183k | if (DispSpec.isImm()183k ) { |
226 | 163k | int64_t DispVal = DispSpec.getImm(); |
227 | 163k | if (DispVal || 163k (!IndexReg.getReg() && 47.7k !BaseReg.getReg()42.0k )) |
228 | 115k | O << formatImm(DispVal); |
229 | 183k | } else { |
230 | 20.1k | assert(DispSpec.isExpr() && "non-immediate displacement for LEA?"); |
231 | 20.1k | DispSpec.getExpr()->print(O, &MAI); |
232 | 20.1k | } |
233 | 183k | |
234 | 183k | if (IndexReg.getReg() || 183k BaseReg.getReg()171k ) { |
235 | 177k | O << '('; |
236 | 177k | if (BaseReg.getReg()) |
237 | 176k | printOperand(MI, Op + X86::AddrBaseReg, O); |
238 | 177k | |
239 | 177k | if (IndexReg.getReg()177k ) { |
240 | 12.0k | O << ','; |
241 | 12.0k | printOperand(MI, Op + X86::AddrIndexReg, O); |
242 | 12.0k | unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm(); |
243 | 12.0k | if (ScaleVal != 112.0k ) { |
244 | 7.56k | O << ',' << markup("<imm:") << ScaleVal // never printed in hex. |
245 | 7.56k | << markup(">"); |
246 | 7.56k | } |
247 | 12.0k | } |
248 | 177k | O << ')'; |
249 | 177k | } |
250 | 183k | |
251 | 183k | O << markup(">"); |
252 | 183k | } |
253 | | |
254 | | void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op, |
255 | 210 | raw_ostream &O) { |
256 | 210 | const MCOperand &SegReg = MI->getOperand(Op + 1); |
257 | 210 | |
258 | 210 | O << markup("<mem:"); |
259 | 210 | |
260 | 210 | // If this has a segment register, print it. |
261 | 210 | if (SegReg.getReg()210 ) { |
262 | 56 | printOperand(MI, Op + 1, O); |
263 | 56 | O << ':'; |
264 | 56 | } |
265 | 210 | |
266 | 210 | O << "("; |
267 | 210 | printOperand(MI, Op, O); |
268 | 210 | O << ")"; |
269 | 210 | |
270 | 210 | O << markup(">"); |
271 | 210 | } |
272 | | |
273 | | void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op, |
274 | 200 | raw_ostream &O) { |
275 | 200 | O << markup("<mem:"); |
276 | 200 | |
277 | 200 | O << "%es:("; |
278 | 200 | printOperand(MI, Op, O); |
279 | 200 | O << ")"; |
280 | 200 | |
281 | 200 | O << markup(">"); |
282 | 200 | } |
283 | | |
284 | | void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, |
285 | 984 | raw_ostream &O) { |
286 | 984 | const MCOperand &DispSpec = MI->getOperand(Op); |
287 | 984 | const MCOperand &SegReg = MI->getOperand(Op + 1); |
288 | 984 | |
289 | 984 | O << markup("<mem:"); |
290 | 984 | |
291 | 984 | // If this has a segment register, print it. |
292 | 984 | if (SegReg.getReg()984 ) { |
293 | 238 | printOperand(MI, Op + 1, O); |
294 | 238 | O << ':'; |
295 | 238 | } |
296 | 984 | |
297 | 984 | if (DispSpec.isImm()984 ) { |
298 | 375 | O << formatImm(DispSpec.getImm()); |
299 | 984 | } else { |
300 | 609 | assert(DispSpec.isExpr() && "non-immediate displacement?"); |
301 | 609 | DispSpec.getExpr()->print(O, &MAI); |
302 | 609 | } |
303 | 984 | |
304 | 984 | O << markup(">"); |
305 | 984 | } |
306 | | |
307 | | void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, |
308 | 70.2k | raw_ostream &O) { |
309 | 70.2k | if (MI->getOperand(Op).isExpr()) |
310 | 3 | return printOperand(MI, Op, O); |
311 | 70.2k | |
312 | 70.2k | O << markup("<imm:") << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff) |
313 | 70.2k | << markup(">"); |
314 | 70.2k | } |