Coverage Report

Created: 2026-10-17 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/X86/X86ATTInstPrinter.c
Line
Count
Source
1
//===-- X86ATTInstPrinter.cpp - AT&T 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 AT&T-style
11
// assembly.
12
//
13
//===----------------------------------------------------------------------===//
14
15
/* Capstone Disassembly Engine */
16
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
17
18
// this code is only relevant when DIET mode is disable
19
#if defined(CAPSTONE_HAS_X86) && !defined(CAPSTONE_DIET) && \
20
  !defined(CAPSTONE_X86_ATT_DISABLE)
21
22
#ifdef _MSC_VER
23
// disable MSVC's warning on strncpy()
24
#pragma warning(disable : 4996)
25
// disable MSVC's warning on strncpy()
26
#pragma warning(disable : 28719)
27
#endif
28
29
#if !defined(CAPSTONE_HAS_OSXKERNEL)
30
#include <ctype.h>
31
#endif
32
#include <capstone/platform.h>
33
34
#if defined(CAPSTONE_HAS_OSXKERNEL)
35
#include <Availability.h>
36
#include <libkern/libkern.h>
37
#else
38
#include <stdio.h>
39
#include <stdlib.h>
40
#endif
41
42
#include <string.h>
43
44
#include "../../utils.h"
45
#include "../../MCInst.h"
46
#include "../../SStream.h"
47
#include "../../MCRegisterInfo.h"
48
#include "X86Mapping.h"
49
#include "X86BaseInfo.h"
50
#include "X86InstPrinterCommon.h"
51
52
#define GET_INSTRINFO_ENUM
53
#ifdef CAPSTONE_X86_REDUCE
54
#include "X86GenInstrInfo_reduce.inc"
55
#else
56
#include "X86GenInstrInfo.inc"
57
#endif
58
59
#define GET_REGINFO_ENUM
60
#include "X86GenRegisterInfo.inc"
61
62
static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
63
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
64
65
static void set_mem_access(MCInst *MI, bool status)
66
110k
{
67
110k
  if (MI->csh->detail_opt != CS_OPT_ON)
68
0
    return;
69
70
110k
  MI->csh->doing_mem = status;
71
110k
  if (!status)
72
    // done, create the next operand slot
73
55.4k
    MI->flat_insn->detail->x86.op_count++;
74
110k
}
75
76
static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
77
13.5k
{
78
13.5k
  switch (x86_get_bit_mode(MI->csh->mode)) {
79
4.54k
  case CS_MODE_16:
80
4.54k
    switch (MI->flat_insn->id) {
81
1.30k
    default:
82
1.30k
      MI->x86opsize = 2;
83
1.30k
      break;
84
827
    case X86_INS_LJMP:
85
1.52k
    case X86_INS_LCALL:
86
1.52k
      MI->x86opsize = 4;
87
1.52k
      break;
88
458
    case X86_INS_SGDT:
89
882
    case X86_INS_SIDT:
90
1.31k
    case X86_INS_LGDT:
91
1.71k
    case X86_INS_LIDT:
92
1.71k
      MI->x86opsize = 6;
93
1.71k
      break;
94
4.54k
    }
95
4.54k
    break;
96
4.92k
  case CS_MODE_32:
97
4.92k
    switch (MI->flat_insn->id) {
98
865
    default:
99
865
      MI->x86opsize = 4;
100
865
      break;
101
761
    case X86_INS_LJMP:
102
1.74k
    case X86_INS_JMP:
103
2.16k
    case X86_INS_LCALL:
104
2.65k
    case X86_INS_SGDT:
105
3.11k
    case X86_INS_SIDT:
106
3.68k
    case X86_INS_LGDT:
107
4.05k
    case X86_INS_LIDT:
108
4.05k
      MI->x86opsize = 6;
109
4.05k
      break;
110
4.92k
    }
111
4.92k
    break;
112
4.92k
  case CS_MODE_64:
113
4.11k
    switch (MI->flat_insn->id) {
114
1.17k
    default:
115
1.17k
      MI->x86opsize = 8;
116
1.17k
      break;
117
540
    case X86_INS_LJMP:
118
968
    case X86_INS_LCALL:
119
1.42k
    case X86_INS_SGDT:
120
1.83k
    case X86_INS_SIDT:
121
2.55k
    case X86_INS_LGDT:
122
2.93k
    case X86_INS_LIDT:
123
2.93k
      MI->x86opsize = 10;
124
2.93k
      break;
125
4.11k
    }
126
4.11k
    break;
127
4.11k
  default: // never reach
128
0
    break;
129
13.5k
  }
130
131
13.5k
  printMemReference(MI, OpNo, O);
132
13.5k
}
133
134
static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
135
82.0k
{
136
82.0k
  MI->x86opsize = 1;
137
82.0k
  printMemReference(MI, OpNo, O);
138
82.0k
}
139
140
static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
141
37.3k
{
142
37.3k
  MI->x86opsize = 2;
143
144
37.3k
  printMemReference(MI, OpNo, O);
145
37.3k
}
146
147
static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
148
38.4k
{
149
38.4k
  MI->x86opsize = 4;
150
151
38.4k
  printMemReference(MI, OpNo, O);
152
38.4k
}
153
154
static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
155
19.8k
{
156
19.8k
  MI->x86opsize = 8;
157
19.8k
  printMemReference(MI, OpNo, O);
158
19.8k
}
159
160
static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
161
7.68k
{
162
7.68k
  MI->x86opsize = 16;
163
7.68k
  printMemReference(MI, OpNo, O);
164
7.68k
}
165
166
static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
167
5.64k
{
168
5.64k
  MI->x86opsize = 64;
169
5.64k
  printMemReference(MI, OpNo, O);
170
5.64k
}
171
172
#ifndef CAPSTONE_X86_REDUCE
173
static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
174
5.16k
{
175
5.16k
  MI->x86opsize = 32;
176
5.16k
  printMemReference(MI, OpNo, O);
177
5.16k
}
178
179
static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
180
9.25k
{
181
9.25k
  switch (MCInst_getOpcode(MI)) {
182
7.32k
  default:
183
7.32k
    MI->x86opsize = 4;
184
7.32k
    break;
185
1.07k
  case X86_FSTENVm:
186
1.93k
  case X86_FLDENVm:
187
    // TODO: fix this in tablegen instead
188
1.93k
    switch (x86_get_bit_mode(MI->csh->mode)) {
189
0
    default: // never reach
190
0
      break;
191
740
    case CS_MODE_16:
192
740
      MI->x86opsize = 14;
193
740
      break;
194
455
    case CS_MODE_32:
195
1.19k
    case CS_MODE_64:
196
1.19k
      MI->x86opsize = 28;
197
1.19k
      break;
198
1.93k
    }
199
1.93k
    break;
200
9.25k
  }
201
202
9.25k
  printMemReference(MI, OpNo, O);
203
9.25k
}
204
205
static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
206
8.31k
{
207
8.31k
  MI->x86opsize = 8;
208
8.31k
  printMemReference(MI, OpNo, O);
209
8.31k
}
210
211
static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
212
433
{
213
433
  MI->x86opsize = 10;
214
433
  printMemReference(MI, OpNo, O);
215
433
}
216
217
static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
218
5.78k
{
219
5.78k
  MI->x86opsize = 16;
220
5.78k
  printMemReference(MI, OpNo, O);
221
5.78k
}
222
223
static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
224
6.04k
{
225
6.04k
  MI->x86opsize = 32;
226
6.04k
  printMemReference(MI, OpNo, O);
227
6.04k
}
228
229
static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
230
4.99k
{
231
4.99k
  MI->x86opsize = 64;
232
4.99k
  printMemReference(MI, OpNo, O);
233
4.99k
}
234
235
#endif
236
237
static void printRegName(SStream *OS, unsigned RegNo);
238
239
// local printOperand, without updating public operands
240
static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
241
340k
{
242
340k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
243
340k
  if (MCOperand_isReg(Op)) {
244
340k
    printRegName(O, MCOperand_getReg(Op));
245
340k
  } else if (MCOperand_isImm(Op)) {
246
0
    uint8_t encsize;
247
0
    uint8_t opsize =
248
0
      X86_immediate_size(MCInst_getOpcode(MI), &encsize);
249
250
    // Print X86 immediates as signed values.
251
0
    int64_t imm = MCOperand_getImm(Op);
252
0
    if (imm < 0) {
253
0
      if (MI->csh->imm_unsigned) {
254
0
        if (opsize) {
255
0
          switch (opsize) {
256
0
          default:
257
0
            break;
258
0
          case 1:
259
0
            imm &= 0xff;
260
0
            break;
261
0
          case 2:
262
0
            imm &= 0xffff;
263
0
            break;
264
0
          case 4:
265
0
            imm &= 0xffffffff;
266
0
            break;
267
0
          }
268
0
        }
269
270
0
        SStream_concat(O, "$0x%" PRIx64, imm);
271
0
      } else {
272
0
        if (imm < -HEX_THRESHOLD)
273
0
          SStream_concat(O, "$-0x%" PRIx64, -imm);
274
0
        else
275
0
          SStream_concat(O, "$-%" PRIu64, -imm);
276
0
      }
277
0
    } else {
278
0
      if (imm > HEX_THRESHOLD)
279
0
        SStream_concat(O, "$0x%" PRIx64, imm);
280
0
      else
281
0
        SStream_concat(O, "$%" PRIu64, imm);
282
0
    }
283
0
  }
284
340k
}
285
286
// convert Intel access info to AT&T access info
287
static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access,
288
        uint64_t *eflags)
