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
62.1k
{
67
62.1k
  if (MI->csh->detail_opt != CS_OPT_ON)
68
0
    return;
69
70
62.1k
  MI->csh->doing_mem = status;
71
62.1k
  if (!status)
72
    // done, create the next operand slot
73
31.0k
    MI->flat_insn->detail->x86.op_count++;
74
62.1k
}
75
76
static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
77
7.63k
{
78
7.63k
  switch (x86_get_bit_mode(MI->csh->mode)) {
79
2.43k
  case CS_MODE_16:
80
2.43k
    switch (MI->flat_insn->id) {
81
830
    default:
82
830
      MI->x86opsize = 2;
83
830
      break;
84
484
    case X86_INS_LJMP:
85
712
    case X86_INS_LCALL:
86
712
      MI->x86opsize = 4;
87
712
      break;
88
239
    case X86_INS_SGDT:
89
454
    case X86_INS_SIDT:
90
692
    case X86_INS_LGDT:
91
894
    case X86_INS_LIDT:
92
894
      MI->x86opsize = 6;
93
894
      break;
94
2.43k
    }
95
2.43k
    break;
96
3.24k
  case CS_MODE_32:
97
3.24k
    switch (MI->flat_insn->id) {
98
523
    default:
99
523
      MI->x86opsize = 4;
100
523
      break;
101
550
    case X86_INS_LJMP:
102
1.32k
    case X86_INS_JMP:
103
1.53k
    case X86_INS_LCALL:
104
1.81k
    case X86_INS_SGDT:
105
2.04k
    case X86_INS_SIDT:
106
2.41k
    case X86_INS_LGDT:
107
2.72k
    case X86_INS_LIDT:
108
2.72k
      MI->x86opsize = 6;
109
2.72k
      break;
110
3.24k
    }
111
3.24k
    break;
112
3.24k
  case CS_MODE_64:
113
1.95k
    switch (MI->flat_insn->id) {
114
492
    default:
115
492
      MI->x86opsize = 8;
116
492
      break;
117
315
    case X86_INS_LJMP:
118
544
    case X86_INS_LCALL:
119
783
    case X86_INS_SGDT:
120
1.01k
    case X86_INS_SIDT:
121
1.28k
    case X86_INS_LGDT:
122
1.46k
    case X86_INS_LIDT:
123
1.46k
      MI->x86opsize = 10;
124
1.46k
      break;
125
1.95k
    }
126
1.95k
    break;
127
1.95k
  default: // never reach
128
0
    break;
129
7.63k
  }
130
131
7.63k
  printMemReference(MI, OpNo, O);
132
7.63k
}
133
134
static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
135
51.5k
{
136
51.5k
  MI->x86opsize = 1;
137
51.5k
  printMemReference(MI, OpNo, O);
138
51.5k
}
139
140
static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
141
19.9k
{
142
19.9k
  MI->x86opsize = 2;
143
144
19.9k
  printMemReference(MI, OpNo, O);
145
19.9k
}
146
147
static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
148
20.9k
{
149
20.9k
  MI->x86opsize = 4;
150
151
20.9k
  printMemReference(MI, OpNo, O);
152
20.9k
}
153
154
static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
155
9.28k
{
156
9.28k
  MI->x86opsize = 8;
157
9.28k
  printMemReference(MI, OpNo, O);
158
9.28k
}
159
160
static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
161
3.36k
{
162
3.36k
  MI->x86opsize = 16;
163
3.36k
  printMemReference(MI, OpNo, O);
164
3.36k
}
165
166
static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
167
2.91k
{
168
2.91k
  MI->x86opsize = 64;
169
2.91k
  printMemReference(MI, OpNo, O);
170
2.91k
}
171
172
#ifndef CAPSTONE_X86_REDUCE
173
static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
174
2.43k
{
175
2.43k
  MI->x86opsize = 32;
176
2.43k
  printMemReference(MI, OpNo, O);
177
2.43k
}
178
179
static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
180
4.38k
{
181
4.38k
  switch (MCInst_getOpcode(MI)) {
182
3.48k
  default:
183
3.48k
    MI->x86opsize = 4;
184
3.48k
    break;
185
642
  case X86_FSTENVm:
186
906
  case X86_FLDENVm:
187
    // TODO: fix this in tablegen instead
188
906
    switch (x86_get_bit_mode(MI->csh->mode)) {
189
0
    default: // never reach
190
0
      break;
191
426
    case CS_MODE_16:
192
426
      MI->x86opsize = 14;
193
426
      break;
194
241
    case CS_MODE_32:
195
480
    case CS_MODE_64:
196
480
      MI->x86opsize = 28;
197
480
      break;
198
906
    }
199
906
    break;
200
4.38k
  }
201
202
4.38k
  printMemReference(MI, OpNo, O);
203
4.38k
}
204
205
static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
206
4.17k
{
207
4.17k
  MI->x86opsize = 8;
208
4.17k
  printMemReference(MI, OpNo, O);
209
4.17k
}
210
211
static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
212
206
{
213
206
  MI->x86opsize = 10;
214
206
  printMemReference(MI, OpNo, O);
215
206
}
216
217
static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
218
2.69k
{
219
2.69k
  MI->x86opsize = 16;
220
2.69k
  printMemReference(MI, OpNo, O);
221
2.69k
}
222
223
static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
224
2.95k
{
225
2.95k
  MI->x86opsize = 32;
226
2.95k
  printMemReference(MI, OpNo, O);
227
2.95k
}
228
229
static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
230
2.56k
{
231
2.56k
  MI->x86opsize = 64;
232
2.56k
  printMemReference(MI, OpNo, O);
233
2.56k
}
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
183k
{
242
183k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
243
183k
  if (MCOperand_isReg(Op)) {
244
183k
    printRegName(O, MCOperand_getReg(Op));
245
183k
  } 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
183k
}
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
13.5k
{
348
13.5k
  MCOperand *SegReg;
349
13.5k
  int reg;
350
351
13.5k
  if (MI->csh->detail_opt) {
352
13.5k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
353
354
13.5k
    MI->flat_insn->detail->x86
355
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
356
13.5k
      .type = X86_OP_MEM;
357
13.5k
    MI->flat_insn->detail->x86
358
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
359
13.5k
      .size = MI->x86opsize;
360
13.5k
    MI->flat_insn->detail->x86
361
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
362
13.5k
      .mem.segment = X86_REG_INVALID;
363
13.5k
    MI->flat_insn->detail->x86
364
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
365
13.5k
      .mem.base = X86_REG_INVALID;
366
13.5k
    MI->flat_insn->detail->x86
367
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
368
13.5k
      .mem.index = X86_REG_INVALID;
369
13.5k
    MI->flat_insn->detail->x86
370
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
371
13.5k
      .mem.scale = 1;
372
13.5k
    MI->flat_insn->detail->x86
373
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
374
13.5k
      .mem.disp = 0;
375
376
13.5k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
377
13.5k
            &MI->flat_insn->detail->x86.eflags);
378
13.5k
    MI->flat_insn->detail->x86
379
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
380
13.5k
      .access = access[MI->flat_insn->detail->x86.op_count];
381
13.5k
  }
