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/MCExpr.h" |
18 | #include "llvm/MC/MCInst.h" |
19 | #include "llvm/MC/MCInstrAnalysis.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 <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) const { |
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::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: |
124 | case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: |
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::VCMPSDZrrib_Intk: |
134 | case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: |
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::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: |
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::VCMPSHZrrib_Intk: |
149 | if (Imm >= 0 && Imm <= 31) { |
150 | OS << '\t'; |
151 | printCMPMnemonic(MI, /*IsVCMP*/IsVCmp: true, OS); |
152 | |
153 | unsigned CurOp = 0; |
154 | printOperand(MI, OpNo: CurOp++, O&: OS); |
155 | |
156 | if (Desc.TSFlags & X86II::EVEX_K) { |
157 | // Print mask operand. |
158 | OS << " {" ; |
159 | printOperand(MI, OpNo: CurOp++, O&: OS); |
160 | OS << "}" ; |
161 | } |
162 | OS << ", " ; |
163 | printOperand(MI, OpNo: CurOp++, O&: OS); |
164 | OS << ", " ; |
165 | |
166 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
167 | if (Desc.TSFlags & X86II::EVEX_B) { |
168 | // Broadcast form. |
169 | // Load size is word for TA map. Otherwise it is based on W-bit. |
170 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
171 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
172 | printwordmem(MI, OpNo: CurOp++, O&: OS); |
173 | } else if (Desc.TSFlags & X86II::REX_W) { |
174 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
175 | } else { |
176 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
177 | } |
178 | |
179 | // Print the number of elements broadcasted. |
180 | unsigned NumElts; |
181 | if (Desc.TSFlags & X86II::EVEX_L2) |
182 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
183 | else if (Desc.TSFlags & X86II::VEX_L) |
184 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
185 | else |
186 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
187 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) { |
188 | assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!" ); |
189 | NumElts *= 2; |
190 | } |
191 | OS << "{1to" << NumElts << "}" ; |
192 | } else { |
193 | if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) { |
194 | if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) |
195 | printwordmem(MI, OpNo: CurOp++, O&: OS); |
196 | else |
197 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
198 | } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) { |
199 | assert((Desc.TSFlags & X86II::OpMapMask) != X86II::TA && |
200 | "Unexpected op map!" ); |
201 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
202 | } else if (Desc.TSFlags & X86II::EVEX_L2) { |
203 | printzmmwordmem(MI, OpNo: CurOp++, O&: OS); |
204 | } else if (Desc.TSFlags & X86II::VEX_L) { |
205 | printymmwordmem(MI, OpNo: CurOp++, O&: OS); |
206 | } else { |
207 | printxmmwordmem(MI, OpNo: CurOp++, O&: OS); |
208 | } |
209 | } |
210 | } else { |
211 | printOperand(MI, OpNo: CurOp++, O&: OS); |
212 | if (Desc.TSFlags & X86II::EVEX_B) |
213 | OS << ", {sae}" ; |
214 | } |
215 | |
216 | return true; |
217 | } |
218 | break; |
219 | |
220 | case X86::VPCOMBmi: case X86::VPCOMBri: |
221 | case X86::VPCOMDmi: case X86::VPCOMDri: |
222 | case X86::VPCOMQmi: case X86::VPCOMQri: |
223 | case X86::VPCOMUBmi: case X86::VPCOMUBri: |
224 | case X86::VPCOMUDmi: case X86::VPCOMUDri: |
225 | case X86::VPCOMUQmi: case X86::VPCOMUQri: |
226 | case X86::VPCOMUWmi: case X86::VPCOMUWri: |
227 | case X86::VPCOMWmi: case X86::VPCOMWri: |
228 | if (Imm >= 0 && Imm <= 7) { |
229 | OS << '\t'; |
230 | printVPCOMMnemonic(MI, OS); |
231 | printOperand(MI, OpNo: 0, O&: OS); |
232 | OS << ", " ; |
233 | printOperand(MI, OpNo: 1, O&: OS); |
234 | OS << ", " ; |
235 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) |
236 | printxmmwordmem(MI, OpNo: 2, O&: OS); |
237 | else |
238 | printOperand(MI, OpNo: 2, O&: OS); |
239 | return true; |
240 | } |
241 | break; |
242 | |
243 | case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri: |
244 | case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri: |
245 | case X86::VPCMPBZrmi: case X86::VPCMPBZrri: |
246 | case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri: |
247 | case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri: |
248 | case X86::VPCMPDZrmi: case X86::VPCMPDZrri: |
249 | case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri: |
250 | case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri: |
251 | case X86::VPCMPQZrmi: case X86::VPCMPQZrri: |
252 | case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri: |
253 | case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri: |
254 | case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri: |
255 | case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri: |
256 | case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri: |
257 | case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri: |
258 | case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri: |
259 | case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri: |
260 | case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri: |
261 | case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri: |
262 | case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri: |
263 | case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri: |
264 | case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri: |
265 | case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri: |
266 | case X86::VPCMPWZrmi: case X86::VPCMPWZrri: |
267 | case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik: |
268 | case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik: |
269 | case X86::VPCMPBZrmik: case X86::VPCMPBZrrik: |
270 | case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik: |
271 | case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik: |
272 | case X86::VPCMPDZrmik: case X86::VPCMPDZrrik: |
273 | case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik: |
274 | case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik: |
275 | case X86::VPCMPQZrmik: case X86::VPCMPQZrrik: |
276 | case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik: |
277 | case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik: |
278 | case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik: |
279 | case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik: |
280 | case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik: |
281 | case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik: |
282 | case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik: |
283 | case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik: |
284 | case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik: |
285 | case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik: |
286 | case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik: |
287 | case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik: |
288 | case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik: |
289 | case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik: |
290 | case X86::VPCMPWZrmik: case X86::VPCMPWZrrik: |
291 | case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk: |
292 | case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk: |
293 | case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk: |
294 | case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk: |
295 | case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk: |
296 | case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk: |
297 | case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk: |
298 | case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk: |
299 | case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk: |
300 | case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk: |
301 | case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk: |
302 | case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk: |
303 | if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) { |
304 | OS << '\t'; |
305 | printVPCMPMnemonic(MI, OS); |
306 | |
307 | unsigned CurOp = 0; |
308 | printOperand(MI, OpNo: CurOp++, O&: OS); |
309 | |
310 | if (Desc.TSFlags & X86II::EVEX_K) { |
311 | // Print mask operand. |
312 | OS << " {" ; |
313 | printOperand(MI, OpNo: CurOp++, O&: OS); |
314 | OS << "}" ; |
315 | } |
316 | OS << ", " ; |
317 | printOperand(MI, OpNo: CurOp++, O&: OS); |
318 | OS << ", " ; |
319 | |
320 | if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) { |
321 | if (Desc.TSFlags & X86II::EVEX_B) { |
322 | // Broadcast form. |
323 | // Load size is based on W-bit as only D and Q are supported. |
324 | if (Desc.TSFlags & X86II::REX_W) |
325 | printqwordmem(MI, OpNo: CurOp++, O&: OS); |
326 | else |
327 | printdwordmem(MI, OpNo: CurOp++, O&: OS); |
328 | |
329 | // Print the number of elements broadcasted. |
330 | unsigned NumElts; |
331 | if (Desc.TSFlags & X86II::EVEX_L2) |
332 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16; |
333 | else if (Desc.TSFlags & X86II::VEX_L) |
334 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8; |
335 | else |
336 | NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4; |
337 | OS << "{1to" << NumElts << "}" ; |
338 | } else { |
339 | if (Desc.TSFlags & X86II::EVEX_L2) |
340 | printzmmwordmem(MI, OpNo: CurOp++, O&: OS); |
341 | else if (Desc.TSFlags & X86II::VEX_L) |
342 | printymmwordmem(MI, OpNo: CurOp++, O&: OS); |
343 | else |
344 | printxmmwordmem(MI, OpNo: CurOp++, O&: OS); |
345 | } |
346 | } else { |
347 | printOperand(MI, OpNo: CurOp++, O&: OS); |
348 | } |
349 | |
350 | return true; |
351 | } |
352 | break; |
353 | } |
354 | |
355 | return false; |
356 | } |
357 | |
358 | void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
359 | raw_ostream &O) { |
360 | const MCOperand &Op = MI->getOperand(i: OpNo); |
361 | if (Op.isReg()) { |
362 | printRegName(OS&: O, Reg: Op.getReg()); |
363 | } else if (Op.isImm()) { |
364 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: (int64_t)Op.getImm()); |
365 | } else { |
366 | assert(Op.isExpr() && "unknown operand kind in printOperand" ); |
367 | O << "offset " ; |
368 | Op.getExpr()->print(OS&: O, MAI: &MAI); |
369 | } |
370 | } |
371 | |
372 | void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op, |
373 | raw_ostream &O) { |
374 | // Do not print the exact form of the memory operand if it references a known |
375 | // binary object. |
376 | if (SymbolizeOperands && MIA) { |
377 | uint64_t Target; |
378 | if (MIA->evaluateBranch(Inst: *MI, Addr: 0, Size: 0, Target)) |
379 | return; |
380 | if (MIA->evaluateMemoryOperandAddress(Inst: *MI, /*STI=*/nullptr, Addr: 0, Size: 0)) |
381 | return; |
382 | } |
383 | const MCOperand &BaseReg = MI->getOperand(i: Op+X86::AddrBaseReg); |
384 | unsigned ScaleVal = MI->getOperand(i: Op+X86::AddrScaleAmt).getImm(); |
385 | const MCOperand &IndexReg = MI->getOperand(i: Op+X86::AddrIndexReg); |
386 | const MCOperand &DispSpec = MI->getOperand(i: Op+X86::AddrDisp); |
387 | |
388 | // If this has a segment register, print it. |
389 | printOptionalSegReg(MI, OpNo: Op + X86::AddrSegmentReg, O); |
390 | |
391 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
392 | O << '['; |
393 | |
394 | bool NeedPlus = false; |
395 | if (BaseReg.getReg()) { |
396 | printOperand(MI, OpNo: Op+X86::AddrBaseReg, O); |
397 | NeedPlus = true; |
398 | } |
399 | |
400 | if (IndexReg.getReg()) { |
401 | if (NeedPlus) O << " + " ; |
402 | if (ScaleVal != 1 || !BaseReg.getReg()) |
403 | O << ScaleVal << '*'; |
404 | printOperand(MI, OpNo: Op+X86::AddrIndexReg, O); |
405 | NeedPlus = true; |
406 | } |
407 | |
408 | if (!DispSpec.isImm()) { |
409 | if (NeedPlus) O << " + " ; |
410 | assert(DispSpec.isExpr() && "non-immediate displacement for LEA?" ); |
411 | DispSpec.getExpr()->print(OS&: O, MAI: &MAI); |
412 | } else { |
413 | int64_t DispVal = DispSpec.getImm(); |
414 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { |
415 | if (NeedPlus) { |
416 | if (DispVal > 0) |
417 | O << " + " ; |
418 | else { |
419 | O << " - " ; |
420 | DispVal = -DispVal; |
421 | } |
422 | } |
423 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: DispVal); |
424 | } |
425 | } |
426 | |
427 | O << ']'; |
428 | } |
429 | |
430 | void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op, |
431 | raw_ostream &O) { |
432 | // If this has a segment register, print it. |
433 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
434 | |
435 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
436 | O << '['; |
437 | printOperand(MI, OpNo: Op, O); |
438 | O << ']'; |
439 | } |
440 | |
441 | void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op, |
442 | raw_ostream &O) { |
443 | // DI accesses are always ES-based. |
444 | O << "es:" ; |
445 | |
446 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
447 | O << '['; |
448 | printOperand(MI, OpNo: Op, O); |
449 | O << ']'; |
450 | } |
451 | |
452 | void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, |
453 | raw_ostream &O) { |
454 | const MCOperand &DispSpec = MI->getOperand(i: Op); |
455 | |
456 | // If this has a segment register, print it. |
457 | printOptionalSegReg(MI, OpNo: Op + 1, O); |
458 | |
459 | WithMarkup M = markup(OS&: O, M: Markup::Memory); |
460 | O << '['; |
461 | |
462 | if (DispSpec.isImm()) { |
463 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: DispSpec.getImm()); |
464 | } else { |
465 | assert(DispSpec.isExpr() && "non-immediate displacement?" ); |
466 | DispSpec.getExpr()->print(OS&: O, MAI: &MAI); |
467 | } |
468 | |
469 | O << ']'; |
470 | } |
471 | |
472 | void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, |
473 | raw_ostream &O) { |
474 | if (MI->getOperand(i: Op).isExpr()) |
475 | return MI->getOperand(i: Op).getExpr()->print(OS&: O, MAI: &MAI); |
476 | |
477 | markup(OS&: O, M: Markup::Immediate) << formatImm(Value: MI->getOperand(i: Op).getImm() & 0xff); |
478 | } |
479 | |
480 | void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, |
481 | raw_ostream &OS) { |
482 | const MCOperand &Op = MI->getOperand(i: OpNo); |
483 | unsigned Reg = Op.getReg(); |
484 | // Override the default printing to print st(0) instead st. |
485 | if (Reg == X86::ST0) |
486 | OS << "st(0)" ; |
487 | else |
488 | printRegName(OS, Reg); |
489 | } |
490 | |