289
791k
{
290
791k
  uint8_t count, i;
291
791k
  const uint8_t *arr = X86_get_op_access(h, id, eflags);
292
293
  // initialize access
294
791k
  memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
295
791k
  if (!arr) {
296
0
    return;
297
0
  }
298
299
  // find the non-zero last entry
300
2.29M
  for (count = 0; arr[count]; count++)
301
1.50M
    ;
302
303
791k
  if (count == 0)
304
53.2k
    return;
305
306
  // copy in reverse order this access array from Intel syntax -> AT&T syntax
307
738k
  count--;
308
2.24M
  for (i = 0; i <= count && ((count - i) < CS_X86_MAXIMUM_OPERAND_SIZE) &&
309
1.50M
        i < CS_X86_MAXIMUM_OPERAND_SIZE;
310
1.50M
       i++) {
311
1.50M
    if (arr[count - i] != CS_AC_IGNORE)
312
1.29M
      access[i] = arr[count - i];
313
203k
    else
314
203k
      access[i] = 0;
315
1.50M
  }
316
738k
}
317
318
static void fixup_evex_opmask_access(MCInst *MI)
319
347k
{
320
347k
  cs_x86 *x86 = &MI->flat_insn->detail->x86;
321
347k
  const uint8_t *arr;
322
347k
  uint8_t count, i, access_index = 0;
323
347k
  if (!(MI->flags & X86_IP_HAS_EVEX_OPMASK))
324
327k
    return;
325
326
19.1k
  arr = X86_get_op_access(MI->csh, MCInst_getOpcode(MI), &x86->eflags);
327
19.1k
  if (!arr)
328
0
    return;
329
66.0k
  for (count = 0; count < CS_X86_MAXIMUM_OPERAND_SIZE; ++count) {
330
66.0k
    if (!arr[count])
331
19.1k
      break;
332
66.0k
  }
333
19.1k
  if (count < 2 || count != x86->op_count)
334
18.8k
    return;
335
336
947
  for (i = count; i > 2; --i) {
337
631
    x86->operands[access_index].access = arr[i - 1];
338
631
    if (x86->operands[access_index].access == CS_AC_IGNORE)
339
0
      x86->operands[access_index].access = 0;
340
631
    access_index++;
341
631
  }
342
316
  x86->operands[access_index++].access = arr[0];
343
316
  x86->operands[access_index].access = arr[1];
344
316
}
345
346
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
347
24.5k
{
348
24.5k
  MCOperand *SegReg;
349
24.5k
  int reg;
350
351
24.5k
  if (MI->csh->detail_opt) {
352
24.5k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
353
354
24.5k
    MI->flat_insn->detail->x86
355
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
356
24.5k
      .type = X86_OP_MEM;
357
24.5k
    MI->flat_insn->detail->x86
358
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
359
24.5k
      .size = MI->x86opsize;
360
24.5k
    MI->flat_insn->detail->x86
361
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
362
24.5k
      .mem.segment = X86_REG_INVALID;
363
24.5k
    MI->flat_insn->detail->x86
364
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
365
24.5k
      .mem.base = X86_REG_INVALID;
366
24.5k
    MI->flat_insn->detail->x86
367
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
368
24.5k
      .mem.index = X86_REG_INVALID;
369
24.5k
    MI->flat_insn->detail->x86
370
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
371
24.5k
      .mem.scale = 1;
372
24.5k
    MI->flat_insn->detail->x86
373
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
374
24.5k
      .mem.disp = 0;
375
376
24.5k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
377
24.5k
            &MI->flat_insn->detail->x86.eflags);
378
24.5k
    MI->flat_insn->detail->x86
379
24.5k
      .operands[MI->flat_insn->detail->x86.op_count]
380
24.5k
      .access = access[MI->flat_insn->detail->x86.op_count];
381
24.5k
  }