382
383
13.5k
  SegReg = MCInst_getOperand(MI, Op + 1);
384
13.5k
  reg = MCOperand_getReg(SegReg);
385
  // If this has a segment register, print it.
386
13.5k
  if (reg) {
387
590
    _printOperand(MI, Op + 1, O);
388
590
    SStream_concat0(O, ":");
389
390
590
    if (MI->csh->detail_opt) {
391
590
      MI->flat_insn->detail->x86
392
590
        .operands[MI->flat_insn->detail->x86.op_count]
393
590
        .mem.segment = X86_register_map(reg);
394
590
    }
395
590
  }
396
397
13.5k
  SStream_concat0(O, "(");
398
13.5k
  set_mem_access(MI, true);
399
400
13.5k
  printOperand(MI, Op, O);
401
402
13.5k
  SStream_concat0(O, ")");
403
13.5k
  set_mem_access(MI, false);
404
13.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
4.42k
{
461
4.42k
  MI->x86opsize = 1;
462
4.42k
  printSrcIdx(MI, OpNo, O);
463
4.42k
}
464
465
static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
466
4.33k
{
467
4.33k
  MI->x86opsize = 2;
468
4.33k
  printSrcIdx(MI, OpNo, O);
469
4.33k
}
470
471
static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
472
3.72k
{
473
3.72k
  MI->x86opsize = 4;
474
3.72k
  printSrcIdx(MI, OpNo, O);
475
3.72k
}
476
477
static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
478
1.03k
{
479
1.03k
  MI->x86opsize = 8;
480
1.03k
  printSrcIdx(MI, OpNo, O);
481
1.03k
}
482
483
static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
484
6.66k
{
485
6.66k
  MI->x86opsize = 1;
486
6.66k
  printDstIdx(MI, OpNo, O);
487
6.66k
}
488
489
static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
490
4.26k
{
491
4.26k
  MI->x86opsize = 2;
492
4.26k
  printDstIdx(MI, OpNo, O);
493
4.26k
}
494
495
static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
496
4.76k
{
497
4.76k
  MI->x86opsize = 4;
498
4.76k
  printDstIdx(MI, OpNo, O);
499
4.76k
}
500
501
static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
502
1.86k
{
503
1.86k
  MI->x86opsize = 8;
504
1.86k
  printDstIdx(MI, OpNo, O);
505
1.86k
}
506
507
static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
508
4.02k
{
509
4.02k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op);
510
4.02k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
511
4.02k
  int reg;
