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
6.76k
{
79
  // FIXME: do this with autogen
80
  // printf(">>> ID = %u\n", MI->flat_insn->id);
81
6.76k
  switch (MI->flat_insn->id) {
82
2.13k
  default:
83
2.13k
    SStream_concat0(O, "ptr ");
84
2.13k
    break;
85
653
  case X86_INS_SGDT:
86
1.29k
  case X86_INS_SIDT:
87
1.97k
  case X86_INS_LGDT:
88
2.57k
  case X86_INS_LIDT:
89
2.82k
  case X86_INS_FXRSTOR:
90
3.03k
  case X86_INS_FXSAVE:
91
4.00k
  case X86_INS_LJMP:
92
4.63k
  case X86_INS_LCALL:
93
    // do not print "ptr"
94
4.63k
    break;
95
6.76k
  }
96
97
6.76k
  switch (x86_get_bit_mode(MI->csh->mode)) {
98
1.81k
  case CS_MODE_16:
99
1.81k
    switch (MI->flat_insn->id) {
100
496
    default:
101
496
      MI->x86opsize = 2;
102
496
      break;
103
240
    case X86_INS_LJMP:
104
442
    case X86_INS_LCALL:
105
442
      MI->x86opsize = 4;
106
442
      break;
107
223
    case X86_INS_SGDT:
108
431
    case X86_INS_SIDT:
109
662
    case X86_INS_LGDT:
110
873
    case X86_INS_LIDT:
111
873
      MI->x86opsize = 6;
112
873
      break;
113
1.81k
    }
114
1.81k
    break;
115
2.88k
  case CS_MODE_32:
116
2.88k
    switch (MI->flat_insn->id) {
117
1.34k
    default:
118
1.34k
      MI->x86opsize = 4;
119
1.34k
      break;
120
195
    case X86_INS_LJMP:
121
506
    case X86_INS_JMP:
122
700
    case X86_INS_LCALL:
123
916
    case X86_INS_SGDT:
124
1.12k
    case X86_INS_SIDT:
125
1.34k
    case X86_INS_LGDT:
126
1.53k
    case X86_INS_LIDT:
127
1.53k
      MI->x86opsize = 6;
128
1.53k
      break;
129
2.88k
    }
130
2.88k
    break;
131
2.88k
  case CS_MODE_64:
132
2.07k
    switch (MI->flat_insn->id) {
133
435
    default:
134
435
      MI->x86opsize = 8;
135
435
      break;
136
533
    case X86_INS_LJMP:
137
769
    case X86_INS_LCALL:
138
983
    case X86_INS_SGDT:
139
1.21k
    case X86_INS_SIDT:
140
1.43k
    case X86_INS_LGDT:
141
1.63k
    case X86_INS_LIDT:
142
1.63k
      MI->x86opsize = 10;
143
1.63k
      break;
144
2.07k
    }
145
2.07k
    break;
146
2.07k
  default: // never reach
147
0
    break;
148
6.76k
  }
149
150
6.76k
  printMemReference(MI, OpNo, O);
151
6.76k
}
152
153
static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
154
41.9k
{
155
41.9k
  SStream_concat0(O, "byte ptr ");
156
41.9k
  MI->x86opsize = 1;
157
41.9k
  printMemReference(MI, OpNo, O);
158
41.9k
}
159
160
static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
161
13.5k
{
162
13.5k
  MI->x86opsize = 2;
163
13.5k
  SStream_concat0(O, "word ptr ");
164
13.5k
  printMemReference(MI, OpNo, O);
165
13.5k
}
166
167
static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
168
30.4k
{
169
30.4k
  MI->x86opsize = 4;
170
30.4k
  SStream_concat0(O, "dword ptr ");
171
30.4k
  printMemReference(MI, OpNo, O);
172
30.4k
}
173
174
static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
175
12.4k
{
176
12.4k
  SStream_concat0(O, "qword ptr ");
177
12.4k
  MI->x86opsize = 8;
178
12.4k
  printMemReference(MI, OpNo, O);
179
12.4k
}
180
181
static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
182
4.88k
{
183
4.88k
  SStream_concat0(O, "xmmword ptr ");
184
4.88k
  MI->x86opsize = 16;
185
4.88k
  printMemReference(MI, OpNo, O);
186
4.88k
}
187
188
static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
189
2.39k
{
190
2.39k
  SStream_concat0(O, "zmmword ptr ");
191
2.39k
  MI->x86opsize = 64;
192
2.39k
  printMemReference(MI, OpNo, O);
193
2.39k
}
194
195
#ifndef CAPSTONE_X86_REDUCE
196
static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
197
2.65k
{
198
2.65k
  SStream_concat0(O, "ymmword ptr ");
199
2.65k
  MI->x86opsize = 32;
200
2.65k
  printMemReference(MI, OpNo, O);
201
2.65k
}
202
203
static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
204
3.68k
{
205
3.68k
  switch (MCInst_getOpcode(MI)) {
206
2.75k
  default:
207
2.75k
    SStream_concat0(O, "dword ptr ");
208
2.75k
    MI->x86opsize = 4;
209
2.75k
    break;
210
347
  case X86_FSTENVm:
211
933
  case X86_FLDENVm:
212
    // TODO: fix this in tablegen instead
213
933
    switch (x86_get_bit_mode(MI->csh->mode)) {
214
0
    default: // never reach
215
0
      break;
216
441
    case CS_MODE_16:
217
441
      MI->x86opsize = 14;
218
441
      break;
219
271
    case CS_MODE_32:
220
492
    case CS_MODE_64:
221
492
      MI->x86opsize = 28;
222
492
      break;
223
933
    }
224
933
    break;
225
3.68k
  }
226
227
3.68k
  printMemReference(MI, OpNo, O);
228
3.68k
}
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
577
{
255
577
  switch (MCInst_getOpcode(MI)) {
256
308
  default:
257
308
    SStream_concat0(O, "xword ptr ");
258
308
    break;
259
248
  case X86_FBLDm:
260
269
  case X86_FBSTPm:
261
269
    break;
262
577
  }
263
264
577
  MI->x86opsize = 10;
265
577
  printMemReference(MI, OpNo, O);
266
577
}
267
268
static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
269
2.69k
{
270
2.69k
  SStream_concat0(O, "xmmword ptr ");
271
2.69k
  MI->x86opsize = 16;
272
2.69k
  printMemReference(MI, OpNo, O);
273
2.69k
}
274
275
static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
276
2.29k
{
277
2.29k
  SStream_concat0(O, "ymmword ptr ");
278
2.29k
  MI->x86opsize = 32;
279
2.29k
  printMemReference(MI, OpNo, O);
280
2.29k
}
281
282
static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
283
1.67k
{
284
1.67k
  SStream_concat0(O, "zmmword ptr ");
285
1.67k
  MI->x86opsize = 64;
286
1.67k
  printMemReference(MI, OpNo, O);
287
1.67k
}
288
#endif
289
290
static const char *getRegisterName(unsigned RegNo);
291
static void printRegName(SStream *OS, unsigned RegNo)
292
454k
{
293
454k
  SStream_concat0(OS, getRegisterName(RegNo));
294
454k
}
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
117k
{
312
117k
  if (positive) {
313
    // always print this number in positive form
314
100k
    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
100k
    } else { // Intel syntax
351
100k
      if (imm < 0) {
352
1.99k
        if (MI->op1_size) {
353
645
          switch (MI->op1_size) {
354
645
          default:
355
645
            break;
356
645
          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
645
          }
366
645
        }
367
368
1.99k
        SStream_concat(O, "0x%" PRIx64, imm);
369
98.0k
      } else {
370
98.0k
        if (imm > HEX_THRESHOLD)
371
89.1k
          SStream_concat(O, "0x%" PRIx64, imm);
372
8.97k
        else
373
8.97k
          SStream_concat(O, "%" PRIu64, imm);
374
98.0k
      }
375
100k
    }
376
100k
  } else {
377
17.0k
    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
17.0k
    } else { // Intel syntax
405
17.0k
      if (imm < 0) {
406
2.82k
        if (imm == 0x8000000000000000LL) // imm == -imm
407
0
          SStream_concat0(O,
408
0
              "0x8000000000000000");
409
2.82k
        else if (imm < -HEX_THRESHOLD)
410
2.59k
          SStream_concat(O, "-0x%" PRIx64, -imm);
411
232
        else
412
232
          SStream_concat(O, "-%" PRIu64, -imm);
413
414
14.2k
      } else {
415
14.2k
        if (imm > HEX_THRESHOLD)
416
11.7k
          SStream_concat(O, "0x%" PRIx64, imm);
417
2.53k
        else
418
2.53k
          SStream_concat(O, "%" PRIu64, imm);
419
14.2k
      }
420
17.0k
    }