382
383
24.5k
  SegReg = MCInst_getOperand(MI, Op + 1);
384
24.5k
  reg = MCOperand_getReg(SegReg);
385
  // If this has a segment register, print it.
386
24.5k
  if (reg) {
387
930
    _printOperand(MI, Op + 1, O);
388
930
    SStream_concat0(O, ":");
389
390
930
    if (MI->csh->detail_opt) {
391
930
      MI->flat_insn->detail->x86
392
930
        .operands[MI->flat_insn->detail->x86.op_count]
393
930
        .mem.segment = X86_register_map(reg);
394
930
    }
395
930
  }
396
397
24.5k
  SStream_concat0(O, "(");
398
24.5k
  set_mem_access(MI, true);
399
400
24.5k
  printOperand(MI, Op, O);
401
402
24.5k
  SStream_concat0(O, ")");
403
24.5k
  set_mem_access(MI, false);
404
24.5k
}
405
406
static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
407
17.5k
{
408
17.5k
  if (MI->csh->detail_opt) {
409
17.5k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
410
411
17.5k
    MI->flat_insn->detail->x86
412
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
413
17.5k
      .type = X86_OP_MEM;
414
17.5k
    MI->flat_insn->detail->x86
415
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
416
17.5k
      .size = MI->x86opsize;
417
17.5k
    MI->flat_insn->detail->x86
418
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
419
17.5k
      .mem.segment = X86_REG_INVALID;
420
17.5k
    MI->flat_insn->detail->x86
421
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
422
17.5k
      .mem.base = X86_REG_INVALID;
423
17.5k
    MI->flat_insn->detail->x86
424
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
425
17.5k
      .mem.index = X86_REG_INVALID;
426
17.5k
    MI->flat_insn->detail->x86
427
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
428
17.5k
      .mem.scale = 1;
429
17.5k
    MI->flat_insn->detail->x86
430
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
431
17.5k
      .mem.disp = 0;
432
433
17.5k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
434
17.5k
            &MI->flat_insn->detail->x86.eflags);
435
17.5k
    MI->flat_insn->detail->x86
436
17.5k
      .operands[MI->flat_insn->detail->x86.op_count]
437
17.5k
      .access = access[MI->flat_insn->detail->x86.op_count];
438
17.5k
  }
439
440
  // DI accesses are always ES-based on non-64bit mode
441
17.5k
  if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
442
10.2k
    SStream_concat0(O, "%es:(");
443
10.2k
    if (MI->csh->detail_opt) {
444
10.2k
      MI->flat_insn->detail->x86
445
10.2k
        .operands[MI->flat_insn->detail->x86.op_count]
446
10.2k
        .mem.segment = X86_REG_ES;
447
10.2k
    }
448
10.2k
  } else
449
7.26k
    SStream_concat0(O, "(");
450
451
17.5k
  set_mem_access(MI, true);
452
453
17.5k
  printOperand(MI, Op, O);
454
455
17.5k
  SStream_concat0(O, ")");
456
17.5k
  set_mem_access(MI, false);
457
17.5k
}
458
459
static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
460
8.12k
{
461
8.12k
  MI->x86opsize = 1;
462
8.12k
  printSrcIdx(MI, OpNo, O);
463
8.12k
}
464
465
static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
466
7.39k
{
467
7.39k
  MI->x86opsize = 2;
468
7.39k
  printSrcIdx(MI, OpNo, O);
469
7.39k
}
470
471
static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
472
7.09k
{
473
7.09k
  MI->x86opsize = 4;
474
7.09k
  printSrcIdx(MI, OpNo, O);
475
7.09k
}
476
477
static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
478
1.90k
{
479
1.90k
  MI->x86opsize = 8;
480
1.90k
  printSrcIdx(MI, OpNo, O);
481
1.90k
}
482
483
static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
484
11.6k
{
485
11.6k
  MI->x86opsize = 1;
486
11.6k
  printDstIdx(MI, OpNo, O);
487
11.6k
}
488
489
static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
490
7.51k
{
491
7.51k
  MI->x86opsize = 2;
492
7.51k
  printDstIdx(MI, OpNo, O);
493
7.51k
}
494
495
static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
496
8.72k
{
497
8.72k
  MI->x86opsize = 4;
498
8.72k
  printDstIdx(MI, OpNo, O);
499
8.72k
}
500
501
static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
502
3.01k
{
503
3.01k
  MI->x86opsize = 8;
504
3.01k
  printDstIdx(MI, OpNo, O);
505
3.01k
}
506
507
static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
508
6.89k
{
509
6.89k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op);
510
6.89k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
511
6.89k
  int reg;
512
513
6.89k
  if (MI->csh->detail_opt) {
514
6.89k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
515
516
6.89k
    MI->flat_insn->detail->x86
517
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
518
6.89k
      .type = X86_OP_MEM;
519
6.89k
    MI->flat_insn->detail->x86
520
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
521
6.89k
      .size = MI->x86opsize;
522
6.89k
    MI->flat_insn->detail->x86
523
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
524
6.89k
      .mem.segment = X86_REG_INVALID;
525
6.89k
    MI->flat_insn->detail->x86
526
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
527
6.89k
      .mem.base = X86_REG_INVALID;
528
6.89k
    MI->flat_insn->detail->x86
529
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
530
6.89k
      .mem.index = X86_REG_INVALID;
531
6.89k
    MI->flat_insn->detail->x86
532
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
533
6.89k
      .mem.scale = 1;
534
6.89k
    MI->flat_insn->detail->x86
535
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
536
6.89k
      .mem.disp = 0;
537
538
6.89k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
539
6.89k
            &MI->flat_insn->detail->x86.eflags);
540
6.89k
    MI->flat_insn->detail->x86
541
6.89k
      .operands[MI->flat_insn->detail->x86.op_count]
542
6.89k
      .access = access[MI->flat_insn->detail->x86.op_count];
543
6.89k
  }