512
513
4.02k
  if (MI->csh->detail_opt) {
514
4.02k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
515
516
4.02k
    MI->flat_insn->detail->x86
517
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
518
4.02k
      .type = X86_OP_MEM;
519
4.02k
    MI->flat_insn->detail->x86
520
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
521
4.02k
      .size = MI->x86opsize;
522
4.02k
    MI->flat_insn->detail->x86
523
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
524
4.02k
      .mem.segment = X86_REG_INVALID;
525
4.02k
    MI->flat_insn->detail->x86
526
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
527
4.02k
      .mem.base = X86_REG_INVALID;
528
4.02k
    MI->flat_insn->detail->x86
529
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
530
4.02k
      .mem.index = X86_REG_INVALID;
531
4.02k
    MI->flat_insn->detail->x86
532
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
533
4.02k
      .mem.scale = 1;
534
4.02k
    MI->flat_insn->detail->x86
535
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
536
4.02k
      .mem.disp = 0;
537
538
4.02k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
539
4.02k
            &MI->flat_insn->detail->x86.eflags);
540
4.02k
    MI->flat_insn->detail->x86
541
4.02k
      .operands[MI->flat_insn->detail->x86.op_count]
542
4.02k
      .access = access[MI->flat_insn->detail->x86.op_count];
543
4.02k
  }
544
545
  // If this has a segment register, print it.
546
4.02k
  reg = MCOperand_getReg(SegReg);
547
4.02k
  if (reg) {
548
375
    _printOperand(MI, Op + 1, O);
549
375
    SStream_concat0(O, ":");
550
551
375
    if (MI->csh->detail_opt) {
552
375
      MI->flat_insn->detail->x86
553
375
        .operands[MI->flat_insn->detail->x86.op_count]
554
375
        .mem.segment = X86_register_map(reg);
555
375
    }
556
375
  }
557
558
4.02k
  if (MCOperand_isImm(DispSpec)) {
559
4.02k
    int64_t imm = MCOperand_getImm(DispSpec);
560
4.02k
    if (MI->csh->detail_opt)
561
4.02k
      MI->flat_insn->detail->x86
562
4.02k
        .operands[MI->flat_insn->detail->x86.op_count]
563
4.02k
        .mem.disp = imm;
564
4.02k
    if (imm < 0) {
565
681
      SStream_concat(O, "0x%" PRIx64,
566
681
               x86_get_address_mask(MI->csh->mode) &
567
681
                 imm);
568
3.34k
    } else {
569
3.34k
      if (imm > HEX_THRESHOLD)
570
2.99k
        SStream_concat(O, "0x%" PRIx64, imm);
571
347
      else
572
347
        SStream_concat(O, "%" PRIu64, imm);
573
3.34k
    }
574
4.02k
  }
575
576
4.02k
  if (MI->csh->detail_opt)
577
4.02k
    MI->flat_insn->detail->x86.op_count++;