421
17.0k
  }
422
117k
}
423
424
// local printOperand, without updating public operands
425
static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
426
159k
{
427
159k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
428
159k
  if (MCOperand_isReg(Op)) {
429
159k
    printRegName(O, MCOperand_getReg(Op));
430
159k
  } 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
159k
}
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
815k
{
441
815k
#ifndef CAPSTONE_DIET
442
815k
  uint8_t i;
443
815k
  const uint8_t *arr = X86_get_op_access(h, id, eflags);
444
445
  // initialize access
446
815k
  memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
447
448
815k
  if (!arr) {
449
0
    access[0] = 0;
450
0
    return;
451
0
  }
452
453
  // copy to access but zero out CS_AC_IGNORE
454
2.39M
  for (i = 0; arr[i]; i++) {
455
1.57M
    if (arr[i] != CS_AC_IGNORE)
456
1.34M
      access[i] = arr[i];
457
229k
    else
458
229k
      access[i] = 0;
459
1.57M
  }
460
461
  // mark the end of array
462
815k
  access[i] = 0;
463
815k
#endif
464
815k
}
465
#endif
466
467
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
468
16.2k
{
469
16.2k
  MCOperand *SegReg;
470
16.2k
  int reg;
471
472
16.2k
  if (MI->csh->detail_opt) {
473
16.2k
#ifndef CAPSTONE_DIET
474
16.2k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
475
16.2k
#endif
476
477
16.2k
    MI->flat_insn->detail->x86
478
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
479
16.2k
      .type = X86_OP_MEM;
480
16.2k
    MI->flat_insn->detail->x86
481
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
482
16.2k
      .size = MI->x86opsize;
483
16.2k
    MI->flat_insn->detail->x86
484
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
485
16.2k
      .mem.segment = X86_REG_INVALID;
486
16.2k
    MI->flat_insn->detail->x86
487
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
488
16.2k
      .mem.base = X86_REG_INVALID;
489
16.2k
    MI->flat_insn->detail->x86
490
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
491
16.2k
      .mem.index = X86_REG_INVALID;
492
16.2k
    MI->flat_insn->detail->x86
493
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
494
16.2k
      .mem.scale = 1;
495
16.2k
    MI->flat_insn->detail->x86
496
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
497
16.2k
      .mem.disp = 0;
498
499
16.2k
#ifndef CAPSTONE_DIET
500
16.2k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
501
16.2k
            &MI->flat_insn->detail->x86.eflags);
502
16.2k
    MI->flat_insn->detail->x86
503
16.2k
      .operands[MI->flat_insn->detail->x86.op_count]
504
16.2k
      .access = access[MI->flat_insn->detail->x86.op_count];
505
16.2k
#endif
506
16.2k
  }