544
545
  // If this has a segment register, print it.
546
6.89k
  reg = MCOperand_getReg(SegReg);
547
6.89k
  if (reg) {
548
583
    _printOperand(MI, Op + 1, O);
549
583
    SStream_concat0(O, ":");
550
551
583
    if (MI->csh->detail_opt) {
552
583
      MI->flat_insn->detail->x86
553
583
        .operands[MI->flat_insn->detail->x86.op_count]
554
583
        .mem.segment = X86_register_map(reg);
555
583
    }
556
583
  }
557
558
6.89k
  if (MCOperand_isImm(DispSpec)) {
559
6.89k
    int64_t imm = MCOperand_getImm(DispSpec);
560
6.89k
    if (MI->csh->detail_opt)
561
6.89k
      MI->flat_insn->detail->x86
562
6.89k
        .operands[MI->flat_insn->detail->x86.op_count]
563
6.89k
        .mem.disp = imm;
564
6.89k
    if (imm < 0) {
565
1.25k
      SStream_concat(O, "0x%" PRIx64,
566
1.25k
               x86_get_address_mask(MI->csh->mode) &
567
1.25k
                 imm);
568
5.64k
    } else {
569
5.64k
      if (imm > HEX_THRESHOLD)
570
5.08k
        SStream_concat(O, "0x%" PRIx64, imm);
571
566
      else
572
566
        SStream_concat(O, "%" PRIu64, imm);
573
5.64k
    }
574
6.89k
  }
575
576
6.89k
  if (MI->csh->detail_opt)
577
6.89k
    MI->flat_insn->detail->x86.op_count++;
578
6.89k
}
579
580
static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
581
43.4k
{
582
43.4k
  uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff;
583
584
43.4k
  if (val > HEX_THRESHOLD)
585
37.0k
    SStream_concat(O, "$0x%x", val);
586
6.42k
  else
587
6.42k
    SStream_concat(O, "$%" PRIu8, val);
588
589
43.4k
  if (MI->csh->detail_opt) {
590
43.4k
    MI->flat_insn->detail->x86
591
43.4k
      .operands[MI->flat_insn->detail->x86.op_count]
592
43.4k
      .type = X86_OP_IMM;
593
43.4k
    MI->flat_insn->detail->x86
594
43.4k
      .operands[MI->flat_insn->detail->x86.op_count]
595
43.4k
      .imm = val;
596
43.4k
    MI->flat_insn->detail->x86
597
43.4k
      .operands[MI->flat_insn->detail->x86.op_count]
598
43.4k
      .size = 1;
599
43.4k
    MI->flat_insn->detail->x86.op_count++;
600
43.4k
  }
601
43.4k
}
602
603
static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
604
3.41k
{
605
3.41k
  MI->x86opsize = 1;
606
3.41k
  printMemOffset(MI, OpNo, O);
607
3.41k
}
608
609
static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
610
1.45k
{
611
1.45k
  MI->x86opsize = 2;
612
1.45k
  printMemOffset(MI, OpNo, O);
613
1.45k
}
614
615
static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
616
1.56k
{
617
1.56k
  MI->x86opsize = 4;
618
1.56k
  printMemOffset(MI, OpNo, O);
619
1.56k
}
620
621
static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
622
461
{
623
461
  MI->x86opsize = 8;
624
461
  printMemOffset(MI, OpNo, O);
625
461
}
626
627
/// printPCRelImm - This is used to print an immediate value that ends up
628
/// being encoded as a pc-relative value (e.g. for jumps and calls).  These
629
/// print slightly differently than normal immediates.  For example, a $ is not
630
/// emitted.
631
static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
632
21.1k
{
633
21.1k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
634
21.1k
  if (MCOperand_isImm(Op)) {
635
21.1k
    int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size +
636
21.1k
            MI->address;
637
638
    // truncate imm for non-64bit
639
21.1k
    if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
640
12.8k
      imm = imm & 0xffffffff;
641
12.8k
    } else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) &&
642
0
         MI->imm_size == 2) {
643
0
      imm &= 0xffff;
644
0
    }
645
646
21.1k
    if (imm < 0) {
647
505
      SStream_concat(O, "0x%" PRIx64, imm);
648
20.6k
    } else {
649
20.6k
      if (imm > HEX_THRESHOLD)
650
20.6k
        SStream_concat(O, "0x%" PRIx64, imm);
651
10
      else
652
10
        SStream_concat(O, "%" PRIu64, imm);
653
20.6k
    }
654
21.1k
    if (MI->csh->detail_opt) {
655
21.1k
      MI->flat_insn->detail->x86
656
21.1k
        .operands[MI->flat_insn->detail->x86.op_count]
657
21.1k
        .type = X86_OP_IMM;
658
21.1k
      MI->has_imm = true;
659
21.1k
      MI->flat_insn->detail->x86
660
21.1k
        .operands[MI->flat_insn->detail->x86.op_count]
661
21.1k
        .imm = imm;
662
21.1k
      MI->flat_insn->detail->x86.op_count++;
663
21.1k
    }
664
21.1k
  }