578
4.02k
}
579
580
static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
581
21.1k
{
582
21.1k
  uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff;
583
584
21.1k
  if (val > HEX_THRESHOLD)
585
17.5k
    SStream_concat(O, "$0x%x", val);
586
3.52k
  else
587
3.52k
    SStream_concat(O, "$%" PRIu8, val);
588
589
21.1k
  if (MI->csh->detail_opt) {
590
21.1k
    MI->flat_insn->detail->x86
591
21.1k
      .operands[MI->flat_insn->detail->x86.op_count]
592
21.1k
      .type = X86_OP_IMM;
593
21.1k
    MI->flat_insn->detail->x86
594
21.1k
      .operands[MI->flat_insn->detail->x86.op_count]
595
21.1k
      .imm = val;
596
21.1k
    MI->flat_insn->detail->x86
597
21.1k
      .operands[MI->flat_insn->detail->x86.op_count]
598
21.1k
      .size = 1;
599
21.1k
    MI->flat_insn->detail->x86.op_count++;
600
21.1k
  }
601
21.1k
}
602
603
static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
604
2.01k
{
605
2.01k
  MI->x86opsize = 1;
606
2.01k
  printMemOffset(MI, OpNo, O);
607
2.01k
}
608
609
static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
610
894
{
611
894
  MI->x86opsize = 2;
612
894
  printMemOffset(MI, OpNo, O);
613
894
}
614
615
static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
616
916
{
617
916
  MI->x86opsize = 4;
618
916
  printMemOffset(MI, OpNo, O);
619
916
}
620
621
static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
622
206
{
623
206
  MI->x86opsize = 8;
624
206
  printMemOffset(MI, OpNo, O);
625
206
}
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
138k
{
873
138k
  MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
874
138k
  MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
875
138k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
876
138k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
877
138k
  uint64_t ScaleVal;
878
138k
  int segreg;
879
138k
  int64_t DispVal = 1;
880
881
138k
  if (MI->csh->detail_opt) {
882
138k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
883
884
138k
    MI->flat_insn->detail->x86
885
138k
      .operands[MI->flat_insn->detail->x86.op_count]
886
138k
      .type = X86_OP_MEM;
887
138k
    MI->flat_insn->detail->x86
888
138k
      .operands[MI->flat_insn->detail->x86.op_count]
889
138k
      .size = MI->x86opsize;
890
138k
    MI->flat_insn->detail->x86
891
138k
      .operands[MI->flat_insn->detail->x86.op_count]
892
138k
      .mem.segment = X86_REG_INVALID;
893
138k
    MI->flat_insn->detail->x86
894
138k
      .operands[MI->flat_insn->detail->x86.op_count]
895
138k
      .mem.base = X86_register_map(MCOperand_getReg(BaseReg));
896
138k
    if (MCOperand_getReg(IndexReg) != X86_EIZ) {
897
138k
      MI->flat_insn->detail->x86
898
138k
        .operands[MI->flat_insn->detail->x86.op_count]
899
138k
        .mem.index =
900
138k
        X86_register_map(MCOperand_getReg(IndexReg));
901
138k
    }
902
138k
    MI->flat_insn->detail->x86
903
138k
      .operands[MI->flat_insn->detail->x86.op_count]
904
138k
      .mem.scale = 1;
905
138k
    MI->flat_insn->detail->x86
906
138k
      .operands[MI->flat_insn->detail->x86.op_count]
907
138k
      .mem.disp = 0;
908
909
138k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
910
138k
            &MI->flat_insn->detail->x86.eflags);
911
138k
    MI->flat_insn->detail->x86
912
138k
      .operands[MI->flat_insn->detail->x86.op_count]
913
138k
      .access = access[MI->flat_insn->detail->x86.op_count];
914
138k
  }
915
916
  // If this has a segment register, print it.
917
138k
  segreg = MCOperand_getReg(SegReg);
918
138k
  if (segreg) {
919
3.05k
    _printOperand(MI, Op + X86_AddrSegmentReg, O);
920
3.05k
    SStream_concat0(O, ":");
921
922
3.05k
    if (MI->csh->detail_opt) {
923
3.05k
      MI->flat_insn->detail->x86
924
3.05k
        .operands[MI->flat_insn->detail->x86.op_count]
925
3.05k
        .mem.segment = X86_register_map(segreg);
926
3.05k
    }
927
3.05k
  }
