/src/capstonenext/arch/X86/X86IntelInstPrinter.c
Line | Count | Source |
1 | | //===-- X86IntelInstPrinter.cpp - Intel 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 Intel-style |
11 | | // assembly. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | /* Capstone Disassembly Engine */ |
16 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ |
17 | | |
18 | | #ifdef CAPSTONE_HAS_X86 |
19 | | |
20 | | #ifdef _MSC_VER |
21 | | // disable MSVC's warning on strncpy() |
22 | | #pragma warning(disable : 4996) |
23 | | // disable MSVC's warning on strncpy() |
24 | | #pragma warning(disable : 28719) |
25 | | #endif |
26 | | |
27 | | #if !defined(CAPSTONE_HAS_OSXKERNEL) |
28 | | #include <ctype.h> |
29 | | #endif |
30 | | #include <capstone/platform.h> |
31 | | |
32 | | #if defined(CAPSTONE_HAS_OSXKERNEL) |
33 | | #include <Availability.h> |
34 | | #include <libkern/libkern.h> |
35 | | #else |
36 | | #include <stdio.h> |
37 | | #include <stdlib.h> |
38 | | #endif |
39 | | #include <string.h> |
40 | | |
41 | | #include "../../utils.h" |
42 | | #include "../../MCInst.h" |
43 | | #include "../../SStream.h" |
44 | | #include "../../MCRegisterInfo.h" |
45 | | |
46 | | #include "X86InstPrinter.h" |
47 | | #include "../../Mapping.h" |
48 | | #include "X86Mapping.h" |
49 | | #include "X86InstPrinterCommon.h" |
50 | | |
51 | | #define GET_INSTRINFO_ENUM |
52 | | #ifdef CAPSTONE_X86_REDUCE |
53 | | #include "X86GenInstrInfo_reduce.inc" |
54 | | #else |
55 | | #include "X86GenInstrInfo.inc" |
56 | | #endif |
57 | | |
58 | | #define GET_REGINFO_ENUM |
59 | | #include "X86GenRegisterInfo.inc" |
60 | | |
61 | | #include "X86BaseInfo.h" |
62 | | |
63 | | static void printMemReference(MCInst *MI, unsigned Op, SStream *O); |
64 | | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O); |
65 | | |
66 | | static void set_mem_access(MCInst *MI, bool status) |
67 | 67.6k | { |
68 | 67.6k | if (!detail_is_set(MI)) |
69 | 0 | return; |
70 | | |
71 | 67.6k | MI->csh->doing_mem = status; |
72 | 67.6k | if (!status) |
73 | | // done, create the next operand slot |
74 | 33.8k | MI->flat_insn->detail->x86.op_count++; |
75 | 67.6k | } |
76 | | |
77 | | static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O) |
78 | 12.5k | { |
79 | | // FIXME: do this with autogen |
80 | | // printf(">>> ID = %u\n", MI->flat_insn->id); |
81 | 12.5k | switch (MI->flat_insn->id) { |
82 | 3.48k | default: |
83 | 3.48k | SStream_concat0(O, "ptr "); |
84 | 3.48k | break; |
85 | 1.31k | case X86_INS_SGDT: |
86 | 2.57k | case X86_INS_SIDT: |
87 | 3.83k | case X86_INS_LGDT: |
88 | 5.02k | case X86_INS_LIDT: |
89 | 5.52k | case X86_INS_FXRSTOR: |
90 | 6.06k | case X86_INS_FXSAVE: |
91 | 7.82k | case X86_INS_LJMP: |
92 | 9.04k | case X86_INS_LCALL: |
93 | | // do not print "ptr" |
94 | 9.04k | break; |
95 | 12.5k | } |
96 | | |
97 | 12.5k | switch (x86_get_bit_mode(MI->csh->mode)) { |
98 | 3.61k | case CS_MODE_16: |
99 | 3.61k | switch (MI->flat_insn->id) { |
100 | 1.08k | default: |
101 | 1.08k | MI->x86opsize = 2; |
102 | 1.08k | break; |
103 | 450 | case X86_INS_LJMP: |
104 | 855 | case X86_INS_LCALL: |
105 | 855 | MI->x86opsize = 4; |
106 | 855 | break; |
107 | 438 | case X86_INS_SGDT: |
108 | 840 | case X86_INS_SIDT: |
109 | 1.26k | case X86_INS_LGDT: |
110 | 1.67k | case X86_INS_LIDT: |
111 | 1.67k | MI->x86opsize = 6; |
112 | 1.67k | break; |
113 | 3.61k | } |
114 | 3.61k | break; |
115 | 5.16k | case CS_MODE_32: |
116 | 5.16k | switch (MI->flat_insn->id) { |
117 | 2.11k | default: |
118 | 2.11k | MI->x86opsize = 4; |
119 | 2.11k | break; |
120 | 395 | case X86_INS_LJMP: |
121 | 975 | case X86_INS_JMP: |
122 | 1.36k | case X86_INS_LCALL: |
123 | 1.82k | case X86_INS_SGDT: |
124 | 2.24k | case X86_INS_SIDT: |
125 | 2.66k | case X86_INS_LGDT: |
126 | 3.05k | case X86_INS_LIDT: |
127 | 3.05k | MI->x86opsize = 6; |
128 | 3.05k | break; |
129 | 5.16k | } |
130 | 5.16k | break; |
131 | 5.16k | case CS_MODE_64: |
132 | 3.75k | switch (MI->flat_insn->id) { |
133 | 759 | default: |
134 | 759 | MI->x86opsize = 8; |
135 | 759 | break; |
136 | 908 | case X86_INS_LJMP: |
137 | 1.33k | case X86_INS_LCALL: |
138 | 1.74k | case X86_INS_SGDT: |
139 | 2.18k | case X86_INS_SIDT: |
140 | 2.60k | case X86_INS_LGDT: |
141 | 2.99k | case X86_INS_LIDT: |
142 | 2.99k | MI->x86opsize = 10; |
143 | 2.99k | break; |
144 | 3.75k | } |
145 | 3.75k | break; |
146 | 3.75k | default: // never reach |
147 | 0 | break; |
148 | 12.5k | } |
149 | | |
150 | 12.5k | printMemReference(MI, OpNo, O); |
151 | 12.5k | } |
152 | | |
153 | | static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O) |
154 | 63.8k | { |
155 | 63.8k | SStream_concat0(O, "byte ptr "); |
156 | 63.8k | MI->x86opsize = 1; |
157 | 63.8k | printMemReference(MI, OpNo, O); |
158 | 63.8k | } |
159 | | |
160 | | static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O) |
161 | 21.7k | { |
162 | 21.7k | MI->x86opsize = 2; |
163 | 21.7k | SStream_concat0(O, "word ptr "); |
164 | 21.7k | printMemReference(MI, OpNo, O); |
165 | 21.7k | } |
166 | | |
167 | | static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O) |
168 | 48.3k | { |
169 | 48.3k | MI->x86opsize = 4; |
170 | 48.3k | SStream_concat0(O, "dword ptr "); |
171 | 48.3k | printMemReference(MI, OpNo, O); |
172 | 48.3k | } |
173 | | |
174 | | static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O) |
175 | 23.0k | { |
176 | 23.0k | SStream_concat0(O, "qword ptr "); |
177 | 23.0k | MI->x86opsize = 8; |
178 | 23.0k | printMemReference(MI, OpNo, O); |
179 | 23.0k | } |
180 | | |
181 | | static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O) |
182 | 9.09k | { |
183 | 9.09k | SStream_concat0(O, "xmmword ptr "); |
184 | 9.09k | MI->x86opsize = 16; |
185 | 9.09k | printMemReference(MI, OpNo, O); |
186 | 9.09k | } |
187 | | |
188 | | static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O) |
189 | 4.65k | { |
190 | 4.65k | SStream_concat0(O, "zmmword ptr "); |
191 | 4.65k | MI->x86opsize = 64; |
192 | 4.65k | printMemReference(MI, OpNo, O); |
193 | 4.65k | } |
194 | | |
195 | | #ifndef CAPSTONE_X86_REDUCE |
196 | | static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O) |
197 | 5.21k | { |
198 | 5.21k | SStream_concat0(O, "ymmword ptr "); |
199 | 5.21k | MI->x86opsize = 32; |
200 | 5.21k | printMemReference(MI, OpNo, O); |
201 | 5.21k | } |
202 | | |
203 | | static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O) |
204 | 7.78k | { |
205 | 7.78k | switch (MCInst_getOpcode(MI)) { |
206 | 5.94k | default: |
207 | 5.94k | SStream_concat0(O, "dword ptr "); |
208 | 5.94k | MI->x86opsize = 4; |
209 | 5.94k | break; |
210 | 581 | case X86_FSTENVm: |
211 | 1.84k | case X86_FLDENVm: |
212 | | // TODO: fix this in tablegen instead |
213 | 1.84k | switch (x86_get_bit_mode(MI->csh->mode)) { |
214 | 0 | default: // never reach |
215 | 0 | break; |
216 | 714 | case CS_MODE_16: |
217 | 714 | MI->x86opsize = 14; |
218 | 714 | break; |
219 | 535 | case CS_MODE_32: |
220 | 1.13k | case CS_MODE_64: |
221 | 1.13k | MI->x86opsize = 28; |
222 | 1.13k | break; |
223 | 1.84k | } |
224 | 1.84k | break; |
225 | 7.78k | } |
226 | | |
227 | 7.78k | printMemReference(MI, OpNo, O); |
228 | 7.78k | } |
229 | | |
230 | | static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O) |
231 | 4.15k | { |
232 | | // TODO: fix COMISD in Tablegen instead (#1456) |
233 | 4.15k | if (MI->op1_size == 16) { |
234 | | // printf("printf64mem id = %u\n", MCInst_getOpcode(MI)); |
235 | 1.68k | switch (MCInst_getOpcode(MI)) { |
236 | 1.68k | default: |
237 | 1.68k | SStream_concat0(O, "qword ptr "); |
238 | 1.68k | MI->x86opsize = 8; |
239 | 1.68k | break; |
240 | 0 | case X86_MOVPQI2QImr: |
241 | 0 | SStream_concat0(O, "xmmword ptr "); |
242 | 0 | MI->x86opsize = 16; |
243 | 0 | break; |
244 | 1.68k | } |
245 | 2.46k | } else { |
246 | 2.46k | SStream_concat0(O, "qword ptr "); |
247 | 2.46k | MI->x86opsize = 8; |
248 | 2.46k | } |
249 | | |
250 | 4.15k | printMemReference(MI, OpNo, O); |
251 | 4.15k | } |
252 | | |
253 | | static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O) |
254 | 993 | { |
255 | 993 | switch (MCInst_getOpcode(MI)) { |
256 | 509 | default: |
257 | 509 | SStream_concat0(O, "xword ptr "); |
258 | 509 | break; |
259 | 285 | case X86_FBLDm: |
260 | 484 | case X86_FBSTPm: |
261 | 484 | break; |
262 | 993 | } |
263 | | |
264 | 993 | MI->x86opsize = 10; |
265 | 993 | printMemReference(MI, OpNo, O); |
266 | 993 | } |
267 | | |
268 | | static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O) |
269 | 5.82k | { |
270 | 5.82k | SStream_concat0(O, "xmmword ptr "); |
271 | 5.82k | MI->x86opsize = 16; |
272 | 5.82k | printMemReference(MI, OpNo, O); |
273 | 5.82k | } |
274 | | |
275 | | static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O) |
276 | 4.26k | { |
277 | 4.26k | SStream_concat0(O, "ymmword ptr "); |
278 | 4.26k | MI->x86opsize = 32; |
279 | 4.26k | printMemReference(MI, OpNo, O); |
280 | 4.26k | } |
281 | | |
282 | | static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O) |
283 | 3.48k | { |
284 | 3.48k | SStream_concat0(O, "zmmword ptr "); |
285 | 3.48k | MI->x86opsize = 64; |
286 | 3.48k | printMemReference(MI, OpNo, O); |
287 | 3.48k | } |
288 | | #endif |
289 | | |
290 | | static const char *getRegisterName(unsigned RegNo); |
291 | | static void printRegName(SStream *OS, unsigned RegNo) |
292 | 784k | { |
293 | 784k | SStream_concat0(OS, getRegisterName(RegNo)); |
294 | 784k | } |
295 | | |
296 | | // for MASM syntax, 0x123 = 123h, 0xA123 = 0A123h |
297 | | // this function tell us if we need to have prefix 0 in front of a number |
298 | | static bool need_zero_prefix(uint64_t imm) |
299 | 0 | { |
300 | | // find the first hex letter representing imm |
301 | 0 | while (imm >= 0x10) |
302 | 0 | imm >>= 4; |
303 | |
|
304 | 0 | if (imm < 0xa) |
305 | 0 | return false; |
306 | 0 | else // this need 0 prefix |
307 | 0 | return true; |
308 | 0 | } |
309 | | |
310 | | static void printImm(MCInst *MI, SStream *O, int64_t imm, bool positive) |
311 | 197k | { |
312 | 197k | if (positive) { |
313 | | // always print this number in positive form |
314 | 169k | if (MI->csh->syntax == CS_OPT_SYNTAX_MASM) { |
315 | 0 | if (imm < 0) { |
316 | 0 | if (MI->op1_size) { |
317 | 0 | switch (MI->op1_size) { |
318 | 0 | default: |
319 | 0 | break; |
320 | 0 | case 1: |
321 | 0 | imm &= 0xff; |
322 | 0 | break; |
323 | 0 | case 2: |
324 | 0 | imm &= 0xffff; |
325 | 0 | break; |
326 | 0 | case 4: |
327 | 0 | imm &= 0xffffffff; |
328 | 0 | break; |
329 | 0 | } |
330 | 0 | } |
331 | | |
332 | 0 | if (imm == 0x8000000000000000LL) // imm == -imm |
333 | 0 | SStream_concat0(O, "8000000000000000h"); |
334 | 0 | else if (need_zero_prefix(imm)) |
335 | 0 | SStream_concat(O, "0%" PRIx64 "h", imm); |
336 | 0 | else |
337 | 0 | SStream_concat(O, "%" PRIx64 "h", imm); |
338 | 0 | } else { |
339 | 0 | if (imm > HEX_THRESHOLD) { |
340 | 0 | if (need_zero_prefix(imm)) |
341 | 0 | SStream_concat(O, |
342 | 0 | "0%" PRIx64 "h", |
343 | 0 | imm); |
344 | 0 | else |
345 | 0 | SStream_concat( |
346 | 0 | O, "%" PRIx64 "h", imm); |
347 | 0 | } else |
348 | 0 | SStream_concat(O, "%" PRIu64, imm); |
349 | 0 | } |
350 | 169k | } else { // Intel syntax |
351 | 169k | if (imm < 0) { |
352 | 3.37k | if (MI->op1_size) { |
353 | 1.22k | switch (MI->op1_size) { |
354 | 1.22k | default: |
355 | 1.22k | break; |
356 | 1.22k | case 1: |
357 | 0 | imm &= 0xff; |
358 | 0 | break; |
359 | 0 | case 2: |
360 | 0 | imm &= 0xffff; |
361 | 0 | break; |
362 | 0 | case 4: |
363 | 0 | imm &= 0xffffffff; |
364 | 0 | break; |
365 | 1.22k | } |
366 | 1.22k | } |
367 | | |
368 | 3.37k | SStream_concat(O, "0x%" PRIx64, imm); |
369 | 166k | } else { |
370 | 166k | if (imm > HEX_THRESHOLD) |
371 | 151k | SStream_concat(O, "0x%" PRIx64, imm); |
372 | 15.1k | else |
373 | 15.1k | SStream_concat(O, "%" PRIu64, imm); |
374 | 166k | } |
375 | 169k | } |
376 | 169k | } else { |
377 | 27.9k | if (MI->csh->syntax == CS_OPT_SYNTAX_MASM) { |
378 | 0 | if (imm < 0) { |
379 | 0 | if (imm == 0x8000000000000000LL) // imm == -imm |
380 | 0 | SStream_concat0(O, "8000000000000000h"); |
381 | 0 | else if (imm < -HEX_THRESHOLD) { |
382 | 0 | if (need_zero_prefix(imm)) |
383 | 0 | SStream_concat(O, |
384 | 0 | "-0%" PRIx64 "h", |
385 | 0 | -imm); |
386 | 0 | else |
387 | 0 | SStream_concat(O, |
388 | 0 | "-%" PRIx64 "h", |
389 | 0 | -imm); |
390 | 0 | } else |
391 | 0 | SStream_concat(O, "-%" PRIu64, -imm); |
392 | 0 | } else { |
393 | 0 | if (imm > HEX_THRESHOLD) { |
394 | 0 | if (need_zero_prefix(imm)) |
395 | 0 | SStream_concat(O, |
396 | 0 | "0%" PRIx64 "h", |
397 | 0 | imm); |
398 | 0 | else |
399 | 0 | SStream_concat( |
400 | 0 | O, "%" PRIx64 "h", imm); |
401 | 0 | } else |
402 | 0 | SStream_concat(O, "%" PRIu64, imm); |
403 | 0 | } |
404 | 27.9k | } else { // Intel syntax |
405 | 27.9k | if (imm < 0) { |
406 | 4.69k | if (imm == 0x8000000000000000LL) // imm == -imm |
407 | 0 | SStream_concat0(O, |
408 | 0 | "0x8000000000000000"); |
409 | 4.69k | else if (imm < -HEX_THRESHOLD) |
410 | 4.16k | SStream_concat(O, "-0x%" PRIx64, -imm); |
411 | 530 | else |
412 | 530 | SStream_concat(O, "-%" PRIu64, -imm); |
413 | | |
414 | 23.2k | } else { |
415 | 23.2k | if (imm > HEX_THRESHOLD) |
416 | 19.3k | SStream_concat(O, "0x%" PRIx64, imm); |
417 | 3.84k | else |
418 | 3.84k | SStream_concat(O, "%" PRIu64, imm); |
419 | 23.2k | } |
420 | 27.9k | } |
421 | 27.9k | } |
422 | 197k | } |
423 | | |
424 | | // local printOperand, without updating public operands |
425 | | static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) |
426 | 270k | { |
427 | 270k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
428 | 270k | if (MCOperand_isReg(Op)) { |
429 | 270k | printRegName(O, MCOperand_getReg(Op)); |
430 | 270k | } else if (MCOperand_isImm(Op)) { |
431 | 0 | int64_t imm = MCOperand_getImm(Op); |
432 | 0 | printImm(MI, O, imm, MI->csh->imm_unsigned); |
433 | 0 | } |
434 | 270k | } |
435 | | |
436 | | #ifndef CAPSTONE_DIET |
437 | | // copy & normalize access info |
438 | | static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, |
439 | | uint64_t *eflags) |
440 | 1.38M | { |
441 | 1.38M | #ifndef CAPSTONE_DIET |
442 | 1.38M | uint8_t i; |
443 | 1.38M | const uint8_t *arr = X86_get_op_access(h, id, eflags); |
444 | | |
445 | | // initialize access |
446 | 1.38M | memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0])); |
447 | | |
448 | 1.38M | if (!arr) { |
449 | 0 | access[0] = 0; |
450 | 0 | return; |
451 | 0 | } |
452 | | |
453 | | // copy to access but zero out CS_AC_IGNORE |
454 | 4.11M | for (i = 0; arr[i]; i++) { |
455 | 2.72M | if (arr[i] != CS_AC_IGNORE) |
456 | 2.31M | access[i] = arr[i]; |
457 | 408k | else |
458 | 408k | access[i] = 0; |
459 | 2.72M | } |
460 | | |
461 | | // mark the end of array |
462 | 1.38M | access[i] = 0; |
463 | 1.38M | #endif |
464 | 1.38M | } |
465 | | #endif |
466 | | |
467 | | static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O) |
468 | 26.4k | { |
469 | 26.4k | MCOperand *SegReg; |
470 | 26.4k | int reg; |
471 | | |
472 | 26.4k | if (MI->csh->detail_opt) { |
473 | 26.4k | #ifndef CAPSTONE_DIET |
474 | 26.4k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
475 | 26.4k | #endif |
476 | | |
477 | 26.4k | MI->flat_insn->detail->x86 |
478 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
479 | 26.4k | .type = X86_OP_MEM; |
480 | 26.4k | MI->flat_insn->detail->x86 |
481 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
482 | 26.4k | .size = MI->x86opsize; |
483 | 26.4k | MI->flat_insn->detail->x86 |
484 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
485 | 26.4k | .mem.segment = X86_REG_INVALID; |
486 | 26.4k | MI->flat_insn->detail->x86 |
487 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
488 | 26.4k | .mem.base = X86_REG_INVALID; |
489 | 26.4k | MI->flat_insn->detail->x86 |
490 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
491 | 26.4k | .mem.index = X86_REG_INVALID; |
492 | 26.4k | MI->flat_insn->detail->x86 |
493 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
494 | 26.4k | .mem.scale = 1; |
495 | 26.4k | MI->flat_insn->detail->x86 |
496 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
497 | 26.4k | .mem.disp = 0; |
498 | | |
499 | 26.4k | #ifndef CAPSTONE_DIET |
500 | 26.4k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
501 | 26.4k | &MI->flat_insn->detail->x86.eflags); |
502 | 26.4k | MI->flat_insn->detail->x86 |
503 | 26.4k | .operands[MI->flat_insn->detail->x86.op_count] |
504 | 26.4k | .access = access[MI->flat_insn->detail->x86.op_count]; |
505 | 26.4k | #endif |
506 | 26.4k | } |
507 | | |
508 | 26.4k | SegReg = MCInst_getOperand(MI, Op + 1); |
509 | 26.4k | reg = MCOperand_getReg(SegReg); |
510 | | |
511 | | // If this has a segment register, print it. |
512 | 26.4k | if (reg) { |
513 | 969 | _printOperand(MI, Op + 1, O); |
514 | 969 | if (MI->csh->detail_opt) { |
515 | 969 | MI->flat_insn->detail->x86 |
516 | 969 | .operands[MI->flat_insn->detail->x86.op_count] |
517 | 969 | .mem.segment = X86_register_map(reg); |
518 | 969 | } |
519 | 969 | SStream_concat0(O, ":"); |
520 | 969 | } |
521 | | |
522 | 26.4k | SStream_concat0(O, "["); |
523 | 26.4k | set_mem_access(MI, true); |
524 | 26.4k | printOperand(MI, Op, O); |
525 | 26.4k | SStream_concat0(O, "]"); |
526 | 26.4k | set_mem_access(MI, false); |
527 | 26.4k | } |
528 | | |
529 | | static void printDstIdx(MCInst *MI, unsigned Op, SStream *O) |
530 | 17.5k | { |
531 | 17.5k | if (MI->csh->detail_opt) { |
532 | 17.5k | #ifndef CAPSTONE_DIET |
533 | 17.5k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
534 | 17.5k | #endif |
535 | | |
536 | 17.5k | MI->flat_insn->detail->x86 |
537 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
538 | 17.5k | .type = X86_OP_MEM; |
539 | 17.5k | MI->flat_insn->detail->x86 |
540 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
541 | 17.5k | .size = MI->x86opsize; |
542 | 17.5k | MI->flat_insn->detail->x86 |
543 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
544 | 17.5k | .mem.segment = X86_REG_INVALID; |
545 | 17.5k | MI->flat_insn->detail->x86 |
546 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
547 | 17.5k | .mem.base = X86_REG_INVALID; |
548 | 17.5k | MI->flat_insn->detail->x86 |
549 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
550 | 17.5k | .mem.index = X86_REG_INVALID; |
551 | 17.5k | MI->flat_insn->detail->x86 |
552 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
553 | 17.5k | .mem.scale = 1; |
554 | 17.5k | MI->flat_insn->detail->x86 |
555 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
556 | 17.5k | .mem.disp = 0; |
557 | | |
558 | 17.5k | #ifndef CAPSTONE_DIET |
559 | 17.5k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
560 | 17.5k | &MI->flat_insn->detail->x86.eflags); |
561 | 17.5k | MI->flat_insn->detail->x86 |
562 | 17.5k | .operands[MI->flat_insn->detail->x86.op_count] |
563 | 17.5k | .access = access[MI->flat_insn->detail->x86.op_count]; |
564 | 17.5k | #endif |
565 | 17.5k | } |
566 | | |
567 | | // DI accesses are always ES-based on non-64bit mode |
568 | 17.5k | if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) { |
569 | 10.8k | SStream_concat0(O, "es:["); |
570 | 10.8k | if (MI->csh->detail_opt) { |
571 | 10.8k | MI->flat_insn->detail->x86 |
572 | 10.8k | .operands[MI->flat_insn->detail->x86.op_count] |
573 | 10.8k | .mem.segment = X86_REG_ES; |
574 | 10.8k | } |
575 | 10.8k | } else |
576 | 6.74k | SStream_concat0(O, "["); |
577 | | |
578 | 17.5k | set_mem_access(MI, true); |
579 | 17.5k | printOperand(MI, Op, O); |
580 | 17.5k | SStream_concat0(O, "]"); |
581 | 17.5k | set_mem_access(MI, false); |
582 | 17.5k | } |
583 | | |
584 | | static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O) |
585 | 9.52k | { |
586 | 9.52k | SStream_concat0(O, "byte ptr "); |
587 | 9.52k | MI->x86opsize = 1; |
588 | 9.52k | printSrcIdx(MI, OpNo, O); |
589 | 9.52k | } |
590 | | |
591 | | static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O) |
592 | 4.79k | { |
593 | 4.79k | SStream_concat0(O, "word ptr "); |
594 | 4.79k | MI->x86opsize = 2; |
595 | 4.79k | printSrcIdx(MI, OpNo, O); |
596 | 4.79k | } |
597 | | |
598 | | static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O) |
599 | 9.33k | { |
600 | 9.33k | SStream_concat0(O, "dword ptr "); |
601 | 9.33k | MI->x86opsize = 4; |
602 | 9.33k | printSrcIdx(MI, OpNo, O); |
603 | 9.33k | } |
604 | | |
605 | | static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O) |
606 | 2.79k | { |
607 | 2.79k | SStream_concat0(O, "qword ptr "); |
608 | 2.79k | MI->x86opsize = 8; |
609 | 2.79k | printSrcIdx(MI, OpNo, O); |
610 | 2.79k | } |
611 | | |
612 | | static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O) |
613 | 10.5k | { |
614 | 10.5k | SStream_concat0(O, "byte ptr "); |
615 | 10.5k | MI->x86opsize = 1; |
616 | 10.5k | printDstIdx(MI, OpNo, O); |
617 | 10.5k | } |
618 | | |
619 | | static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O) |
620 | 5.51k | { |
621 | 5.51k | SStream_concat0(O, "word ptr "); |
622 | 5.51k | MI->x86opsize = 2; |
623 | 5.51k | printDstIdx(MI, OpNo, O); |
624 | 5.51k | } |
625 | | |
626 | | static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O) |
627 | 11.8k | { |
628 | 11.8k | SStream_concat0(O, "dword ptr "); |
629 | 11.8k | MI->x86opsize = 4; |
630 | 11.8k | printDstIdx(MI, OpNo, O); |
631 | 11.8k | } |
632 | | |
633 | | static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O) |
634 | 3.52k | { |
635 | 3.52k | SStream_concat0(O, "qword ptr "); |
636 | 3.52k | MI->x86opsize = 8; |
637 | 3.52k | printDstIdx(MI, OpNo, O); |
638 | 3.52k | } |
639 | | |
640 | | static void printMemOffset(MCInst *MI, unsigned Op, SStream *O) |
641 | 4.50k | { |
642 | 4.50k | MCOperand *DispSpec = MCInst_getOperand(MI, Op); |
643 | 4.50k | MCOperand *SegReg = MCInst_getOperand(MI, Op + 1); |
644 | 4.50k | int reg; |
645 | | |
646 | 4.50k | if (MI->csh->detail_opt) { |
647 | 4.50k | #ifndef CAPSTONE_DIET |
648 | 4.50k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
649 | 4.50k | #endif |
650 | | |
651 | 4.50k | MI->flat_insn->detail->x86 |
652 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
653 | 4.50k | .type = X86_OP_MEM; |
654 | 4.50k | MI->flat_insn->detail->x86 |
655 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
656 | 4.50k | .size = MI->x86opsize; |
657 | 4.50k | MI->flat_insn->detail->x86 |
658 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
659 | 4.50k | .mem.segment = X86_REG_INVALID; |
660 | 4.50k | MI->flat_insn->detail->x86 |
661 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
662 | 4.50k | .mem.base = X86_REG_INVALID; |
663 | 4.50k | MI->flat_insn->detail->x86 |
664 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
665 | 4.50k | .mem.index = X86_REG_INVALID; |
666 | 4.50k | MI->flat_insn->detail->x86 |
667 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
668 | 4.50k | .mem.scale = 1; |
669 | 4.50k | MI->flat_insn->detail->x86 |
670 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
671 | 4.50k | .mem.disp = 0; |
672 | | |
673 | 4.50k | #ifndef CAPSTONE_DIET |
674 | 4.50k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
675 | 4.50k | &MI->flat_insn->detail->x86.eflags); |
676 | 4.50k | MI->flat_insn->detail->x86 |
677 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
678 | 4.50k | .access = access[MI->flat_insn->detail->x86.op_count]; |
679 | 4.50k | #endif |
680 | 4.50k | } |
681 | | |
682 | | // If this has a segment register, print it. |
683 | 4.50k | reg = MCOperand_getReg(SegReg); |
684 | 4.50k | if (reg) { |
685 | 547 | _printOperand(MI, Op + 1, O); |
686 | 547 | SStream_concat0(O, ":"); |
687 | 547 | if (MI->csh->detail_opt) { |
688 | 547 | MI->flat_insn->detail->x86 |
689 | 547 | .operands[MI->flat_insn->detail->x86.op_count] |
690 | 547 | .mem.segment = X86_register_map(reg); |
691 | 547 | } |
692 | 547 | } |
693 | | |
694 | 4.50k | SStream_concat0(O, "["); |
695 | | |
696 | 4.50k | if (MCOperand_isImm(DispSpec)) { |
697 | 4.50k | int64_t imm = MCOperand_getImm(DispSpec); |
698 | 4.50k | if (MI->csh->detail_opt) |
699 | 4.50k | MI->flat_insn->detail->x86 |
700 | 4.50k | .operands[MI->flat_insn->detail->x86.op_count] |
701 | 4.50k | .mem.disp = imm; |
702 | | |
703 | 4.50k | if (imm < 0) |
704 | 839 | printImm(MI, O, |
705 | 839 | x86_get_address_mask(MI->csh->mode) & imm, |
706 | 839 | true); |
707 | 3.66k | else |
708 | 3.66k | printImm(MI, O, imm, true); |
709 | 4.50k | } |
710 | | |
711 | 4.50k | SStream_concat0(O, "]"); |
712 | | |
713 | 4.50k | if (MI->csh->detail_opt) |
714 | 4.50k | MI->flat_insn->detail->x86.op_count++; |
715 | | |
716 | 4.50k | if (MI->op1_size == 0) |
717 | 4.50k | MI->op1_size = MI->x86opsize; |
718 | 4.50k | } |
719 | | |
720 | | static void printU8Imm(MCInst *MI, unsigned Op, SStream *O) |
721 | 39.2k | { |
722 | 39.2k | uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff; |
723 | | |
724 | 39.2k | printImm(MI, O, val, true); |
725 | | |
726 | 39.2k | if (MI->csh->detail_opt) { |
727 | 39.2k | #ifndef CAPSTONE_DIET |
728 | 39.2k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
729 | 39.2k | #endif |
730 | | |
731 | 39.2k | MI->flat_insn->detail->x86 |
732 | 39.2k | .operands[MI->flat_insn->detail->x86.op_count] |
733 | 39.2k | .type = X86_OP_IMM; |
734 | 39.2k | MI->flat_insn->detail->x86 |
735 | 39.2k | .operands[MI->flat_insn->detail->x86.op_count] |
736 | 39.2k | .imm = val; |
737 | 39.2k | MI->flat_insn->detail->x86 |
738 | 39.2k | .operands[MI->flat_insn->detail->x86.op_count] |
739 | 39.2k | .size = 1; |
740 | | |
741 | 39.2k | #ifndef CAPSTONE_DIET |
742 | 39.2k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
743 | 39.2k | &MI->flat_insn->detail->x86.eflags); |
744 | 39.2k | MI->flat_insn->detail->x86 |
745 | 39.2k | .operands[MI->flat_insn->detail->x86.op_count] |
746 | 39.2k | .access = access[MI->flat_insn->detail->x86.op_count]; |
747 | 39.2k | #endif |
748 | | |
749 | 39.2k | MI->flat_insn->detail->x86.op_count++; |
750 | 39.2k | } |
751 | 39.2k | } |
752 | | |
753 | | static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O) |
754 | 2.06k | { |
755 | 2.06k | SStream_concat0(O, "byte ptr "); |
756 | 2.06k | MI->x86opsize = 1; |
757 | 2.06k | printMemOffset(MI, OpNo, O); |
758 | 2.06k | } |
759 | | |
760 | | static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O) |
761 | 778 | { |
762 | 778 | SStream_concat0(O, "word ptr "); |
763 | 778 | MI->x86opsize = 2; |
764 | 778 | printMemOffset(MI, OpNo, O); |
765 | 778 | } |
766 | | |
767 | | static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O) |
768 | 1.26k | { |
769 | 1.26k | SStream_concat0(O, "dword ptr "); |
770 | 1.26k | MI->x86opsize = 4; |
771 | 1.26k | printMemOffset(MI, OpNo, O); |
772 | 1.26k | } |
773 | | |
774 | | static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O) |
775 | 393 | { |
776 | 393 | SStream_concat0(O, "qword ptr "); |
777 | 393 | MI->x86opsize = 8; |
778 | 393 | printMemOffset(MI, OpNo, O); |
779 | 393 | } |
780 | | |
781 | | static void printInstruction(MCInst *MI, SStream *O); |
782 | | |
783 | | static void intel_printInst(MCInst *MI, SStream *O, void *Info) |
784 | 308k | { |
785 | 308k | x86_reg reg = X86_REG_INVALID, reg2; |
786 | 308k | enum cs_ac_type access1, access2; |
787 | | |
788 | | // printf("opcode = %u\n", MCInst_getOpcode(MI)); |
789 | | |
790 | | // perhaps this instruction does not need printer |
791 | 308k | if (MI->assembly[0]) { |
792 | 0 | strncpy(O->buffer, MI->assembly, sizeof(O->buffer)); |
793 | 0 | return; |
794 | 0 | } |
795 | | |
796 | 308k | X86_lockrep(MI, O); |
797 | 308k | printInstruction(MI, O); |
798 | | |
799 | 308k | if (MI->csh->detail_opt) { |
800 | 308k | #ifndef CAPSTONE_DIET |
801 | 308k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE] = { 0 }; |
802 | 308k | #endif |
803 | | |
804 | | // first op can be embedded in the asm by llvm. |
805 | | // so we have to add the missing register as the first operand |
806 | 308k | reg = X86_insn_reg_intel_h(MI->csh, MCInst_getOpcode(MI), |
807 | 308k | &access1); |
808 | 308k | if (reg) { |
809 | | // shift all the ops right to leave 1st slot for this new register op |
810 | 28.6k | memmove(&(MI->flat_insn->detail->x86.operands[1]), |
811 | 28.6k | &(MI->flat_insn->detail->x86.operands[0]), |
812 | 28.6k | sizeof(MI->flat_insn->detail->x86.operands[0]) * |
813 | 28.6k | (ARR_SIZE(MI->flat_insn->detail->x86 |
814 | 28.6k | .operands) - |
815 | 28.6k | 1)); |
816 | 28.6k | memset(&(MI->flat_insn->detail->x86.operands[0]), 0, |
817 | 28.6k | sizeof(MI->flat_insn->detail->x86.operands[0])); |
818 | 28.6k | MI->flat_insn->detail->x86.operands[0].type = |
819 | 28.6k | X86_OP_REG; |
820 | 28.6k | MI->flat_insn->detail->x86.operands[0].reg = reg; |
821 | 28.6k | MI->flat_insn->detail->x86.operands[0].size = |
822 | 28.6k | MI->csh->regsize_map[reg]; |
823 | 28.6k | MI->flat_insn->detail->x86.operands[0].access = access1; |
824 | 28.6k | MI->flat_insn->detail->x86.op_count++; |
825 | 279k | } else { |
826 | 279k | if (X86_insn_reg_intel2(MCInst_getOpcode(MI), ®, |
827 | 279k | &access1, ®2, &access2)) { |
828 | 5.07k | MI->flat_insn->detail->x86.operands[0].type = |
829 | 5.07k | X86_OP_REG; |
830 | 5.07k | MI->flat_insn->detail->x86.operands[0].reg = |
831 | 5.07k | reg; |
832 | 5.07k | MI->flat_insn->detail->x86.operands[0].size = |
833 | 5.07k | MI->csh->regsize_map[reg]; |
834 | 5.07k | MI->flat_insn->detail->x86.operands[0].access = |
835 | 5.07k | access1; |
836 | 5.07k | MI->flat_insn->detail->x86.operands[1].type = |
837 | 5.07k | X86_OP_REG; |
838 | 5.07k | MI->flat_insn->detail->x86.operands[1].reg = |
839 | 5.07k | reg2; |
840 | 5.07k | MI->flat_insn->detail->x86.operands[1].size = |
841 | 5.07k | MI->csh->regsize_map[reg2]; |
842 | 5.07k | MI->flat_insn->detail->x86.operands[1].access = |
843 | 5.07k | access2; |
844 | 5.07k | MI->flat_insn->detail->x86.op_count = 2; |
845 | 5.07k | } |
846 | 279k | } |
847 | | |
848 | 308k | #ifndef CAPSTONE_DIET |
849 | 308k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
850 | 308k | &MI->flat_insn->detail->x86.eflags); |
851 | 873k | for (uint8_t i = 0; i < MI->flat_insn->detail->x86.op_count && |
852 | 565k | i < ARR_SIZE(access); |
853 | 565k | i++) { |
854 | 565k | MI->flat_insn->detail->x86.operands[i].access = |
855 | 565k | access[i]; |
856 | 565k | } |
857 | 308k | #endif |
858 | 308k | } |
859 | | |
860 | 308k | if (MI->op1_size == 0 && reg) |
861 | 18.9k | MI->op1_size = MI->csh->regsize_map[reg]; |
862 | 308k | } |
863 | | |
864 | | void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info) |
865 | 308k | { |
866 | 308k | #if !defined(CAPSTONE_DIET) && !defined(CAPSTONE_X86_ATT_DISABLE) |
867 | 308k | if (MI->csh->detail_opt & CS_OPT_DETAIL_ATT_ORDER) { |
868 | 0 | X86_printInst_detail_syntax(MI, O, Info, intel_printInst, |
869 | 0 | X86_ATT_printInst, |
870 | 0 | CS_OPT_SYNTAX_ATT); |
871 | 0 | return; |
872 | 0 | } |
873 | 308k | #endif |
874 | 308k | intel_printInst(MI, O, Info); |
875 | 308k | } |
876 | | |
877 | | /// printPCRelImm - This is used to print an immediate value that ends up |
878 | | /// being encoded as a pc-relative value. |
879 | | static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O) |
880 | 19.4k | { |
881 | 19.4k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
882 | 19.4k | if (MCOperand_isImm(Op)) { |
883 | 19.4k | int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + |
884 | 19.4k | MI->address; |
885 | 19.4k | uint8_t opsize = X86_immediate_size(MI->Opcode, NULL); |
886 | | |
887 | | // truncate imm for non-64bit |
888 | 19.4k | if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) { |
889 | 12.3k | imm = imm & 0xffffffff; |
890 | 12.3k | } else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) && |
891 | 0 | MI->imm_size == 2) { |
892 | 0 | imm &= 0xffff; |
893 | 0 | } |
894 | | |
895 | 19.4k | printImm(MI, O, imm, true); |
896 | | |
897 | 19.4k | if (MI->csh->detail_opt) { |
898 | 19.4k | #ifndef CAPSTONE_DIET |
899 | 19.4k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
900 | 19.4k | #endif |
901 | | |
902 | 19.4k | MI->flat_insn->detail->x86 |
903 | 19.4k | .operands[MI->flat_insn->detail->x86.op_count] |
904 | 19.4k | .type = X86_OP_IMM; |
905 | | // if op_count > 0, then this operand's size is taken from the destination op |
906 | 19.4k | if (MI->flat_insn->detail->x86.op_count > 0) |
907 | 0 | MI->flat_insn->detail->x86 |
908 | 0 | .operands[MI->flat_insn->detail->x86 |
909 | 0 | .op_count] |
910 | 0 | .size = |
911 | 0 | MI->flat_insn->detail->x86.operands[0] |
912 | 0 | .size; |
913 | 19.4k | else if (opsize > 0) |
914 | 743 | MI->flat_insn->detail->x86 |
915 | 743 | .operands[MI->flat_insn->detail->x86 |
916 | 743 | .op_count] |
917 | 743 | .size = opsize; |
918 | 18.6k | else |
919 | 18.6k | MI->flat_insn->detail->x86 |
920 | 18.6k | .operands[MI->flat_insn->detail->x86 |
921 | 18.6k | .op_count] |
922 | 18.6k | .size = MI->imm_size; |
923 | 19.4k | MI->flat_insn->detail->x86 |
924 | 19.4k | .operands[MI->flat_insn->detail->x86.op_count] |
925 | 19.4k | .imm = imm; |
926 | | |
927 | 19.4k | #ifndef CAPSTONE_DIET |
928 | 19.4k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
929 | 19.4k | &MI->flat_insn->detail->x86.eflags); |
930 | 19.4k | MI->flat_insn->detail->x86 |
931 | 19.4k | .operands[MI->flat_insn->detail->x86.op_count] |
932 | 19.4k | .access = |
933 | 19.4k | access[MI->flat_insn->detail->x86.op_count]; |
934 | 19.4k | #endif |
935 | | |
936 | 19.4k | MI->flat_insn->detail->x86.op_count++; |
937 | 19.4k | } |
938 | | |
939 | 19.4k | if (MI->op1_size == 0) |
940 | 19.4k | MI->op1_size = MI->imm_size; |
941 | 19.4k | } |
942 | 19.4k | } |
943 | | |
944 | | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) |
945 | 573k | { |
946 | 573k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
947 | | |
948 | 573k | if (MCOperand_isReg(Op)) { |
949 | 513k | unsigned int reg = MCOperand_getReg(Op); |
950 | | |
951 | 513k | printRegName(O, reg); |
952 | 513k | if (MI->csh->detail_opt) { |
953 | 513k | if (MI->csh->doing_mem) { |
954 | 57.8k | MI->flat_insn->detail->x86 |
955 | 57.8k | .operands[MI->flat_insn->detail->x86 |
956 | 57.8k | .op_count] |
957 | 57.8k | .mem.base = X86_register_map(reg); |
958 | 455k | } else { |
959 | 455k | #ifndef CAPSTONE_DIET |
960 | 455k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
961 | 455k | #endif |
962 | | |
963 | 455k | MI->flat_insn->detail->x86 |
964 | 455k | .operands[MI->flat_insn->detail->x86 |
965 | 455k | .op_count] |
966 | 455k | .type = X86_OP_REG; |
967 | 455k | MI->flat_insn->detail->x86 |
968 | 455k | .operands[MI->flat_insn->detail->x86 |
969 | 455k | .op_count] |
970 | 455k | .reg = X86_register_map(reg); |
971 | 455k | MI->flat_insn->detail->x86 |
972 | 455k | .operands[MI->flat_insn->detail->x86 |
973 | 455k | .op_count] |
974 | 455k | .size = |
975 | 455k | MI->csh->regsize_map[X86_register_map( |
976 | 455k | reg)]; |
977 | | |
978 | 455k | #ifndef CAPSTONE_DIET |
979 | 455k | get_op_access( |
980 | 455k | MI->csh, MCInst_getOpcode(MI), access, |
981 | 455k | &MI->flat_insn->detail->x86.eflags); |
982 | 455k | MI->flat_insn->detail->x86 |
983 | 455k | .operands[MI->flat_insn->detail->x86 |
984 | 455k | .op_count] |
985 | 455k | .access = |
986 | 455k | access[MI->flat_insn->detail->x86 |
987 | 455k | .op_count]; |
988 | 455k | #endif |
989 | | |
990 | 455k | MI->flat_insn->detail->x86.op_count++; |
991 | 455k | } |
992 | 513k | } |
993 | | |
994 | 513k | if (MI->op1_size == 0) |
995 | 260k | MI->op1_size = |
996 | 260k | MI->csh->regsize_map[X86_register_map(reg)]; |
997 | 513k | } else if (MCOperand_isImm(Op)) { |
998 | 59.6k | uint8_t encsize; |
999 | 59.6k | int64_t imm = MCOperand_getImm(Op); |
1000 | 59.6k | uint8_t opsize = |
1001 | 59.6k | X86_immediate_size(MCInst_getOpcode(MI), &encsize); |
1002 | | |
1003 | 59.6k | if (opsize == 1) // print 1 byte immediate in positive form |
1004 | 24.3k | imm = imm & 0xff; |
1005 | | |
1006 | | // printf(">>> id = %u\n", MI->flat_insn->id); |
1007 | 59.6k | switch (MI->flat_insn->id) { |
1008 | 27.9k | default: |
1009 | 27.9k | printImm(MI, O, imm, MI->csh->imm_unsigned); |
1010 | 27.9k | break; |
1011 | | |
1012 | 426 | case X86_INS_MOVABS: |
1013 | 7.34k | case X86_INS_MOV: |
1014 | | // do not print number in negative form |
1015 | 7.34k | printImm(MI, O, imm, true); |
1016 | 7.34k | break; |
1017 | | |
1018 | 0 | case X86_INS_IN: |
1019 | 0 | case X86_INS_OUT: |
1020 | 0 | case X86_INS_INT: |
1021 | | // do not print number in negative form |
1022 | 0 | imm = imm & 0xff; |
1023 | 0 | printImm(MI, O, imm, true); |
1024 | 0 | break; |
1025 | | |
1026 | 1.11k | case X86_INS_LCALL: |
1027 | 2.33k | case X86_INS_LJMP: |
1028 | 2.33k | case X86_INS_JMP: |
1029 | | // always print address in positive form |
1030 | 2.33k | if (OpNo == 1) { // ptr16 part |
1031 | 1.16k | imm = imm & 0xffff; |
1032 | 1.16k | opsize = 2; |
1033 | 1.16k | } else |
1034 | 1.16k | opsize = 4; |
1035 | 2.33k | printImm(MI, O, imm, true); |
1036 | 2.33k | break; |
1037 | | |
1038 | 5.43k | case X86_INS_AND: |
1039 | 9.55k | case X86_INS_OR: |
1040 | 14.7k | case X86_INS_XOR: |
1041 | | // do not print number in negative form |
1042 | 14.7k | if (imm >= 0 && imm <= HEX_THRESHOLD) |
1043 | 2.74k | printImm(MI, O, imm, true); |
1044 | 12.0k | else { |
1045 | 12.0k | imm = arch_masks[opsize ? opsize : MI->imm_size] & |
1046 | 12.0k | imm; |
1047 | 12.0k | printImm(MI, O, imm, true); |
1048 | 12.0k | } |
1049 | 14.7k | break; |
1050 | | |
1051 | 6.35k | case X86_INS_RET: |
1052 | 7.33k | case X86_INS_RETF: |
1053 | | // RET imm16 |
1054 | 7.33k | if (imm >= 0 && imm <= HEX_THRESHOLD) |
1055 | 614 | printImm(MI, O, imm, true); |
1056 | 6.72k | else { |
1057 | 6.72k | imm = 0xffff & imm; |
1058 | 6.72k | printImm(MI, O, imm, true); |
1059 | 6.72k | } |
1060 | 7.33k | break; |
1061 | 59.6k | } |
1062 | | |
1063 | 59.6k | if (MI->csh->detail_opt) { |
1064 | 59.6k | if (MI->csh->doing_mem) { |
1065 | 0 | MI->flat_insn->detail->x86 |
1066 | 0 | .operands[MI->flat_insn->detail->x86 |
1067 | 0 | .op_count] |
1068 | 0 | .mem.disp = imm; |
1069 | 59.6k | } else { |
1070 | 59.6k | #ifndef CAPSTONE_DIET |
1071 | 59.6k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
1072 | 59.6k | #endif |
1073 | | |
1074 | 59.6k | MI->flat_insn->detail->x86 |
1075 | 59.6k | .operands[MI->flat_insn->detail->x86 |
1076 | 59.6k | .op_count] |
1077 | 59.6k | .type = X86_OP_IMM; |
1078 | 59.6k | if (opsize > 0) { |
1079 | 48.7k | MI->flat_insn->detail->x86 |
1080 | 48.7k | .operands[MI->flat_insn->detail |
1081 | 48.7k | ->x86.op_count] |
1082 | 48.7k | .size = opsize; |
1083 | 48.7k | MI->flat_insn->detail->x86.encoding |
1084 | 48.7k | .imm_size = encsize; |
1085 | 48.7k | } else if (MI->flat_insn->detail->x86.op_count > |
1086 | 10.9k | 0) { |
1087 | 2.29k | if (MI->flat_insn->id != |
1088 | 2.29k | X86_INS_LCALL && |
1089 | 2.29k | MI->flat_insn->id != X86_INS_LJMP) { |
1090 | 2.29k | MI->flat_insn->detail->x86 |
1091 | 2.29k | .operands[MI->flat_insn |
1092 | 2.29k | ->detail |
1093 | 2.29k | ->x86 |
1094 | 2.29k | .op_count] |
1095 | 2.29k | .size = |
1096 | 2.29k | MI->flat_insn->detail |
1097 | 2.29k | ->x86 |
1098 | 2.29k | .operands[0] |
1099 | 2.29k | .size; |
1100 | 2.29k | } else |
1101 | 0 | MI->flat_insn->detail->x86 |
1102 | 0 | .operands[MI->flat_insn |
1103 | 0 | ->detail |
1104 | 0 | ->x86 |
1105 | 0 | .op_count] |
1106 | 0 | .size = MI->imm_size; |
1107 | 2.29k | } else |
1108 | 8.67k | MI->flat_insn->detail->x86 |
1109 | 8.67k | .operands[MI->flat_insn->detail |
1110 | 8.67k | ->x86.op_count] |
1111 | 8.67k | .size = MI->imm_size; |
1112 | 59.6k | MI->flat_insn->detail->x86 |
1113 | 59.6k | .operands[MI->flat_insn->detail->x86 |
1114 | 59.6k | .op_count] |
1115 | 59.6k | .imm = imm; |
1116 | | |
1117 | 59.6k | #ifndef CAPSTONE_DIET |
1118 | 59.6k | get_op_access( |
1119 | 59.6k | MI->csh, MCInst_getOpcode(MI), access, |
1120 | 59.6k | &MI->flat_insn->detail->x86.eflags); |
1121 | 59.6k | MI->flat_insn->detail->x86 |
1122 | 59.6k | .operands[MI->flat_insn->detail->x86 |
1123 | 59.6k | .op_count] |
1124 | 59.6k | .access = |
1125 | 59.6k | access[MI->flat_insn->detail->x86 |
1126 | 59.6k | .op_count]; |
1127 | 59.6k | #endif |
1128 | | |
1129 | 59.6k | MI->flat_insn->detail->x86.op_count++; |
1130 | 59.6k | } |
1131 | 59.6k | } |
1132 | 59.6k | } |
1133 | 573k | } |
1134 | | |
1135 | | static void printMemReference(MCInst *MI, unsigned Op, SStream *O) |
1136 | 133k | { |
1137 | 133k | bool NeedPlus = false; |
1138 | 133k | MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg); |
1139 | 133k | uint64_t ScaleVal = |
1140 | 133k | MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); |
1141 | 133k | MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg); |
1142 | 133k | MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); |
1143 | 133k | MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); |
1144 | 133k | int reg; |
1145 | | |
1146 | 133k | if (MI->csh->detail_opt) { |
1147 | 133k | #ifndef CAPSTONE_DIET |
1148 | 133k | uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE]; |
1149 | 133k | #endif |
1150 | | |
1151 | 133k | MI->flat_insn->detail->x86 |
1152 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1153 | 133k | .type = X86_OP_MEM; |
1154 | 133k | MI->flat_insn->detail->x86 |
1155 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1156 | 133k | .size = MI->x86opsize; |
1157 | 133k | MI->flat_insn->detail->x86 |
1158 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1159 | 133k | .mem.segment = X86_REG_INVALID; |
1160 | 133k | MI->flat_insn->detail->x86 |
1161 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1162 | 133k | .mem.base = X86_register_map(MCOperand_getReg(BaseReg)); |
1163 | 133k | if (MCOperand_getReg(IndexReg) != X86_EIZ) { |
1164 | 132k | MI->flat_insn->detail->x86 |
1165 | 132k | .operands[MI->flat_insn->detail->x86.op_count] |
1166 | 132k | .mem.index = |
1167 | 132k | X86_register_map(MCOperand_getReg(IndexReg)); |
1168 | 132k | } |
1169 | 133k | MI->flat_insn->detail->x86 |
1170 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1171 | 133k | .mem.scale = (int)ScaleVal; |
1172 | 133k | MI->flat_insn->detail->x86 |
1173 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1174 | 133k | .mem.disp = 0; |
1175 | | |
1176 | 133k | #ifndef CAPSTONE_DIET |
1177 | 133k | get_op_access(MI->csh, MCInst_getOpcode(MI), access, |
1178 | 133k | &MI->flat_insn->detail->x86.eflags); |
1179 | 133k | MI->flat_insn->detail->x86 |
1180 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1181 | 133k | .access = access[MI->flat_insn->detail->x86.op_count]; |
1182 | 133k | #endif |
1183 | 133k | } |
1184 | | |
1185 | | // If this has a segment register, print it. |
1186 | 133k | reg = MCOperand_getReg(SegReg); |
1187 | 133k | if (reg) { |
1188 | 2.32k | _printOperand(MI, Op + X86_AddrSegmentReg, O); |
1189 | 2.32k | if (MI->csh->detail_opt) { |
1190 | 2.32k | MI->flat_insn->detail->x86 |
1191 | 2.32k | .operands[MI->flat_insn->detail->x86.op_count] |
1192 | 2.32k | .mem.segment = X86_register_map(reg); |
1193 | 2.32k | } |
1194 | 2.32k | SStream_concat0(O, ":"); |
1195 | 2.32k | } |
1196 | | |
1197 | 133k | SStream_concat0(O, "["); |
1198 | | |
1199 | 133k | if (MCOperand_getReg(BaseReg)) { |
1200 | 130k | _printOperand(MI, Op + X86_AddrBaseReg, O); |
1201 | 130k | NeedPlus = true; |
1202 | 130k | } |
1203 | | |
1204 | 133k | if (MCOperand_getReg(IndexReg) && |
1205 | 27.2k | MCOperand_getReg(IndexReg) != X86_EIZ) { |
1206 | 26.3k | if (NeedPlus) |
1207 | 25.8k | SStream_concat0(O, " + "); |
1208 | 26.3k | _printOperand(MI, Op + X86_AddrIndexReg, O); |
1209 | 26.3k | if (ScaleVal != 1) |
1210 | 5.69k | SStream_concat(O, "*%" PRIu64, ScaleVal); |
1211 | 26.3k | NeedPlus = true; |
1212 | 26.3k | } |
1213 | | |
1214 | 133k | if (MCOperand_isImm(DispSpec)) { |
1215 | 133k | int64_t DispVal = MCOperand_getImm(DispSpec); |
1216 | 133k | if (MI->csh->detail_opt) |
1217 | 133k | MI->flat_insn->detail->x86 |
1218 | 133k | .operands[MI->flat_insn->detail->x86.op_count] |
1219 | 133k | .mem.disp = DispVal; |
1220 | 133k | if (DispVal) { |
1221 | 37.8k | if (NeedPlus) { |
1222 | 35.2k | if (DispVal < 0) { |
1223 | 14.1k | SStream_concat0(O, " - "); |
1224 | 14.1k | printImm(MI, O, -DispVal, true); |
1225 | 21.0k | } else { |
1226 | 21.0k | SStream_concat0(O, " + "); |
1227 | 21.0k | printImm(MI, O, DispVal, true); |
1228 | 21.0k | } |
1229 | 35.2k | } else { |
1230 | | // memory reference to an immediate address |
1231 | 2.66k | if (x86_has_feature(MI->csh->mode, CS_MODE_64)) |
1232 | 468 | MI->op1_size = 8; |
1233 | 2.66k | if (DispVal < 0) { |
1234 | 1.10k | printImm(MI, O, |
1235 | 1.10k | x86_get_address_mask( |
1236 | 1.10k | MI->csh->mode) & |
1237 | 1.10k | DispVal, |
1238 | 1.10k | true); |
1239 | 1.55k | } else { |
1240 | 1.55k | printImm(MI, O, DispVal, true); |
1241 | 1.55k | } |
1242 | 2.66k | } |
1243 | | |
1244 | 95.5k | } else { |
1245 | | // DispVal = 0 |
1246 | 95.5k | if (!NeedPlus) // [0] |
1247 | 226 | SStream_concat0(O, "0"); |
1248 | 95.5k | } |
1249 | 133k | } |
1250 | | |
1251 | 133k | SStream_concat0(O, "]"); |
1252 | | |
1253 | 133k | if (MI->csh->detail_opt) |
1254 | 133k | MI->flat_insn->detail->x86.op_count++; |
1255 | | |
1256 | 133k | if (MI->op1_size == 0) |
1257 | 80.6k | MI->op1_size = MI->x86opsize; |
1258 | 133k | } |
1259 | | |
1260 | | static void printanymem(MCInst *MI, unsigned OpNo, SStream *O) |
1261 | 6.43k | { |
1262 | 6.43k | switch (MI->Opcode) { |
1263 | 411 | default: |
1264 | 411 | break; |
1265 | 726 | case X86_LEA16r: |
1266 | 726 | MI->x86opsize = 2; |
1267 | 726 | break; |
1268 | 537 | case X86_LEA32r: |
1269 | 1.16k | case X86_LEA64_32r: |
1270 | 1.16k | MI->x86opsize = 4; |
1271 | 1.16k | break; |
1272 | 427 | case X86_LEA64r: |
1273 | 427 | MI->x86opsize = 8; |
1274 | 427 | break; |
1275 | 0 | #ifndef CAPSTONE_X86_REDUCE |
1276 | 403 | case X86_BNDCL32rm: |
1277 | 796 | case X86_BNDCN32rm: |
1278 | 1.23k | case X86_BNDCU32rm: |
1279 | 1.93k | case X86_BNDSTXmr: |
1280 | 2.46k | case X86_BNDLDXrm: |
1281 | 2.85k | case X86_BNDCL64rm: |
1282 | 3.24k | case X86_BNDCN64rm: |
1283 | 3.70k | case X86_BNDCU64rm: |
1284 | 3.70k | MI->x86opsize = 16; |
1285 | 3.70k | break; |
1286 | 6.43k | #endif |
1287 | 6.43k | } |
1288 | | |
1289 | 6.43k | printMemReference(MI, OpNo, O); |
1290 | 6.43k | } |
1291 | | |
1292 | | #ifdef CAPSTONE_X86_REDUCE |
1293 | | #include "X86GenAsmWriter1_reduce.inc" |
1294 | | #else |
1295 | | #include "X86GenAsmWriter1.inc" |
1296 | | #endif |
1297 | | |
1298 | | #include "X86GenRegisterName1.inc" |
1299 | | |
1300 | | #endif |