665
21.1k
}
666
667
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
668
342k
{
669
342k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
670
342k
  if (MCOperand_isReg(Op)) {
671
301k
    unsigned int reg = MCOperand_getReg(Op);
672
301k
    printRegName(O, reg);
673
301k
    if (MI->csh->detail_opt) {
674
301k
      if (MI->csh->doing_mem) {
675
31.0k
        MI->flat_insn->detail->x86
676
31.0k
          .operands[MI->flat_insn->detail->x86
677
31.0k
                .op_count]
678
31.0k
          .mem.base = X86_register_map(reg);
679
270k
      } else {
680
270k
        uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
681
682
270k
        MI->flat_insn->detail->x86
683
270k
          .operands[MI->flat_insn->detail->x86
684
270k
                .op_count]
685
270k
          .type = X86_OP_REG;
686
270k
        MI->flat_insn->detail->x86
687
270k
          .operands[MI->flat_insn->detail->x86
688
270k
                .op_count]
689
270k
          .reg = X86_register_map(reg);
690
270k
        MI->flat_insn->detail->x86
691
270k
          .operands[MI->flat_insn->detail->x86
692
270k
                .op_count]
693
270k
          .size =
694
270k
          MI->csh->regsize_map[X86_register_map(
695
270k
            reg)];
696
697
270k
        get_op_access(
698
270k
          MI->csh, MCInst_getOpcode(MI), access,
699
270k
          &MI->flat_insn->detail->x86.eflags);
700
270k
        MI->flat_insn->detail->x86
701
270k
          .operands[MI->flat_insn->detail->x86
702
270k
                .op_count]
703
270k
          .access =
704
270k
          access[MI->flat_insn->detail->x86
705
270k
                   .op_count];
706
707
270k
        MI->flat_insn->detail->x86.op_count++;
708
270k
      }
709
301k
    }
710
301k
  } else if (MCOperand_isImm(Op)) {
711
    // Print X86 immediates as signed values.
712
40.9k
    uint8_t encsize;
713
40.9k
    int64_t imm = MCOperand_getImm(Op);
714
40.9k
    uint8_t opsize =
715
40.9k
      X86_immediate_size(MCInst_getOpcode(MI), &encsize);
716
717
40.9k
    if (opsize == 1) { // print 1 byte immediate in positive form
718
20.2k
      imm = imm & 0xff;
719
20.2k
    }
720
721
40.9k
    switch (MI->flat_insn->id) {
722
17.8k
    default:
723
17.8k
      if (imm >= 0) {
724
16.3k
        if (imm > HEX_THRESHOLD)
725
14.4k
          SStream_concat(O, "$0x%" PRIx64, imm);
726
1.90k
        else
727
1.90k
          SStream_concat(O, "$%" PRIu64, imm);
728
16.3k
      } else {
729
1.55k
        if (MI->csh->imm_unsigned) {
730
          // the mask is for display only: the value
731
          // stored in detail must stay unmasked
732
0
          int64_t p = imm;
733
0
          if (opsize) {
734
0
            switch (opsize) {
735
0
            default:
736
0
              break;
737
            // case 1 cannot occur because above imm was ANDed with 0xff,
738
            // making it effectively always positive.
739
            // So this switch is never reached.
740
0
            case 2:
741
0
              p &= 0xffff;
742
0
              break;
743
0
            case 4:
744
0
              p &= 0xffffffff;
745
0
              break;
746
0
            }
747
0
          }
748
749
0
          SStream_concat(O, "$0x%" PRIx64, p);
750
1.55k
        } else {
751
1.55k
          if (imm ==
752
1.55k
              0x8000000000000000LL) // imm == -imm
753
0
            SStream_concat0(
754
0
              O,
755
0
              "$0x8000000000000000");
756
1.55k
          else if (imm < -HEX_THRESHOLD)
757
1.40k
            SStream_concat(O,
758
1.40k
                     "$-0x%" PRIx64,
759
1.40k
                     -imm);
760
148
          else
761
148
            SStream_concat(O, "$-%" PRIu64,
762
148
                     -imm);
763
1.55k
        }
764
1.55k
      }
765
17.8k
      break;
766
767
17.8k
    case X86_INS_MOVABS:
768
8.97k
    case X86_INS_MOV:
769
      // do not print number in negative form
770
      // Use unsigned comparison to handle values >= 2^63 correctly
771
8.97k
      if ((uint64_t)imm > HEX_THRESHOLD)
772
7.41k
        SStream_concat(O, "$0x%" PRIx64, imm);
773
1.55k
      else
774
1.55k
        SStream_concat(O, "$%" PRIu64, imm);
775
8.97k
      break;
776
777
0
    case X86_INS_IN:
778
0
    case X86_INS_OUT:
779
0
    case X86_INS_INT:
780
      // do not print number in negative form
781
0
      imm = imm & 0xff;
782
0
      if (imm >= 0 && imm <= HEX_THRESHOLD)
783
0
        SStream_concat(O, "$%" PRIu64, imm);
784
0
      else {
785
0
        SStream_concat(O, "$0x%x", imm);
786
0
      }
787
0
      break;
788
789
376
    case X86_INS_LCALL:
790
1.30k
    case X86_INS_LJMP:
791
1.30k
    case X86_INS_JMP:
792
      // always print address in positive form
793
1.30k
      if (OpNo == 1) { // selector is ptr16
794
652
        imm = imm & 0xffff;
795
652
        opsize = 2;
796
652
      } else
797
652
        opsize = 4;
798
1.30k
      SStream_concat(O, "$0x%" PRIx64, imm);
799
1.30k
      break;
800
801
2.98k
    case X86_INS_AND:
802
5.30k
    case X86_INS_OR:
803
8.39k
    case X86_INS_XOR:
804
      // do not print number in negative form
805
8.39k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
806
1.03k
        SStream_concat(O, "$%" PRIu64, imm);
807
7.36k
      else {
808
7.36k
        imm = arch_masks[opsize ? opsize : MI->imm_size] &
809
7.36k
              imm;
810
7.36k
        SStream_concat(O, "$0x%" PRIx64, imm);
811
7.36k
      }
812
8.39k
      break;
813
814
3.62k
    case X86_INS_RET:
815
4.36k
    case X86_INS_RETF:
816
      // RET imm16
817
4.36k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
818
240
        SStream_concat(O, "$%" PRIu64, imm);
819
4.12k
      else {
820
4.12k
        imm = 0xffff & imm;
821
4.12k
        SStream_concat(O, "$0x%x", imm);
822
4.12k
      }
823
4.36k
      break;
824
40.9k
    }
825
826
40.9k
    if (MI->csh->detail_opt) {
827
40.9k
      if (MI->csh->doing_mem) {
828
0
        MI->flat_insn->detail->x86
829
0
          .operands[MI->flat_insn->detail->x86
830
0
                .op_count]
831
0
          .type = X86_OP_MEM;
832
0
        MI->flat_insn->detail->x86
833
0
          .operands[MI->flat_insn->detail->x86
834
0
                .op_count]
835
0
          .mem.disp = imm;
836
40.9k
      } else {
837
40.9k
        MI->flat_insn->detail->x86
838
40.9k
          .operands[MI->flat_insn->detail->x86
839
40.9k
                .op_count]
840
40.9k
          .type = X86_OP_IMM;
841
40.9k
        MI->has_imm = true;
842
40.9k
        MI->flat_insn->detail->x86
843
40.9k
          .operands[MI->flat_insn->detail->x86
844
40.9k
                .op_count]
845
40.9k
          .imm = imm;
846
847
40.9k
        if (opsize > 0) {
848
35.3k
          MI->flat_insn->detail->x86
849
35.3k
            .operands[MI->flat_insn->detail
850
35.3k
                  ->x86.op_count]
851
35.3k
            .size = opsize;
852
35.3k
          MI->flat_insn->detail->x86.encoding
853
35.3k
            .imm_size = encsize;
854
35.3k
        } else if (MI->op1_size > 0)
855
0
          MI->flat_insn->detail->x86
856
0
            .operands[MI->flat_insn->detail
857
0
                  ->x86.op_count]
858
0
            .size = MI->op1_size;
859
5.56k
        else
860
5.56k
          MI->flat_insn->detail->x86
861
5.56k
            .operands[MI->flat_insn->detail
862
5.56k
                  ->x86.op_count]
863
5.56k
            .size = MI->imm_size;
864
865
40.9k
        MI->flat_insn->detail->x86.op_count++;
866
40.9k
      }
867
40.9k
    }
868
40.9k
  }
869
342k
}
870
871
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
872
251k
{
873
251k
  MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
874
251k
  MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
875
251k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
876
251k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
877
251k
  uint64_t ScaleVal;
878
251k
  int segreg;
879
251k
  int64_t DispVal = 1;
880
881
251k
  if (MI->csh->detail_opt) {
882
251k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
883
884
251k
    MI->flat_insn->detail->x86
885
251k
      .operands[MI->flat_insn->detail->x86.op_count]
886
251k
      .type = X86_OP_MEM;
887
251k
    MI->flat_insn->detail->x86
888
251k
      .operands[MI->flat_insn->detail->x86.op_count]
889
251k
      .size = MI->x86opsize;
890
251k
    MI->flat_insn->detail->x86
891
251k
      .operands[MI->flat_insn->detail->x86.op_count]
892
251k
      .mem.segment = X86_REG_INVALID;
893
251k
    MI->flat_insn->detail->x86
894
251k
      .operands[MI->flat_insn->detail->x86.op_count]
895
251k
      .mem.base = X86_register_map(MCOperand_getReg(BaseReg));
896
251k
    if (MCOperand_getReg(IndexReg) != X86_EIZ) {
897
251k
      MI->flat_insn->detail->x86
898
251k
        .operands[MI->flat_insn->detail->x86.op_count]
899
251k
        .mem.index =
900
251k
        X86_register_map(MCOperand_getReg(IndexReg));
901
251k
    }
902
251k
    MI->flat_insn->detail->x86
903
251k
      .operands[MI->flat_insn->detail->x86.op_count]
904
251k
      .mem.scale = 1;
905
251k
    MI->flat_insn->detail->x86
906
251k
      .operands[MI->flat_insn->detail->x86.op_count]
907
251k
      .mem.disp = 0;
908
909
251k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
910
251k
            &MI->flat_insn->detail->x86.eflags);
911
251k
    MI->flat_insn->detail->x86
912
251k
      .operands[MI->flat_insn->detail->x86.op_count]
913
251k
      .access = access[MI->flat_insn->detail->x86.op_count];
914
251k
  }