507
508
16.2k
  SegReg = MCInst_getOperand(MI, Op + 1);
509
16.2k
  reg = MCOperand_getReg(SegReg);
510
511
  // If this has a segment register, print it.
512
16.2k
  if (reg) {
513
650
    _printOperand(MI, Op + 1, O);
514
650
    if (MI->csh->detail_opt) {
515
650
      MI->flat_insn->detail->x86
516
650
        .operands[MI->flat_insn->detail->x86.op_count]
517
650
        .mem.segment = X86_register_map(reg);
518
650
    }
519
650
    SStream_concat0(O, ":");
520
650
  }
521
522
16.2k
  SStream_concat0(O, "[");
523
16.2k
  set_mem_access(MI, true);
524
16.2k
  printOperand(MI, Op, O);
525
16.2k
  SStream_concat0(O, "]");
526
16.2k
  set_mem_access(MI, false);
527
16.2k
}
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
6.29k
{
586
6.29k
  SStream_concat0(O, "byte ptr ");
587
6.29k
  MI->x86opsize = 1;
588
6.29k
  printSrcIdx(MI, OpNo, O);
589
6.29k
}
590
591
static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
592
3.44k
{
593
3.44k
  SStream_concat0(O, "word ptr ");
594
3.44k
  MI->x86opsize = 2;
595
3.44k
  printSrcIdx(MI, OpNo, O);
596
3.44k
}
597
598
static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
599
4.87k
{
600
4.87k
  SStream_concat0(O, "dword ptr ");
601
4.87k
  MI->x86opsize = 4;
602
4.87k
  printSrcIdx(MI, OpNo, O);
603
4.87k
}
604
605
static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
606
1.66k
{
607
1.66k
  SStream_concat0(O, "qword ptr ");
608
1.66k
  MI->x86opsize = 8;
609
1.66k
  printSrcIdx(MI, OpNo, O);
610
1.66k
}
611
612
static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
613
6.38k
{
614
6.38k
  SStream_concat0(O, "byte ptr ");
615
6.38k
  MI->x86opsize = 1;
616
6.38k
  printDstIdx(MI, OpNo, O);
617
6.38k
}
618
619
static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
620
3.51k
{
621
3.51k
  SStream_concat0(O, "word ptr ");
622
3.51k
  MI->x86opsize = 2;
623
3.51k
  printDstIdx(MI, OpNo, O);
624
3.51k
}
625
626
static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
627
5.83k
{
628
5.83k
  SStream_concat0(O, "dword ptr ");
629
5.83k
  MI->x86opsize = 4;
630
5.83k
  printDstIdx(MI, OpNo, O);
631
5.83k
}
632
633
static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
634
1.84k
{
635
1.84k
  SStream_concat0(O, "qword ptr ");
636
1.84k
  MI->x86opsize = 8;
637
1.84k
  printDstIdx(MI, OpNo, O);
638
1.84k
}
639
640
static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
641
2.68k
{
642
2.68k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op);
643
2.68k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
644
2.68k
  int reg;
