Coverage Report

Created: 2026-09-28 06:34

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