915
916
  // If this has a segment register, print it.
917
251k
  segreg = MCOperand_getReg(SegReg);
918
251k
  if (segreg) {
919
6.64k
    _printOperand(MI, Op + X86_AddrSegmentReg, O);
920
6.64k
    SStream_concat0(O, ":");
921
922
6.64k
    if (MI->csh->detail_opt) {
923
6.64k
      MI->flat_insn->detail->x86
924
6.64k
        .operands[MI->flat_insn->detail->x86.op_count]
925
6.64k
        .mem.segment = X86_register_map(segreg);
926
6.64k
    }
927
6.64k
  }
928
929
251k
  if (MCOperand_isImm(DispSpec)) {
930
251k
    DispVal = MCOperand_getImm(DispSpec);
931
251k
    if (MI->csh->detail_opt)
932
251k
      MI->flat_insn->detail->x86
933
251k
        .operands[MI->flat_insn->detail->x86.op_count]
934
251k
        .mem.disp = DispVal;
935
251k
    if (DispVal) {
936
85.2k
      if (MCOperand_getReg(IndexReg) ||
937
80.0k
          MCOperand_getReg(BaseReg)) {
938
80.0k
        printInt64(O, DispVal);
939
80.0k
      } else {
940
        // only immediate as address of memory
941
5.21k
        if (DispVal < 0) {
942
2.23k
          SStream_concat(O, "0x%" PRIx64,
943
2.23k
                   x86_get_address_mask(
944
2.23k
                     MI->csh->mode) &
945
2.23k
                     DispVal);
946
2.97k
        } else {
947
2.97k
          if (DispVal > HEX_THRESHOLD)
948
2.51k
            SStream_concat(O, "0x%" PRIx64,
949
2.51k
                     DispVal);
950
461
          else
951
461
            SStream_concat(O, "%" PRIu64,
952
461
                     DispVal);
953
2.97k
        }
954
5.21k
      }
955
85.2k
    }
956
251k
  }
957
958
251k
  if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
959
246k
    SStream_concat0(O, "(");
960
961
246k
    if (MCOperand_getReg(BaseReg))
962
245k
      _printOperand(MI, Op + X86_AddrBaseReg, O);
963
964
246k
    if (MCOperand_getReg(IndexReg) &&
965
87.7k
        MCOperand_getReg(IndexReg) != X86_EIZ) {
966
86.8k
      SStream_concat0(O, ", ");
967
86.8k
      _printOperand(MI, Op + X86_AddrIndexReg, O);
968
86.8k
      ScaleVal = MCOperand_getImm(
969
86.8k
        MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
970
86.8k
      if (MI->csh->detail_opt)
971
86.8k
        MI->flat_insn->detail->x86
972
86.8k
          .operands[MI->flat_insn->detail->x86
973
86.8k
                .op_count]
974
86.8k
          .mem.scale = (int)ScaleVal;
975
86.8k
      if (ScaleVal != 1) {
976
9.66k
        SStream_concat(O, ", %" PRIu64, ScaleVal);
977
9.66k
      }
978
86.8k
    }
979
980
246k
    SStream_concat0(O, ")");
981
246k
  } else {
982
5.86k
    if (!DispVal)
983
645
      SStream_concat0(O, "0");
984
5.86k
  }
985
986
251k
  if (MI->csh->detail_opt)
987
251k
    MI->flat_insn->detail->x86.op_count++;
