1 | //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file includes code for rendering MCInst instances as AT&T-style |
10 | // assembly. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "X86ATTInstPrinter.h" |
15 | #include "X86BaseInfo.h" |
16 | #include "X86InstComments.h" |
17 | #include "llvm/MC/MCExpr.h" |
18 | #include "llvm/MC/MCInst.h" |
19 | #include "llvm/MC/MCInstrAnalysis.h" |
20 | #include "llvm/MC/MCInstrInfo.h" |
21 | #include "llvm/MC/MCSubtargetInfo.h" |
22 | #include "llvm/Support/Casting.h" |
23 | #include "llvm/Support/ErrorHandling.h" |
24 | #include "llvm/Support/Format.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | #include <cassert> |
27 | #include <cinttypes> |
28 | #include <cstdint> |
29 | |
30 | using namespace llvm; |
31 | |
32 | #define DEBUG_TYPE "asm-printer" |
33 | |
34 | // Include the auto-generated portion of the assembly writer. |
35 | #define PRINT_ALIAS_INSTR |
36 | #include "X86GenAsmWriter.inc" |
37 | |
38 | void X86ATTInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { |
39 | markup(OS, M: Markup::Register) << '%' << getRegisterName(Reg); |
40 | } |
41 | |
42 | void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address, |
43 | StringRef Annot, const MCSubtargetInfo &STI, |
44 | raw_ostream &OS) { |
45 | // If verbose assembly is enabled, we can print some informative comments. |
46 | if (CommentStream) |
47 | HasCustomInstComment = EmitAnyX86InstComments(MI, OS&: *CommentStream, MCII: MII); |
48 | |
49 | printInstFlags(MI, O&: OS, STI); |
50 | |
51 | // Output CALLpcrel32 as "callq" in 64-bit mode. |
52 | // In Intel annotation it's always emitted as "call". |
53 | // |
54 | // TODO: Probably this hack should be redesigned via InstAlias in |
55 | // InstrInfo.td as soon as Requires clause is supported properly |
56 | // for InstAlias. |
57 | if (MI->getOpcode() == X86::CALLpcrel32 && |
58 | (STI.hasFeature(Feature: X86::Is64Bit))) { |
59 | OS << "\tcallq\t" ; |
60 | printPCRelImm(MI, Address, OpNo: 0, O&: OS); |
61 | } |
62 | // data16 and data32 both have the same encoding of 0x66. While data32 is |
63 | // valid only in 16 bit systems, data16 is valid in the rest. |
64 | // There seems to be some lack of support of the Requires clause that causes |
65 | // 0x66 to be interpreted as "data16" by the asm printer. |
66 | // Thus we add an adjustment here in order to print the "right" instruction. |
67 | else if (MI->getOpcode() == X86::DATA16_PREFIX && |
68 | STI.hasFeature(Feature: X86::Is16Bit)) { |
69 | OS << "\tdata32" ; |
70 | } |
71 | // Try to print any aliases first. |
72 | else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS)) |
73 | printInstruction(MI, Address, O&: OS); |
74 | |
75 | // Next always print the annotation. |
76 | printAnnotation(OS, Annot); |
77 | } |
78 | |
79 | bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI, |
80 | raw_ostream &OS) { |
81 | if (MI->getNumOperands() == 0 || |
82 | !MI->getOperand(i: MI->getNumOperands() - 1).isImm()) |
83 | return false; |
84 | |
85 | int64_t Imm = MI->getOperand(i: MI->getNumOperands() - 1).getImm(); |
86 | |
87 | const MCInstrDesc &Desc = MII.get(Opcode: MI->getOpcode()); |
88 | |
89 | // Custom print the vector compare instructions to get the immediate |
90 | // translated into the mnemonic. |
91 | switch (MI->getOpcode()) { |
92 | case X86::CMPPDrmi: case X86::CMPPDrri: |
93 | case X86::CMPPSrmi: case X86::CMPPSrri: |
94 | case X86::CMPSDrmi: case X86::CMPSDrri: |
95 | case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: |
96 | case X86::CMPSSrmi: case X86::CMPSSrri: |
97 | case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: |
98 | if (Imm >= 0 && Imm <= 7) { |
99 | OS << '\t'; |
100 | printCMPMnemonic(MI, /*IsVCMP*/IsVCmp: false, OS); |
101 | |
102 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
103 | if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) |
104 | printdwordmem(MI, OpNo: 2, O&: OS); |
105 | else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) |
106 | printqwordmem(MI, OpNo: 2, O&: OS); |
107 | else |
108 | printxmmwordmem(MI, OpNo: 2, O&: OS); |
109 | } else |
110 | printOperand(MI, OpNo: 2, OS); |
111 | |
112 | // Skip operand 1 as its tied to the dest. |
113 | |
114 | OS << ", " ; |
115 | printOperand(MI, OpNo: 0, OS); |
116 | return true; |
117 | } |
118 | break; |
119 | |
120 | case X86::VCMPPDrmi: case X86::VCMPPDrri: |
121 | case X86::VCMPPDYrmi: case X86::VCMPPDYrri: |
122 | case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: |
123 | case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: |
124 | case X86::VCMPPDZrmi: case X86::VCMPPDZrri: |
125 | case X86::VCMPPSrmi: case X86::VCMPPSrri: |
126 | case X86::VCMPPSYrmi: case X86::VCMPPSYrri: |
127 | case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: |
128 | case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: |
129 | case X86::VCMPPSZrmi: case X86::VCMPPSZrri: |
130 | case X86::VCMPSDrmi: case X86::VCMPSDrri: |
131 | case X86::VCMPSDZrmi: case X86::VCMPSDZrri: |
132 | case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: |
133 | case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: |
134 | case X86::VCMPSSrmi: case X86::VCMPSSrri: |
135 | case X86::VCMPSSZrmi: case X86::VCMPSSZrri: |
136 | case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: |
137 | case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: |
138 | case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: |
139 | case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: |
140 | case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: |
141 | case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: |
142 | case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: |
143 | case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: |
144 | case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: |
145 | case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: |
146 | case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: |
147 | case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: |
148 | case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: |
149 | case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: |
150 | case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: |
151 | case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: |
152 | case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: |
153 | case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: |
154 | case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk: |
155 | case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: |
156 | case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: |
157 | case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: |
158 | case X86::VCMPPHZrmi: case X86::VCMPPHZrri: |
159 | case X86::VCMPSHZrmi: case X86::VCMPSHZrri: |
160 | case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: |
161 | case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: |
162 | case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: |
163 | case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: |
164 | case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: |
165 | case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: |
166 | case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: |
167 | case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: |
168 | case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: |
169 | case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk: |
170 | if (Imm >= 0 && Imm <= 31) { |
171 | OS << '\t'; |
172 | printCMPMnemonic(MI, /*IsVCMP*/IsVCmp: true, OS); |
173 | |
174 | unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2; |
175 | |
176 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
177 | if (Desc.TSFlags & X86II::EVEX_B) { |
178 | // Broadcast form. |
179 | // Load size is word for TA map. Otherwise it is based on W-bit. |
180 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
181 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
182 | printwordmem(MI, OpNo: CurOp--, O&: OS); |
183 | } else if (Desc.TSFlags & X86II::REX_W) { |
184 | printqwordmem(MI, OpNo: CurOp--, O&: OS); |
185 | } else { |
186 | printdwordmem(MI, OpNo: CurOp--, O&: OS); |
187 | } |
188 | |
189 | // Print the number of elements broadcasted. |
190 | unsigned NumElts; |
191 | if (Desc.TSFlags & X86II::EVEX_L2) |
192 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
193 | else if (Desc.TSFlags & X86II::VEX_L) |
194 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
195 | else |
196 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
197 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
198 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
199 | NumElts *= 2; |
200 | } |
201 | OS << "{1to" << NumElts << "}" ; |
202 | } else { |
203 | if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) { |
204 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) |
205 | printwordmem(MI, OpNo: CurOp--, O&: OS); |
206 | else |
207 | printdwordmem(MI, OpNo: CurOp--, O&: OS); |
208 | } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) { |
209 | assert((Desc.TSFlags & X86II::OpMapMask) != X86II::TA && |
210 | "Unexpected op map!" ); |
211 | printqwordmem(MI, OpNo: CurOp--, O&: OS); |
212 | } else if (Desc.TSFlags & X86II::EVEX_L2) { |
213 | printzmmwordmem(MI, OpNo: CurOp--, O&: OS); |
214 | } else if (Desc.TSFlags & X86II::VEX_L) { |
215 | printymmwordmem(MI, OpNo: CurOp--, O&: OS); |
216 | } else { |
217 | printxmmwordmem(MI, OpNo: CurOp--, O&: OS); |
218 | } |
219 | } |
220 | } else { |
221 | if (Desc.TSFlags & X86II::EVEX_B) |
222 | OS << "{sae}, " ; |
223 | printOperand(MI, OpNo: CurOp--, OS); |
224 | } |
225 | |
226 | OS << ", " ; |
227 | printOperand(MI, OpNo: CurOp--, OS); |
228 | OS << ", " ; |
229 | printOperand(MI, OpNo: 0, OS); |
230 | if (CurOp > 0) { |
231 | // Print mask operand. |
232 | OS << " {" ; |
233 | printOperand(MI, OpNo: CurOp--, OS); |
234 | OS << "}" ; |
235 | } |
236 | |
237 | return true; |
238 | } |
239 | break; |
240 | |
241 | case X86::VPCOMBmi: case X86::VPCOMBri: |
242 | case X86::VPCOMDmi: case X86::VPCOMDri: |
243 | case X86::VPCOMQmi: case X86::VPCOMQri: |
244 | case X86::VPCOMUBmi: case X86::VPCOMUBri: |
245 | case X86::VPCOMUDmi: case X86::VPCOMUDri: |
246 | case X86::VPCOMUQmi: case X86::VPCOMUQri: |
247 | case X86::VPCOMUWmi: case X86::VPCOMUWri: |
248 | case X86::VPCOMWmi: case X86::VPCOMWri: |
249 | if (Imm >= 0 && Imm <= 7) { |
250 | OS << '\t'; |
251 | printVPCOMMnemonic(MI, OS); |
252 | |
253 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) |
254 | printxmmwordmem(MI, OpNo: 2, O&: OS); |
255 | else |
256 | printOperand(MI, OpNo: 2, OS); |
257 | |
258 | OS << ", " ; |
259 | printOperand(MI, OpNo: 1, OS); |
260 | OS << ", " ; |
261 | printOperand(MI, OpNo: 0, OS); |
262 | return true; |
263 | } |
264 | break; |
265 | |
266 | case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri: |
267 | case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri: |
268 | case X86::VPCMPBZrmi: case X86::VPCMPBZrri: |
269 | case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri: |
270 | case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri: |
271 | case X86::VPCMPDZrmi: case X86::VPCMPDZrri: |
272 | case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri: |
273 | case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri: |
274 | case X86::VPCMPQZrmi: case X86::VPCMPQZrri: |
275 | case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri: |
276 | case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri: |
277 | case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri: |
278 | case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri: |
279 | case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri: |
280 | case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri: |
281 | case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri: |
282 | case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri: |
283 | case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri: |
284 | case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri: |
285 | case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri: |
286 | case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri: |
287 | case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri: |
288 | case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri: |
289 | case X86::VPCMPWZrmi: case X86::VPCMPWZrri: |
290 | case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik: |
291 | case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik: |
292 | case X86::VPCMPBZrmik: case X86::VPCMPBZrrik: |
293 | case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik: |
294 | case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik: |
295 | case X86::VPCMPDZrmik: case X86::VPCMPDZrrik: |
296 | case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik: |
297 | case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik: |
298 | case X86::VPCMPQZrmik: case X86::VPCMPQZrrik: |
299 | case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik: |
300 | case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik: |
301 | case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik: |
302 | case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik: |
303 | case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik: |
304 | case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik: |
305 | case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik: |
306 | case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik: |
307 | case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik: |
308 | case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik: |
309 | case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik: |
310 | case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik: |
311 | case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik: |
312 | case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik: |
313 | case X86::VPCMPWZrmik: case X86::VPCMPWZrrik: |
314 | case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk: |
315 | case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk: |
316 | case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk: |
317 | case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk: |
318 | case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk: |
319 | case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk: |
320 | case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk: |
321 | case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk: |
322 | case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk: |
323 | case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk: |
324 | case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk: |
325 | case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk: |
326 | if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) { |
327 | OS << '\t'; |
328 | printVPCMPMnemonic(MI, OS); |
329 | |
330 | unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2; |
331 | |
332 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
333 | if (Desc.TSFlags & X86II::EVEX_B) { |
334 | // Broadcast form. |
335 | // Load size is based on W-bit as only D and Q are supported. |
336 | if (Desc.TSFlags & X86II::REX_W) |
337 | printqwordmem(MI, OpNo: CurOp--, O&: OS); |
338 | else |
339 | printdwordmem(MI, OpNo: CurOp--, O&: OS); |
340 | |
341 | // Print the number of elements broadcasted. |
342 | unsigned NumElts; |
343 | if (Desc.TSFlags & X86II::EVEX_L2) |
344 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
345 | else if (Desc.TSFlags & X86II::VEX_L) |
346 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
347 | else |
348 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
349 | OS << "{1to" << NumElts << "}" ; |
350 | } else { |
351 | if (Desc.TSFlags & X86II::EVEX_L2) |
352 | printzmmwordmem(MI, OpNo: CurOp--, O&: OS); |
353 | else if (Desc.TSFlags & X86II::VEX_L) |
354 | printymmwordmem(MI, OpNo: CurOp--, O&: OS); |
355 | else |
356 | printxmmwordmem(MI, OpNo: CurOp--, O&: OS); |
357 | } |
358 | } else { |
359 | printOperand(MI, OpNo: CurOp--, OS); |
360 | } |
361 | |
362 | OS << ", " ; |
363 | printOperand(MI, OpNo: CurOp--, OS); |
364 | OS << ", " ; |
365 | printOperand(MI, OpNo: 0, OS); |
366 | if (CurOp > 0) { |
367 | // Print mask operand. |
368 | OS << " {" ; |
369 | printOperand(MI, OpNo: CurOp--, OS); |
370 | OS << "}" ; |
371 | } |
372 | |
373 | return true; |
374 | } |
375 | break; |
376 | } |
377 | |
378 | return false; |
379 | } |
380 | |
381 | void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
382 | raw_ostream &O) { |
383 | const MCOperand &Op = MI->getOperand(i: OpNo); |
384 | if (Op.isReg()) { |
385 | printRegName(OS&: O, Reg: Op.getReg()); |
386 | } else if (Op.isImm()) { |
387 | // Print immediates as signed values. |
388 | int64_t Imm = Op.getImm(); |
389 | markup(OS&: O, M: Markup::Immediate) << '$' << formatImm(Value: Imm); |
390 | |
391 | // TODO: This should be in a helper function in the base class, so it can |
392 | // be used by other printers. |
393 | |
394 | // If there are no instruction-specific comments, add a comment clarifying |
395 | // the hex value of the immediate operand when it isn't in the range |
396 | // [-256,255]. |
397 | if (CommentStream && !HasCustomInstComment && (Imm > 255 || Imm < -256)) { |
398 | // Don't print unnecessary hex sign bits. |
399 | if (Imm == (int16_t)(Imm)) |
400 | *CommentStream << format(Fmt: "imm = 0x%" PRIX16 "\n" , Vals: (uint16_t)Imm); |
401 | else if (Imm == (int32_t)(Imm)) |
402 | *CommentStream << format(Fmt: "imm = 0x%" PRIX32 "\n" , Vals: (uint32_t)Imm); |
403 | else |
404 | *CommentStream << format(Fmt: "imm = 0x%" PRIX64 "\n" , Vals: (uint64_t)Imm); |
405 | } |
406 | } else { |
407 | assert(Op.isExpr() && "unknown operand kind in printOperand" ); |
408 | WithMarkup M = markup(OS&: O, M: Markup::Immediate); |
409 | O << '$'; |
410 | Op.getExpr()->print(OS&: O, MAI: &MAI); |
411 | } |
412 | } |
413 | |
414 | void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, |
415 | raw_ostream &O) { |
416 | // Do not print the exact form of the memory operand if it references a known |
417 | // binary object. |
418 | if (SymbolizeOperands && MIA) { |
419 | uint64_t Target; |
420 | if (MIA->evaluateBranch(Inst: *MI, Addr: 0, Size: 0, Target)) |
421 | return; |
422 | if (MIA->evaluateMemoryOperandAddress(Inst: *MI, /*STI=*/nullptr, Addr: 0, Size: 0)) |
423 | return; |
424 | } |
425 | |
426 | const MCOperand &BaseReg = MI->getOperand(i: Op + X86::AddrBaseReg); |
427 | const MCOperand &IndexReg = MI->getOperand(i: Op + X86::AddrIndexReg); |
428 | const MCOperand &DispSpec = MI->getOperand(i: Op + X86::AddrDisp); |
429 | |
430 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
431 | |
432 | // If this has a segment register, print it. |
433 | printOptionalSegReg(MI, OpNo: Op + X86::AddrSegmentReg, O); |
434 | |
435 | if (DispSpec.isImm()) { |
436 | int64_t DispVal = DispSpec.getImm(); |
437 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) |
438 | O << formatImm(Value: DispVal); |
439 | } else { |
440 | assert(DispSpec.isExpr() && "non-immediate displacement for LEA?" ); |
441 | DispSpec.getExpr()->print(OS&: O, MAI: &MAI); |
442 | } |
443 | |
444 | if (IndexReg.getReg() || BaseReg.getReg()) { |
445 | O << '('; |
446 | if (BaseReg.getReg()) |
447 | printOperand(MI, OpNo: Op + X86::AddrBaseReg, O); |
448 | |
449 | if (IndexReg.getReg()) { |
450 | O << ','; |
451 | printOperand(MI, OpNo: Op + X86::AddrIndexReg, O); |
452 | unsigned ScaleVal = MI->getOperand(i: Op + X86::AddrScaleAmt).getImm(); |
453 | if (ScaleVal != 1) { |
454 | O << ','; |
455 | markup(OS&: O, M: Markup::Immediate) << ScaleVal; // never printed in hex. |
456 | } |
457 | } |
458 | O << ')'; |
459 | } |
460 | } |
461 | |
462 | void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op, |
463 | raw_ostream &O) { |
464 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
465 | |
466 | // If this has a segment register, print it. |
467 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
468 | |
469 | O << "(" ; |
470 | printOperand(MI, OpNo: Op, O); |
471 | O << ")" ; |
472 | } |
473 | |
474 | void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op, |
475 | raw_ostream &O) { |
476 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
477 | |
478 | O << "%es:(" ; |
479 | printOperand(MI, OpNo: Op, O); |
480 | O << ")" ; |
481 | } |
482 | |
483 | void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, |
484 | raw_ostream &O) { |
485 | const MCOperand &DispSpec = MI->getOperand(i: Op); |
486 | |
487 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
488 | |
489 | // If this has a segment register, print it. |
490 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
491 | |
492 | if (DispSpec.isImm()) { |
493 | O << formatImm(Value: DispSpec.getImm()); |
494 | } else { |
495 | assert(DispSpec.isExpr() && "non-immediate displacement?" ); |
496 | DispSpec.getExpr()->print(OS&: O, MAI: &MAI); |
497 | } |
498 | } |
499 | |
500 | void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, |
501 | raw_ostream &O) { |
502 | if (MI->getOperand(i: Op).isExpr()) |
503 | return printOperand(MI, OpNo: Op, O); |
504 | |
505 | markup(OS&: O, M: Markup::Immediate) |
506 | << '$' << formatImm(Value: MI->getOperand(i: Op).getImm() & 0xff); |
507 | } |
508 | |
509 | void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, |
510 | raw_ostream &OS) { |
511 | const MCOperand &Op = MI->getOperand(i: OpNo); |
512 | unsigned Reg = Op.getReg(); |
513 | // Override the default printing to print st(0) instead st. |
514 | if (Reg == X86::ST0) |
515 | markup(OS, M: Markup::Register) << "%st(0)" ; |
516 | else |
517 | printRegName(OS, Reg); |
518 | } |
519 | |