928
929
138k
  if (MCOperand_isImm(DispSpec)) {
930
138k
    DispVal = MCOperand_getImm(DispSpec);
931
138k
    if (MI->csh->detail_opt)
932
138k
      MI->flat_insn->detail->x86
933
138k
        .operands[MI->flat_insn->detail->x86.op_count]
934
138k
        .mem.disp = DispVal;
935
138k
    if (DispVal) {
936
46.0k
      if (MCOperand_getReg(IndexReg) ||
937
42.8k
          MCOperand_getReg(BaseReg)) {
938
42.8k
        printInt64(O, DispVal);
939
42.8k
      } else {
940
        // only immediate as address of memory
941
3.28k
        if (DispVal < 0) {
942
1.51k
          SStream_concat(O, "0x%" PRIx64,
943
1.51k
                   x86_get_address_mask(
944
1.51k
                     MI->csh->mode) &
945
1.51k
                     DispVal);
946
1.77k
        } else {
947
1.77k
          if (DispVal > HEX_THRESHOLD)
948
1.53k
            SStream_concat(O, "0x%" PRIx64,
949
1.53k
                     DispVal);
950
237
          else
951
237
            SStream_concat(O, "%" PRIu64,
952
237
                     DispVal);
953
1.77k
        }
954
3.28k
      }
955
46.0k
    }
956
138k
  }
957
958
138k
  if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
959
135k
    SStream_concat0(O, "(");
960
961
135k
    if (MCOperand_getReg(BaseReg))
962
134k
      _printOperand(MI, Op + X86_AddrBaseReg, O);
963
964
135k
    if (MCOperand_getReg(IndexReg) &&
965
45.6k
        MCOperand_getReg(IndexReg) != X86_EIZ) {
966
45.0k
      SStream_concat0(O, ", ");
967
45.0k
      _printOperand(MI, Op + X86_AddrIndexReg, O);
968
45.0k
      ScaleVal = MCOperand_getImm(
969
45.0k
        MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
970
45.0k
      if (MI->csh->detail_opt)
971
45.0k
        MI->flat_insn->detail->x86
972
45.0k
          .operands[MI->flat_insn->detail->x86
973
45.0k
                .op_count]
974
45.0k
          .mem.scale = (int)ScaleVal;
975
45.0k
      if (ScaleVal != 1) {
976
4.74k
        SStream_concat(O, ", %" PRIu64, ScaleVal);
977
4.74k
      }
978
45.0k
    }
979
980
135k
    SStream_concat0(O, ")");
981
135k
  } else {
982
3.62k
    if (!DispVal)
983
338
      SStream_concat0(O, "0");
984
3.62k
  }
985
986
138k
  if (MI->csh->detail_opt)
987
138k
    MI->flat_insn->detail->x86.op_count++;
988
138k
}
989
990
static void printanymem(MCInst *MI, unsigned OpNo, SStream *O)
991
3.77k
{
992
3.77k
  switch (MI->Opcode) {
993
212
  default:
994
212
    break;
995
401
  case X86_LEA16r:
996
401
    MI->x86opsize = 2;
997
401
    break;
998
237
  case X86_LEA32r:
999
632
  case X86_LEA64_32r:
1000
632
    MI->x86opsize = 4;
1001
632
    break;
1002
202
  case X86_LEA64r:
1003
202
    MI->x86opsize = 8;
1004
202
    break;
1005
0
#ifndef CAPSTONE_X86_REDUCE
1006
194
  case X86_BNDCL32rm:
1007
474
  case X86_BNDCN32rm:
1008
673
  case X86_BNDCU32rm:
1009
967
  case X86_BNDSTXmr:
1010
1.48k
  case X86_BNDLDXrm:
1011
1.74k
  case X86_BNDCL64rm:
1012
2.05k
  case X86_BNDCN64rm:
1013
2.32k
  case X86_BNDCU64rm:
1014
2.32k
    MI->x86opsize = 16;
1015
2.32k
    break;
1016
3.77k
#endif
1017
3.77k
  }
1018
1019
3.77k
  printMemReference(MI, OpNo, O);
1020
3.77k
}
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
485k
{
1035
485k
  SStream_concat(OS, "%%%s", getRegisterName(RegNo));
1036
485k
}
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