645
646
2.68k
  if (MI->csh->detail_opt) {
647
2.68k
#ifndef CAPSTONE_DIET
648
2.68k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
649
2.68k
#endif
650
651
2.68k
    MI->flat_insn->detail->x86
652
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
653
2.68k
      .type = X86_OP_MEM;
654
2.68k
    MI->flat_insn->detail->x86
655
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
656
2.68k
      .size = MI->x86opsize;
657
2.68k
    MI->flat_insn->detail->x86
658
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
659
2.68k
      .mem.segment = X86_REG_INVALID;
660
2.68k
    MI->flat_insn->detail->x86
661
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
662
2.68k
      .mem.base = X86_REG_INVALID;
663
2.68k
    MI->flat_insn->detail->x86
664
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
665
2.68k
      .mem.index = X86_REG_INVALID;
666
2.68k
    MI->flat_insn->detail->x86
667
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
668
2.68k
      .mem.scale = 1;
669
2.68k
    MI->flat_insn->detail->x86
670
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
671
2.68k
      .mem.disp = 0;
672
673
2.68k
#ifndef CAPSTONE_DIET
674
2.68k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
675
2.68k
            &MI->flat_insn->detail->x86.eflags);
676
2.68k
    MI->flat_insn->detail->x86
677
2.68k
      .operands[MI->flat_insn->detail->x86.op_count]
678
2.68k
      .access = access[MI->flat_insn->detail->x86.op_count];
679
2.68k
#endif
680
2.68k
  }
681
682
  // If this has a segment register, print it.
683
2.68k
  reg = MCOperand_getReg(SegReg);
684
2.68k
  if (reg) {
685
348
    _printOperand(MI, Op + 1, O);
686
348
    SStream_concat0(O, ":");
687
348
    if (MI->csh->detail_opt) {
688
348
      MI->flat_insn->detail->x86
689
348
        .operands[MI->flat_insn->detail->x86.op_count]
690
348
        .mem.segment = X86_register_map(reg);
691
348
    }
692
348
  }
