Coverage Report

Created: 2026-11-12 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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), &reg,
827
279k
            &access1, &reg2, &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