988
251k
}
989
990
static void printanymem(MCInst *MI, unsigned OpNo, SStream *O)
991
7.46k
{
992
7.46k
  switch (MI->Opcode) {
993
409
  default:
994
409
    break;
995
1.08k
  case X86_LEA16r:
996
1.08k
    MI->x86opsize = 2;
997
1.08k
    break;
998
489
  case X86_LEA32r:
999
1.15k
  case X86_LEA64_32r:
1000
1.15k
    MI->x86opsize = 4;
1001
1.15k
    break;
1002
646
  case X86_LEA64r:
1003
646
    MI->x86opsize = 8;
1004
646
    break;
1005
0
#ifndef CAPSTONE_X86_REDUCE
1006
372
  case X86_BNDCL32rm:
1007
865
  case X86_BNDCN32rm:
1008
1.23k
  case X86_BNDCU32rm:
1009
1.82k
  case X86_BNDSTXmr:
1010
2.74k
  case X86_BNDLDXrm:
1011
3.20k
  case X86_BNDCL64rm:
1012
3.70k
  case X86_BNDCN64rm:
1013
4.17k
  case X86_BNDCU64rm:
1014
4.17k
    MI->x86opsize = 16;
1015
4.17k
    break;
1016
7.46k
#endif
1017
7.46k
  }
1018
1019
7.46k
  printMemReference(MI, OpNo, O);
1020
7.46k
}
1021
1022
#include "X86InstPrinter.h"
1023
1024
// Include the auto-generated portion of the assembly writer.
1025
#ifdef CAPSTONE_X86_REDUCE
1026
#include "X86GenAsmWriter_reduce.inc"
1027
#else
1028
#include "X86GenAsmWriter.inc"
1029
#endif
1030
1031
#include "X86GenRegisterName.inc"
1032
1033
static void printRegName(SStream *OS, unsigned RegNo)
1034
887k
{
1035
887k
  SStream_concat(OS, "%%%s", getRegisterName(RegNo));
1036
887k
}
1037
1038
void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
1039
347k
{
1040
347k
  x86_reg reg, reg2;
1041
347k
  enum cs_ac_type access1, access2;
1042
347k
  int i;
1043
1044
  // perhaps this instruction does not need printer
1045
347k
  if (MI->assembly[0]) {
1046
0
    strncpy(OS->buffer, MI->assembly, sizeof(OS->buffer));
1047
0
    return;
1048
0
  }
1049
1050
  // Output CALLpcrel32 as "callq" in 64-bit mode.
1051
  // In Intel annotation it's always emitted as "call".
1052
  //
1053
  // TODO: Probably this hack should be redesigned via InstAlias in
1054
  // InstrInfo.td as soon as Requires clause is supported properly
1055
  // for InstAlias.
1056
347k
  if ((x86_has_feature(MI->csh->mode, CS_MODE_64)) &&
1057
128k
      MCInst_getOpcode(MI) == X86_CALLpcrel32) {
1058
0
    SStream_concat0(OS, "callq\t");
1059
0
    MCInst_setOpcodePub(MI, X86_INS_CALL);
1060
0
    printPCRelImm(MI, 0, OS);
1061
0
    return;
1062
0
  }
1063
1064
347k
  X86_lockrep(MI, OS);
1065
347k
  printInstruction(MI, OS);
1066
1067
347k
  if (MI->has_imm) {
1068
    // if op_count > 1, then this operand's size is taken from the destination op
1069
61.1k
    if (MI->flat_insn->detail->x86.op_count > 1) {
1070
33.6k
      if (MI->flat_insn->id != X86_INS_LCALL &&
1071
33.4k
          MI->flat_insn->id != X86_INS_LJMP &&
1072
32.9k
          MI->flat_insn->id != X86_INS_JMP) {
1073
32.9k
        for (i = 0;
1074
100k
             i < MI->flat_insn->detail->x86.op_count;
1075
67.0k
             i++) {
1076
67.0k
          if (MI->flat_insn->detail->x86
1077
67.0k
                .operands[i]
1078
67.0k
                .type == X86_OP_IMM)
1079
33.3k
            MI->flat_insn->detail->x86
1080
33.3k
              .operands[i]
1081
33.3k
              .size =
1082
33.3k
              MI->flat_insn->detail
1083
33.3k
                ->x86
1084
33.3k
                .operands
1085
33.3k
                  [MI->flat_insn
1086
33.3k
                     ->detail
1087
33.3k
                     ->x86
1088
33.3k
                     .op_count -
1089
33.3k
                   1]
1090
33.3k
                .size;
1091
67.0k
        }
1092
32.9k
      }
1093
33.6k
    } else if (!MI->flat_insn->detail->x86.operands[0].size) {
1094
      // AT&T sets has_imm without a size (printPCRelImm,
1095
      // op_addImm) and relies on this; printOperand does set
1096
      // one, so it must not be overwritten here
1097
21.1k
      MI->flat_insn->detail->x86.operands[0].size =
1098
21.1k
        MI->imm_size;
1099
21.1k
    }
1100
61.1k
  }
1101
1102
347k
  if (MI->csh->detail_opt) {
1103
347k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE] = { 0 };
1104
1105
    // some instructions need to supply immediate 1 in the first op
1106
347k
    switch (MCInst_getOpcode(MI)) {
1107
325k
    default:
1108
325k
      break;
1109
325k
    case X86_SHL8r1:
1110
456
    case X86_SHL16r1:
1111
797
    case X86_SHL32r1:
1112
1.05k
    case X86_SHL64r1:
1113
1.29k
    case X86_SAL8r1:
1114
1.83k
    case X86_SAL16r1:
1115
2.47k
    case X86_SAL32r1:
1116
3.09k
    case X86_SAL64r1:
1117
3.32k
    case X86_SHR8r1:
1118
3.67k
    case X86_SHR16r1:
1119
4.47k
    case X86_SHR32r1:
1120
4.71k
    case X86_SHR64r1:
1121
5.07k
    case X86_SAR8r1:
1122
5.25k
    case X86_SAR16r1:
1123
5.76k
    case X86_SAR32r1:
1124
5.98k
    case X86_SAR64r1:
1125
7.19k
    case X86_RCL8r1:
1126
7.82k
    case X86_RCL16r1:
1127
8.54k
    case X86_RCL32r1:
1128
8.80k
    case X86_RCL64r1:
1129
9.05k
    case X86_RCR8r1:
1130
9.22k
    case X86_RCR16r1:
1131
9.47k
    case X86_RCR32r1:
1132
9.81k
    case X86_RCR64r1:
1133
10.0k
    case X86_ROL8r1:
1134
10.2k
    case X86_ROL16r1:
1135
10.5k
    case X86_ROL32r1:
1136
10.7k
    case X86_ROL64r1:
1137
10.9k
    case X86_ROR8r1:
1138
11.4k
    case X86_ROR16r1:
1139
11.6k
    case X86_ROR32r1:
1140
11.8k
    case X86_ROR64r1:
1141
12.2k
    case X86_SHL8m1:
1142
12.5k
    case X86_SHL16m1:
1143
13.0k
    case X86_SHL32m1:
1144
13.2k
    case X86_SHL64m1:
1145
13.6k
    case X86_SAL8m1:
1146
13.9k
    case X86_SAL16m1:
1147
14.2k
    case X86_SAL32m1:
1148
14.5k
    case X86_SAL64m1:
1149
14.8k
    case X86_SHR8m1:
1150
15.4k
    case X86_SHR16m1:
1151
15.9k
    case X86_SHR32m1:
1152
16.2k
    case X86_SHR64m1:
1153
16.4k
    case X86_SAR8m1:
1154
16.6k
    case X86_SAR16m1:
1155
16.8k
    case X86_SAR32m1:
1156
16.9k
    case X86_SAR64m1:
1157
17.1k
    case X86_RCL8m1:
1158
17.4k
    case X86_RCL16m1:
1159
17.6k
    case X86_RCL32m1:
1160
17.7k
    case X86_RCL64m1:
1161
17.9k
    case X86_RCR8m1:
1162
18.4k
    case X86_RCR16m1:
1163
18.6k
    case X86_RCR32m1:
1164
19.0k
    case X86_RCR64m1:
1165
19.4k
    case X86_ROL8m1:
1166
19.7k
    case X86_ROL16m1:
1167
20.1k
    case X86_ROL32m1:
1168
20.2k
    case X86_ROL64m1:
1169
20.5k
    case X86_ROR8m1:
1170
20.8k
    case X86_ROR16m1:
1171
21.1k
    case X86_ROR32m1:
1172
21.2k
    case X86_ROR64m1:
1173
      // shift all the ops right to leave 1st slot for this new register op
1174
21.2k
      memmove(&(MI->flat_insn->detail->x86.operands[1]),
1175
21.2k
        &(MI->flat_insn->detail->x86.operands[0]),
1176
21.2k
        sizeof(MI->flat_insn->detail->x86.operands[0]) *
1177
21.2k
          (ARR_SIZE(MI->flat_insn->detail->x86
1178
21.2k
                .operands) -
1179
21.2k
           1));
1180
21.2k
      memset(&(MI->flat_insn->detail->x86.operands[0]), 0,
1181
21.2k
             sizeof(MI->flat_insn->detail->x86.operands[0]));
1182
21.2k
      MI->flat_insn->detail->x86.operands[0].type =
1183
21.2k
        X86_OP_IMM;
1184
21.2k
      MI->flat_insn->detail->x86.operands[0].imm = 1;
1185
21.2k
      MI->flat_insn->detail->x86.operands[0].size = 1;
1186
21.2k
      MI->flat_insn->detail->x86.op_count++;
1187
347k
    }
1188
1189
    // special instruction needs to supply register op
1190
    // first op can be embedded in the asm by llvm.
1191
    // so we have to add the missing register as the first operand
1192
1193
    //printf(">>> opcode = %u\n", MCInst_getOpcode(MI));
1194
1195
347k
    reg = X86_insn_reg_att_h(MI->csh, MCInst_getOpcode(MI),
1196
347k
           &access1);
1197
347k
    if (reg) {
1198
      // shift all the ops right to leave 1st slot for this new register op
1199
18.7k
      memmove(&(MI->flat_insn->detail->x86.operands[1]),
1200
18.7k
        &(MI->flat_insn->detail->x86.operands[0]),
1201
18.7k
        sizeof(MI->flat_insn->detail->x86.operands[0]) *
1202
18.7k
          (ARR_SIZE(MI->flat_insn->detail->x86
1203
18.7k
                .operands) -
1204
18.7k
           1));
1205
18.7k
      memset(&(MI->flat_insn->detail->x86.operands[0]), 0,
1206
18.7k
             sizeof(MI->flat_insn->detail->x86.operands[0]));
1207
18.7k
      MI->flat_insn->detail->x86.operands[0].type =
1208
18.7k
        X86_OP_REG;
1209
18.7k
      MI->flat_insn->detail->x86.operands[0].reg = reg;
1210
18.7k
      MI->flat_insn->detail->x86.operands[0].size =
1211
18.7k
        MI->csh->regsize_map[reg];
1212
18.7k
      MI->flat_insn->detail->x86.operands[0].access = access1;
1213
1214
18.7k
      MI->flat_insn->detail->x86.op_count++;
1215
328k
    } else {
1216
328k
      if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg,
1217
328k
                &access1, &reg2, &access2)) {
1218
6.81k
        MI->flat_insn->detail->x86.operands[0].type =
1219
6.81k
          X86_OP_REG;
1220
6.81k
        MI->flat_insn->detail->x86.operands[0].reg =
1221
6.81k
          reg;
1222
6.81k
        MI->flat_insn->detail->x86.operands[0].size =
1223
6.81k
          MI->csh->regsize_map[reg];
1224
6.81k
        MI->flat_insn->detail->x86.operands[0].access =
1225
6.81k
          access1;
1226
6.81k
        MI->flat_insn->detail->x86.operands[1].type =
1227
6.81k
          X86_OP_REG;
1228
6.81k
        MI->flat_insn->detail->x86.operands[1].reg =
1229
6.81k
          reg2;
1230
6.81k
        MI->flat_insn->detail->x86.operands[1].size =
1231
6.81k
          MI->csh->regsize_map[reg2];
1232
6.81k
        MI->flat_insn->detail->x86.operands[1].access =
1233
6.81k
          access2;
1234
6.81k
        MI->flat_insn->detail->x86.op_count = 2;
1235
6.81k
      }
1236
328k
    }
1237
1238
347k
#ifndef CAPSTONE_DIET
1239
347k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
1240
347k
            &MI->flat_insn->detail->x86.eflags);
1241
959k
    for (i = 0; i < MI->flat_insn->detail->x86.op_count &&
1242
612k
          i < ARR_SIZE(access);
1243
612k
         i++) {
1244
612k
      MI->flat_insn->detail->x86.operands[i].access =
1245
612k
        access[i];
1246
612k
    }
1247
347k
    fixup_evex_opmask_access(MI);
1248
347k
#endif
1249
347k
  }
1250
347k
}
1251
1252
#endif