693
694
2.68k
  SStream_concat0(O, "[");
695
696
2.68k
  if (MCOperand_isImm(DispSpec)) {
697
2.68k
    int64_t imm = MCOperand_getImm(DispSpec);
698
2.68k
    if (MI->csh->detail_opt)
699
2.68k
      MI->flat_insn->detail->x86
700
2.68k
        .operands[MI->flat_insn->detail->x86.op_count]
701
2.68k
        .mem.disp = imm;
702
703
2.68k
    if (imm < 0)
704
523
      printImm(MI, O,
705
523
         x86_get_address_mask(MI->csh->mode) & imm,
706
523
         true);
707
2.15k
    else
708
2.15k
      printImm(MI, O, imm, true);
709
2.68k
  }
710
711
2.68k
  SStream_concat0(O, "]");
712
713
2.68k
  if (MI->csh->detail_opt)
714
2.68k
    MI->flat_insn->detail->x86.op_count++;
715
716
2.68k
  if (MI->op1_size == 0)
717
2.68k
    MI->op1_size = MI->x86opsize;
718
2.68k
}
719
720
static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
721
20.1k
{
722
20.1k
  uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff;
723
724
20.1k
  printImm(MI, O, val, true);
725
726
20.1k
  if (MI->csh->detail_opt) {
727
20.1k
#ifndef CAPSTONE_DIET
728
20.1k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
729
20.1k
#endif
730
731
20.1k
    MI->flat_insn->detail->x86
732
20.1k
      .operands[MI->flat_insn->detail->x86.op_count]
733
20.1k
      .type = X86_OP_IMM;
734
20.1k
    MI->flat_insn->detail->x86
735
20.1k
      .operands[MI->flat_insn->detail->x86.op_count]
736
20.1k
      .imm = val;
737
20.1k
    MI->flat_insn->detail->x86
738
20.1k
      .operands[MI->flat_insn->detail->x86.op_count]
739
20.1k
      .size = 1;
740
741
20.1k
#ifndef CAPSTONE_DIET
742
20.1k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
743
20.1k
            &MI->flat_insn->detail->x86.eflags);
744
20.1k
    MI->flat_insn->detail->x86
745
20.1k
      .operands[MI->flat_insn->detail->x86.op_count]
746
20.1k
      .access = access[MI->flat_insn->detail->x86.op_count];
747
20.1k
#endif
748
749
20.1k
    MI->flat_insn->detail->x86.op_count++;
750
20.1k
  }
