1 | //===-- X86IntelInstPrinter.cpp - Intel 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 Intel-style |
10 | // assembly. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "X86IntelInstPrinter.h" |
15 | #include "X86BaseInfo.h" |
16 | #include "X86InstComments.h" |
17 | #include "llvm/MC/MCAsmInfo.h" |
18 | #include "llvm/MC/MCExpr.h" |
19 | #include "llvm/MC/MCInst.h" |
20 | #include "llvm/MC/MCInstrAnalysis.h" |
21 | #include "llvm/MC/MCInstrDesc.h" |
22 | #include "llvm/MC/MCInstrInfo.h" |
23 | #include "llvm/MC/MCSubtargetInfo.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include <cassert> |
26 | #include <cstdint> |
27 | |
28 | using namespace llvm; |
29 | |
30 | #define DEBUG_TYPE "asm-printer" |
31 | |
32 | // Include the auto-generated portion of the assembly writer. |
33 | #define PRINT_ALIAS_INSTR |
34 | #include "X86GenAsmWriter1.inc" |
35 | |
36 | void X86IntelInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) { |
37 | markup(OS, M: Markup::Register) << getRegisterName(Reg); |
38 | } |
39 | |
40 | void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address, |
41 | StringRef Annot, const MCSubtargetInfo &STI, |
42 | raw_ostream &OS) { |
43 | printInstFlags(MI, O&: OS, STI); |
44 | |
45 | // In 16-bit mode, print data16 as data32. |
46 | if (MI->getOpcode() == X86::DATA16_PREFIX && |
47 | STI.hasFeature(Feature: X86::Is16Bit)) { |
48 | OS << "\tdata32" ; |
49 | } else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS)) |
50 | printInstruction(MI, Address, O&: OS); |
51 | |
52 | // Next always print the annotation. |
53 | printAnnotation(OS, Annot); |
54 | |
55 | // If verbose assembly is enabled, we can print some informative comments. |
56 | if (CommentStream) |
57 | EmitAnyX86InstComments(MI, OS&: *CommentStream, MCII: MII); |
58 | } |
59 | |
60 | bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS) { |
61 | if (MI->getNumOperands() == 0 || |
62 | !MI->getOperand(i: MI->getNumOperands() - 1).isImm()) |
63 | return false; |
64 | |
65 | int64_t Imm = MI->getOperand(i: MI->getNumOperands() - 1).getImm(); |
66 | |
67 | const MCInstrDesc &Desc = MII.get(Opcode: MI->getOpcode()); |
68 | |
69 | // Custom print the vector compare instructions to get the immediate |
70 | // translated into the mnemonic. |
71 | switch (MI->getOpcode()) { |
72 | case X86::CMPPDrmi: case X86::CMPPDrri: |
73 | case X86::CMPPSrmi: case X86::CMPPSrri: |
74 | case X86::CMPSDrmi: case X86::CMPSDrri: |
75 | case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: |
76 | case X86::CMPSSrmi: case X86::CMPSSrri: |
77 | case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: |
78 | if (Imm >= 0 && Imm <= 7) { |
79 | OS << '\t'; |
80 | printCMPMnemonic(MI, /*IsVCMP*/IsVCmp: false, OS); |
81 | printOperand(MI, OpNo: 0, O&: OS); |
82 | OS << ", " ; |
83 | // Skip operand 1 as its tied to the dest. |
84 | |
85 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
86 | if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) |
87 | printdwordmem(MI, OpNo: 2, O&: OS); |
88 | else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) |
89 | printqwordmem(MI, OpNo: 2, O&: OS); |
90 | else |
91 | printxmmwordmem(MI, OpNo: 2, O&: OS); |
92 | } else |
93 | printOperand(MI, OpNo: 2, O&: OS); |
94 | |
95 | return true; |
96 | } |
97 | break; |
98 | |
99 | case X86::VCMPPDrmi: case X86::VCMPPDrri: |
100 | case X86::VCMPPDYrmi: case X86::VCMPPDYrri: |
101 | case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: |
102 | case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: |
103 | case X86::VCMPPDZrmi: case X86::VCMPPDZrri: |
104 | case X86::VCMPPSrmi: case X86::VCMPPSrri: |
105 | case X86::VCMPPSYrmi: case X86::VCMPPSYrri: |
106 | case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: |
107 | case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: |
108 | case X86::VCMPPSZrmi: case X86::VCMPPSZrri: |
109 | case X86::VCMPSDrmi: case X86::VCMPSDrri: |
110 | case X86::VCMPSDZrmi: case X86::VCMPSDZrri: |
111 | case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: |
112 | case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: |
113 | case X86::VCMPSSrmi: case X86::VCMPSSrri: |
114 | case X86::VCMPSSZrmi: case X86::VCMPSSZrri: |
115 | case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: |
116 | case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: |
117 | case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: |
118 | case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: |
119 | case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: |
120 | case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: |
121 | case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: |
122 | case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: |
123 | case X86::VCMPSDZrmik_Int: case X86::VCMPSDZrrik_Int: |
124 | case X86::VCMPSSZrmik_Int: case X86::VCMPSSZrrik_Int: |
125 | case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: |
126 | case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: |
127 | case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: |
128 | case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: |
129 | case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: |
130 | case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: |
131 | case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: |
132 | case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: |
133 | case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrribk_Int: |
134 | case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrribk_Int: |
135 | case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: |
136 | case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: |
137 | case X86::VCMPPHZrmi: case X86::VCMPPHZrri: |
138 | case X86::VCMPSHZrmi: case X86::VCMPSHZrri: |
139 | case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: |
140 | case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: |
141 | case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: |
142 | case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: |
143 | case X86::VCMPSHZrmik_Int: case X86::VCMPSHZrrik_Int: |
144 | case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: |
145 | case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: |
146 | case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: |
147 | case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: |
148 | case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrribk_Int: |
149 | case X86::VCMPBF16Z128rmi: case X86::VCMPBF16Z128rri: |
150 | case X86::VCMPBF16Z256rmi: case X86::VCMPBF16Z256rri: |
151 | case X86::VCMPBF16Zrmi: case X86::VCMPBF16Zrri: |
152 | case X86::VCMPBF16Z128rmik: case X86::VCMPBF16Z128rrik: |
153 | case X86::VCMPBF16Z256rmik: case X86::VCMPBF16Z256rrik: |
154 | case X86::VCMPBF16Zrmik: case X86::VCMPBF16Zrrik: |
155 | case X86::VCMPBF16Z128rmbi: case X86::VCMPBF16Z128rmbik: |
156 | case X86::VCMPBF16Z256rmbi: case X86::VCMPBF16Z256rmbik: |
157 | case X86::VCMPBF16Zrmbi: case X86::VCMPBF16Zrmbik: |
158 | if (Imm >= 0 && Imm <= 31) { |
159 | OS << '\t'; |
160 | printCMPMnemonic(MI, /*IsVCMP*/IsVCmp: true, OS); |
161 | |
162 | unsigned CurOp = 0; |
163 | printOperand(MI, OpNo: CurOp++, O&: OS); |
164 | |
165 | if (Desc.TSFlags & X86II::EVEX_K) { |
166 | // Print mask operand. |
167 | OS << " {" ; |
168 | printOperand(MI, OpNo: CurOp++, O&: OS); |
169 | OS << "}" ; |
170 | } |
171 | OS << ", " ; |
172 | printOperand(MI, OpNo: CurOp++, O&: OS); |
173 | OS << ", " ; |
174 | |
175 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
176 | if (Desc.TSFlags & X86II::EVEX_B) { |
177 | // Broadcast form. |
178 | // Load size is word for TA map. Otherwise it is based on W-bit. |
179 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
180 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
181 | printwordmem(MI, OpNo: CurOp++, O&: OS); |
182 | } else if (Desc.TSFlags & X86II::REX_W) { |
183 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
184 | } else { |
185 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
186 | } |
187 | |
188 | // Print the number of elements broadcasted. |
189 | unsigned NumElts; |
190 | if (Desc.TSFlags & X86II::EVEX_L2) |
191 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
192 | else if (Desc.TSFlags & X86II::VEX_L) |
193 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
194 | else |
195 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
196 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
197 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
198 | NumElts *= 2; |
199 | } |
200 | OS << "{1to" << NumElts << "}" ; |
201 | } else { |
202 | if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) { |
203 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) |
204 | printwordmem(MI, OpNo: CurOp++, O&: OS); |
205 | else |
206 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
207 | } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD && |
208 | (Desc.TSFlags & X86II::OpMapMask) != X86II::TA) { |
209 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
210 | } else if (Desc.TSFlags & X86II::EVEX_L2) { |
211 | printzmmwordmem(MI, OpNo: CurOp++, O&: OS); |
212 | } else if (Desc.TSFlags & X86II::VEX_L) { |
213 | printymmwordmem(MI, OpNo: CurOp++, O&: OS); |
214 | } else { |
215 | printxmmwordmem(MI, OpNo: CurOp++, O&: OS); |
216 | } |
217 | } |
218 | } else { |
219 | printOperand(MI, OpNo: CurOp++, O&: OS); |
220 | if (Desc.TSFlags & X86II::EVEX_B) |
221 | OS << ", {sae}" ; |
222 | } |
223 | |
224 | return true; |
225 | } |
226 | break; |
227 | |
228 | case X86::VPCOMBmi: case X86::VPCOMBri: |
229 | case X86::VPCOMDmi: case X86::VPCOMDri: |
230 | case X86::VPCOMQmi: case X86::VPCOMQri: |
231 | case X86::VPCOMUBmi: case X86::VPCOMUBri: |
232 | case X86::VPCOMUDmi: case X86::VPCOMUDri: |
233 | case X86::VPCOMUQmi: case X86::VPCOMUQri: |
234 | case X86::VPCOMUWmi: case X86::VPCOMUWri: |
235 | case X86::VPCOMWmi: case X86::VPCOMWri: |
236 | if (Imm >= 0 && Imm <= 7) { |
237 | OS << '\t'; |
238 | printVPCOMMnemonic(MI, OS); |
239 | printOperand(MI, OpNo: 0, O&: OS); |
240 | OS << ", " ; |
241 | printOperand(MI, OpNo: 1, O&: OS); |
242 | OS << ", " ; |
243 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) |
244 | printxmmwordmem(MI, OpNo: 2, O&: OS); |
245 | else |
246 | printOperand(MI, OpNo: 2, O&: OS); |
247 | return true; |
248 | } |
249 | break; |
250 | |
251 | case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri: |
252 | case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri: |
253 | case X86::VPCMPBZrmi: case X86::VPCMPBZrri: |
254 | case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri: |
255 | case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri: |
256 | case X86::VPCMPDZrmi: case X86::VPCMPDZrri: |
257 | case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri: |
258 | case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri: |
259 | case X86::VPCMPQZrmi: case X86::VPCMPQZrri: |
260 | case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri: |
261 | case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri: |
262 | case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri: |
263 | case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri: |
264 | case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri: |
265 | case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri: |
266 | case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri: |
267 | case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri: |
268 | case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri: |
269 | case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri: |
270 | case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri: |
271 | case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri: |
272 | case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri: |
273 | case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri: |
274 | case X86::VPCMPWZrmi: case X86::VPCMPWZrri: |
275 | case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik: |
276 | case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik: |
277 | case X86::VPCMPBZrmik: case X86::VPCMPBZrrik: |
278 | case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik: |
279 | case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik: |
280 | case X86::VPCMPDZrmik: case X86::VPCMPDZrrik: |
281 | case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik: |
282 | case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik: |
283 | case X86::VPCMPQZrmik: case X86::VPCMPQZrrik: |
284 | case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik: |
285 | case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik: |
286 | case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik: |
287 | case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik: |
288 | case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik: |
289 | case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik: |
290 | case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik: |
291 | case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik: |
292 | case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik: |
293 | case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik: |
294 | case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik: |
295 | case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik: |
296 | case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik: |
297 | case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik: |
298 | case X86::VPCMPWZrmik: case X86::VPCMPWZrrik: |
299 | case X86::VPCMPDZ128rmbi: case X86::VPCMPDZ128rmbik: |
300 | case X86::VPCMPDZ256rmbi: case X86::VPCMPDZ256rmbik: |
301 | case X86::VPCMPDZrmbi: case X86::VPCMPDZrmbik: |
302 | case X86::VPCMPQZ128rmbi: case X86::VPCMPQZ128rmbik: |
303 | case X86::VPCMPQZ256rmbi: case X86::VPCMPQZ256rmbik: |
304 | case X86::VPCMPQZrmbi: case X86::VPCMPQZrmbik: |
305 | case X86::VPCMPUDZ128rmbi: case X86::VPCMPUDZ128rmbik: |
306 | case X86::VPCMPUDZ256rmbi: case X86::VPCMPUDZ256rmbik: |
307 | case X86::VPCMPUDZrmbi: case X86::VPCMPUDZrmbik: |
308 | case X86::VPCMPUQZ128rmbi: case X86::VPCMPUQZ128rmbik: |
309 | case X86::VPCMPUQZ256rmbi: case X86::VPCMPUQZ256rmbik: |
310 | case X86::VPCMPUQZrmbi: case X86::VPCMPUQZrmbik: |
311 | if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) { |
312 | OS << '\t'; |
313 | printVPCMPMnemonic(MI, OS); |
314 | |
315 | unsigned CurOp = 0; |
316 | printOperand(MI, OpNo: CurOp++, O&: OS); |
317 | |
318 | if (Desc.TSFlags & X86II::EVEX_K) { |
319 | // Print mask operand. |
320 | OS << " {" ; |
321 | printOperand(MI, OpNo: CurOp++, O&: OS); |
322 | OS << "}" ; |
323 | } |
324 | OS << ", " ; |
325 | printOperand(MI, OpNo: CurOp++, O&: OS); |
326 | OS << ", " ; |
327 | |
328 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
329 | if (Desc.TSFlags & X86II::EVEX_B) { |
330 | // Broadcast form. |
331 | // Load size is based on W-bit as only D and Q are supported. |
332 | if (Desc.TSFlags & X86II::REX_W) |
333 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
334 | else |
335 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
336 | |
337 | // Print the number of elements broadcasted. |
338 | unsigned NumElts; |
339 | if (Desc.TSFlags & X86II::EVEX_L2) |
340 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
341 | else if (Desc.TSFlags & X86II::VEX_L) |
342 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
343 | else |
344 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
345 | OS << "{1to" << NumElts << "}" ; |
346 | } else { |
347 | if (Desc.TSFlags & X86II::EVEX_L2) |
348 | printzmmwordmem(MI, OpNo: CurOp++, O&: OS); |
349 | else if (Desc.TSFlags & X86II::VEX_L) |
350 | printymmwordmem(MI, OpNo: CurOp++, O&: OS); |
351 | else |
352 | printxmmwordmem(MI, OpNo: CurOp++, O&: OS); |
353 | } |
354 | } else { |
355 | printOperand(MI, OpNo: CurOp++, O&: OS); |
356 | } |
357 | |
358 | return true; |
359 | } |
360 | break; |
361 | } |
362 | |
363 | return false; |
364 | } |
365 | |
366 | void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
367 | raw_ostream &O) { |
368 | const MCOperand &Op = MI->getOperand(i: OpNo); |
369 | if (Op.isReg()) { |
370 | printRegName(OS&: O, Reg: Op.getReg()); |
371 | } else if (Op.isImm()) { |
372 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: (int64_t)Op.getImm()); |
373 | } else { |
374 | assert(Op.isExpr() && "unknown operand kind in printOperand" ); |
375 | O << "offset " ; |
376 | MAI.printExpr(O, *Op.getExpr()); |
377 | } |
378 | } |
379 | |
380 | void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op, |
381 | raw_ostream &O) { |
382 | // Do not print the exact form of the memory operand if it references a known |
383 | // binary object. |
384 | if (SymbolizeOperands && MIA) { |
385 | uint64_t Target; |
386 | if (MIA->evaluateBranch(Inst: *MI, Addr: 0, Size: 0, Target)) |
387 | return; |
388 | if (MIA->evaluateMemoryOperandAddress(Inst: *MI, /*STI=*/nullptr, Addr: 0, Size: 0)) |
389 | return; |
390 | } |
391 | const MCOperand &BaseReg = MI->getOperand(i: Op+X86::AddrBaseReg); |
392 | unsigned ScaleVal = MI->getOperand(i: Op+X86::AddrScaleAmt).getImm(); |
393 | const MCOperand &IndexReg = MI->getOperand(i: Op+X86::AddrIndexReg); |
394 | const MCOperand &DispSpec = MI->getOperand(i: Op+X86::AddrDisp); |
395 | |
396 | // If this has a segment register, print it. |
397 | printOptionalSegReg(MI, OpNo: Op + X86::AddrSegmentReg, O); |
398 | |
399 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
400 | O << '['; |
401 | |
402 | bool NeedPlus = false; |
403 | if (BaseReg.getReg()) { |
404 | printOperand(MI, OpNo: Op+X86::AddrBaseReg, O); |
405 | NeedPlus = true; |
406 | } |
407 | |
408 | if (IndexReg.getReg()) { |
409 | if (NeedPlus) O << " + " ; |
410 | if (ScaleVal != 1 || !BaseReg.getReg()) |
411 | O << ScaleVal << '*'; |
412 | printOperand(MI, OpNo: Op+X86::AddrIndexReg, O); |
413 | NeedPlus = true; |
414 | } |
415 | |
416 | if (!DispSpec.isImm()) { |
417 | if (NeedPlus) O << " + " ; |
418 | assert(DispSpec.isExpr() && "non-immediate displacement for LEA?" ); |
419 | MAI.printExpr(O, *DispSpec.getExpr()); |
420 | } else { |
421 | int64_t DispVal = DispSpec.getImm(); |
422 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { |
423 | if (NeedPlus) { |
424 | if (DispVal > 0) |
425 | O << " + " ; |
426 | else { |
427 | O << " - " ; |
428 | DispVal = -DispVal; |
429 | } |
430 | } |
431 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: DispVal); |
432 | } |
433 | } |
434 | |
435 | O << ']'; |
436 | } |
437 | |
438 | void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op, |
439 | raw_ostream &O) { |
440 | // If this has a segment register, print it. |
441 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
442 | |
443 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
444 | O << '['; |
445 | printOperand(MI, OpNo: Op, O); |
446 | O << ']'; |
447 | } |
448 | |
449 | void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op, |
450 | raw_ostream &O) { |
451 | // DI accesses are always ES-based. |
452 | O << "es:" ; |
453 | |
454 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
455 | O << '['; |
456 | printOperand(MI, OpNo: Op, O); |
457 | O << ']'; |
458 | } |
459 | |
460 | void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, |
461 | raw_ostream &O) { |
462 | const MCOperand &DispSpec = MI->getOperand(i: Op); |
463 | |
464 | // If this has a segment register, print it. |
465 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
466 | |
467 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
468 | O << '['; |
469 | |
470 | if (DispSpec.isImm()) { |
471 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: DispSpec.getImm()); |
472 | } else { |
473 | assert(DispSpec.isExpr() && "non-immediate displacement?" ); |
474 | MAI.printExpr(O, *DispSpec.getExpr()); |
475 | } |
476 | |
477 | O << ']'; |
478 | } |
479 | |
480 | void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, |
481 | raw_ostream &O) { |
482 | if (MI->getOperand(i: Op).isExpr()) |
483 | return MAI.printExpr(O, *MI->getOperand(i: Op).getExpr()); |
484 | |
485 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: MI->getOperand(i: Op).getImm() & 0xff); |
486 | } |
487 | |
488 | void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, |
489 | raw_ostream &OS) { |
490 | MCRegister Reg = MI->getOperand(i: OpNo).getReg(); |
491 | // Override the default printing to print st(0) instead st. |
492 | if (Reg == X86::ST0) |
493 | OS << "st(0)" ; |
494 | else |
495 | printRegName(OS, Reg); |
496 | } |
497 | |