751
20.1k
}
752
753
static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
754
1.24k
{
755
1.24k
  SStream_concat0(O, "byte ptr ");
756
1.24k
  MI->x86opsize = 1;
757
1.24k
  printMemOffset(MI, OpNo, O);
758
1.24k
}
759
760
static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
761
437
{
762
437
  SStream_concat0(O, "word ptr ");
763
437
  MI->x86opsize = 2;
764
437
  printMemOffset(MI, OpNo, O);
765
437
}
766
767
static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
768
806
{
769
806
  SStream_concat0(O, "dword ptr ");
770
806
  MI->x86opsize = 4;
771
806
  printMemOffset(MI, OpNo, O);
772
806
}
773
774
static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
775
199
{
776
199
  SStream_concat0(O, "qword ptr ");
777
199
  MI->x86opsize = 8;
778
199
  printMemOffset(MI, OpNo, O);
779
199
}
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
331k
{
946
331k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
947
948
331k
  if (MCOperand_isReg(Op)) {
949
294k
    unsigned int reg = MCOperand_getReg(Op);
950
951
294k
    printRegName(O, reg);
952
294k
    if (MI->csh->detail_opt) {
953
294k
      if (MI->csh->doing_mem) {
954
33.8k
        MI->flat_insn->detail->x86
955
33.8k
          .operands[MI->flat_insn->detail->x86
956
33.8k
                .op_count]
957
33.8k
          .mem.base = X86_register_map(reg);
958
261k
      } else {
959
261k
#ifndef CAPSTONE_DIET
960
261k
        uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
961
261k
#endif
962
963
261k
        MI->flat_insn->detail->x86
964
261k
          .operands[MI->flat_insn->detail->x86
965
261k
                .op_count]
966
261k
          .type = X86_OP_REG;
967
261k
        MI->flat_insn->detail->x86
968
261k
          .operands[MI->flat_insn->detail->x86
969
261k
                .op_count]
970
261k
          .reg = X86_register_map(reg);
971
261k
        MI->flat_insn->detail->x86
972
261k
          .operands[MI->flat_insn->detail->x86
973
261k
                .op_count]
974
261k
          .size =
975
261k
          MI->csh->regsize_map[X86_register_map(
976
261k
            reg)];
977
978
261k
#ifndef CAPSTONE_DIET
979
261k
        get_op_access(
980
261k
          MI->csh, MCInst_getOpcode(MI), access,
981
261k
          &MI->flat_insn->detail->x86.eflags);
982
261k
        MI->flat_insn->detail->x86
983
261k
          .operands[MI->flat_insn->detail->x86
984
261k
                .op_count]
985
261k
          .access =
986
261k
          access[MI->flat_insn->detail->x86
987
261k
                   .op_count];
988
261k
#endif
989
990
261k
        MI->flat_insn->detail->x86.op_count++;
991
261k
      }
992
294k
    }
993
994
294k
    if (MI->op1_size == 0)
995
150k
      MI->op1_size =
996
150k
        MI->csh->regsize_map[X86_register_map(reg)];
997
294k
  } else if (MCOperand_isImm(Op)) {
998
36.9k
    uint8_t encsize;
999
36.9k
    int64_t imm = MCOperand_getImm(Op);
1000
36.9k
    uint8_t opsize =
1001
36.9k
      X86_immediate_size(MCInst_getOpcode(MI), &encsize);
1002
1003
36.9k
    if (opsize == 1) // print 1 byte immediate in positive form
1004
15.0k
      imm = imm & 0xff;
1005
1006
    // printf(">>> id = %u\n", MI->flat_insn->id);
1007
36.9k
    switch (MI->flat_insn->id) {
1008
17.0k
    default:
1009
17.0k
      printImm(MI, O, imm, MI->csh->imm_unsigned);
1010
17.0k
      break;
1011
1012
208
    case X86_INS_MOVABS:
1013
4.54k
    case X86_INS_MOV:
1014
      // do not print number in negative form
1015
4.54k
      printImm(MI, O, imm, true);
1016
4.54k
      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
586
    case X86_INS_LCALL:
1027
1.18k
    case X86_INS_LJMP:
1028
1.18k
    case X86_INS_JMP:
1029
      // always print address in positive form
1030
1.18k
      if (OpNo == 1) { // ptr16 part
1031
594
        imm = imm & 0xffff;
1032
594
        opsize = 2;
1033
594
      } else
1034
594
        opsize = 4;
1035
1.18k
      printImm(MI, O, imm, true);
1036
1.18k
      break;
1037
1038
3.52k
    case X86_INS_AND:
1039
5.71k
    case X86_INS_OR:
1040
9.17k
    case X86_INS_XOR:
1041
      // do not print number in negative form
1042
9.17k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
1043
1.59k
        printImm(MI, O, imm, true);
1044
7.57k
      else {
1045
7.57k
        imm = arch_masks[opsize ? opsize : MI->imm_size] &
1046
7.57k
              imm;
1047
7.57k
        printImm(MI, O, imm, true);
1048
7.57k
      }
1049
9.17k
      break;
1050
1051
4.60k
    case X86_INS_RET:
1052
5.02k
    case X86_INS_RETF:
1053
      // RET imm16
1054
5.02k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
1055
383
        printImm(MI, O, imm, true);
1056
4.64k
      else {
1057
4.64k
        imm = 0xffff & imm;
1058
4.64k
        printImm(MI, O, imm, true);
1059
4.64k
      }
1060
5.02k
      break;
1061
36.9k
    }
1062
1063
36.9k
    if (MI->csh->detail_opt) {
1064
36.9k
      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
36.9k
      } else {
1070
36.9k
#ifndef CAPSTONE_DIET
1071
36.9k
        uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
1072
36.9k
#endif
1073
1074
36.9k
        MI->flat_insn->detail->x86
1075
36.9k
          .operands[MI->flat_insn->detail->x86
1076
36.9k
                .op_count]
1077
36.9k
          .type = X86_OP_IMM;
1078
36.9k
        if (opsize > 0) {
1079
29.3k
          MI->flat_insn->detail->x86
1080
29.3k
            .operands[MI->flat_insn->detail
1081
29.3k
                  ->x86.op_count]
1082
29.3k
            .size = opsize;
1083
29.3k
          MI->flat_insn->detail->x86.encoding
1084
29.3k
            .imm_size = encsize;
1085
29.3k
        } else if (MI->flat_insn->detail->x86.op_count >
1086
7.67k
             0) {
1087
1.65k
          if (MI->flat_insn->id !=
1088
1.65k
                X86_INS_LCALL &&
1089
1.65k
              MI->flat_insn->id != X86_INS_LJMP) {
1090
1.65k
            MI->flat_insn->detail->x86
1091
1.65k
              .operands[MI->flat_insn
1092
1.65k
                    ->detail
1093
1.65k
                    ->x86
1094
1.65k
                    .op_count]
1095
1.65k
              .size =
1096
1.65k
              MI->flat_insn->detail
1097
1.65k
                ->x86
1098
1.65k
                .operands[0]
1099
1.65k
                .size;
1100
1.65k
          } 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
1.65k
        } else
1108
6.01k
          MI->flat_insn->detail->x86
1109
6.01k
            .operands[MI->flat_insn->detail
1110
6.01k
                  ->x86.op_count]
1111
6.01k
            .size = MI->imm_size;
1112
36.9k
        MI->flat_insn->detail->x86
1113
36.9k
          .operands[MI->flat_insn->detail->x86
1114
36.9k
                .op_count]
1115
36.9k
          .imm = imm;
1116
1117
36.9k
#ifndef CAPSTONE_DIET
1118
36.9k
        get_op_access(
1119
36.9k
          MI->csh, MCInst_getOpcode(MI), access,
1120
36.9k
          &MI->flat_insn->detail->x86.eflags);
1121
36.9k
        MI->flat_insn->detail->x86
1122
36.9k
          .operands[MI->flat_insn->detail->x86
1123
36.9k
                .op_count]
1124
36.9k
          .access =
1125
36.9k
          access[MI->flat_insn->detail->x86
1126
36.9k
                   .op_count];
1127
36.9k
#endif
1128
1129
36.9k
        MI->flat_insn->detail->x86.op_count++;
1130
36.9k
      }
1131
36.9k
    }
1132
36.9k
  }
1133
331k
}
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
3.23k
{
1262
3.23k
  switch (MI->Opcode) {
1263
212
  default:
1264
212
    break;
1265
371
  case X86_LEA16r:
1266
371
    MI->x86opsize = 2;
1267
371
    break;
1268
296
  case X86_LEA32r:
1269
591
  case X86_LEA64_32r:
1270
591
    MI->x86opsize = 4;
1271
591
    break;
1272
223
  case X86_LEA64r:
1273
223
    MI->x86opsize = 8;
1274
223
    break;
1275
0
#ifndef CAPSTONE_X86_REDUCE
1276
204
  case X86_BNDCL32rm:
1277
403
  case X86_BNDCN32rm:
1278
647
  case X86_BNDCU32rm:
1279
940
  case X86_BNDSTXmr:
1280
1.23k
  case X86_BNDLDXrm:
1281
1.43k
  case X86_BNDCL64rm:
1282
1.63k
  case X86_BNDCN64rm:
1283
1.83k
  case X86_BNDCU64rm:
1284
1.83k
    MI->x86opsize = 16;
1285
1.83k
    break;
1286
3.23k
#endif
1287
3.23k
  }
1288
1289
3.23k
  printMemReference(MI, OpNo, O);
1290
3.23k
}
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