Coverage Report

Created: 2026-11-12 06:22

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 "../../Mapping.h"
49
#include "X86Mapping.h"
50
#include "X86BaseInfo.h"
51
#include "X86InstPrinterCommon.h"
52
53
#define GET_INSTRINFO_ENUM
54
#ifdef CAPSTONE_X86_REDUCE
55
#include "X86GenInstrInfo_reduce.inc"
56
#else
57
#include "X86GenInstrInfo.inc"
58
#endif
59
60
#define GET_REGINFO_ENUM
61
#include "X86GenRegisterInfo.inc"
62
63
static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
64
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
65
66
static void set_mem_access(MCInst *MI, bool status)
67
50.1k
{
68
50.1k
  if (!detail_is_set(MI))
69
0
    return;
70
71
50.1k
  MI->csh->doing_mem = status;
72
50.1k
  if (!status)
73
    // done, create the next operand slot
74
25.0k
    MI->flat_insn->detail->x86.op_count++;
75
50.1k
}
76
77
static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
78
11.2k
{
79
11.2k
  switch (x86_get_bit_mode(MI->csh->mode)) {
80
3.83k
  case CS_MODE_16:
81
3.83k
    switch (MI->flat_insn->id) {
82
1.22k
    default:
83
1.22k
      MI->x86opsize = 2;
84
1.22k
      break;
85
529
    case X86_INS_LJMP:
86
943
    case X86_INS_LCALL:
87
943
      MI->x86opsize = 4;
88
943
      break;
89
420
    case X86_INS_SGDT:
90
849
    case X86_INS_SIDT:
91
1.27k
    case X86_INS_LGDT:
92
1.66k
    case X86_INS_LIDT:
93
1.66k
      MI->x86opsize = 6;
94
1.66k
      break;
95
3.83k
    }
96
3.83k
    break;
97
3.85k
  case CS_MODE_32:
98
3.85k
    switch (MI->flat_insn->id) {
99
695
    default:
100
695
      MI->x86opsize = 4;
101
695
      break;
102
477
    case X86_INS_LJMP:
103
1.09k
    case X86_INS_JMP:
104
1.48k
    case X86_INS_LCALL:
105
1.88k
    case X86_INS_SGDT:
106
2.36k
    case X86_INS_SIDT:
107
2.77k
    case X86_INS_LGDT:
108
3.16k
    case X86_INS_LIDT:
109
3.16k
      MI->x86opsize = 6;
110
3.16k
      break;
111
3.85k
    }
112
3.85k
    break;
113
3.85k
  case CS_MODE_64:
114
3.52k
    switch (MI->flat_insn->id) {
115
791
    default:
116
791
      MI->x86opsize = 8;
117
791
      break;
118
549
    case X86_INS_LJMP:
119
957
    case X86_INS_LCALL:
120
1.48k
    case X86_INS_SGDT:
121
1.90k
    case X86_INS_SIDT:
122
2.33k
    case X86_INS_LGDT:
123
2.73k
    case X86_INS_LIDT:
124
2.73k
      MI->x86opsize = 10;
125
2.73k
      break;
126
3.52k
    }
127
3.52k
    break;
128
3.52k
  default: // never reach
129
0
    break;
130
11.2k
  }
131
132
11.2k
  printMemReference(MI, OpNo, O);
133
11.2k
}
134
135
static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
136
52.9k
{
137
52.9k
  MI->x86opsize = 1;
138
52.9k
  printMemReference(MI, OpNo, O);
139
52.9k
}
140
141
static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
142
29.4k
{
143
29.4k
  MI->x86opsize = 2;
144
145
29.4k
  printMemReference(MI, OpNo, O);
146
29.4k
}
147
148
static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
149
30.3k
{
150
30.3k
  MI->x86opsize = 4;
151
152
30.3k
  printMemReference(MI, OpNo, O);
153
30.3k
}
154
155
static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
156
18.8k
{
157
18.8k
  MI->x86opsize = 8;
158
18.8k
  printMemReference(MI, OpNo, O);
159
18.8k
}
160
161
static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
162
8.92k
{
163
8.92k
  MI->x86opsize = 16;
164
8.92k
  printMemReference(MI, OpNo, O);
165
8.92k
}
166
167
static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
168
5.56k
{
169
5.56k
  MI->x86opsize = 64;
170
5.56k
  printMemReference(MI, OpNo, O);
171
5.56k
}
172
173
#ifndef CAPSTONE_X86_REDUCE
174
static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
175
5.93k
{
176
5.93k
  MI->x86opsize = 32;
177
5.93k
  printMemReference(MI, OpNo, O);
178
5.93k
}
179
180
static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
181
8.46k
{
182
8.46k
  switch (MCInst_getOpcode(MI)) {
183
6.68k
  default:
184
6.68k
    MI->x86opsize = 4;
185
6.68k
    break;
186
654
  case X86_FSTENVm:
187
1.78k
  case X86_FLDENVm:
188
    // TODO: fix this in tablegen instead
189
1.78k
    switch (x86_get_bit_mode(MI->csh->mode)) {
190
0
    default: // never reach
191
0
      break;
192
501
    case CS_MODE_16:
193
501
      MI->x86opsize = 14;
194
501
      break;
195
429
    case CS_MODE_32:
196
1.28k
    case CS_MODE_64:
197
1.28k
      MI->x86opsize = 28;
198
1.28k
      break;
199
1.78k
    }
200
1.78k
    break;
201
8.46k
  }
202
203
8.46k
  printMemReference(MI, OpNo, O);
204
8.46k
}
205
206
static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
207
7.31k
{
208
7.31k
  MI->x86opsize = 8;
209
7.31k
  printMemReference(MI, OpNo, O);
210
7.31k
}
211
212
static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
213
411
{
214
411
  MI->x86opsize = 10;
215
411
  printMemReference(MI, OpNo, O);
216
411
}
217
218
static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
219
6.11k
{
220
6.11k
  MI->x86opsize = 16;
221
6.11k
  printMemReference(MI, OpNo, O);
222
6.11k
}
223
224
static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
225
6.42k
{
226
6.42k
  MI->x86opsize = 32;
227
6.42k
  printMemReference(MI, OpNo, O);
228
6.42k
}
229
230
static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
231
5.45k
{
232
5.45k
  MI->x86opsize = 64;
233
5.45k
  printMemReference(MI, OpNo, O);
234
5.45k
}
235
236
#endif
237
238
static void printRegName(SStream *OS, unsigned RegNo);
239
240
// local printOperand, without updating public operands
241
static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
242
274k
{
243
274k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
244
274k
  if (MCOperand_isReg(Op)) {
245
274k
    printRegName(O, MCOperand_getReg(Op));
246
274k
  } else if (MCOperand_isImm(Op)) {
247
0
    uint8_t encsize;
248
0
    uint8_t opsize =
249
0
      X86_immediate_size(MCInst_getOpcode(MI), &encsize);
250
251
    // Print X86 immediates as signed values.
252
0
    int64_t imm = MCOperand_getImm(Op);
253
0
    if (imm < 0) {
254
0
      if (MI->csh->imm_unsigned) {
255
0
        if (opsize) {
256
0
          switch (opsize) {
257
0
          default:
258
0
            break;
259
0
          case 1:
260
0
            imm &= 0xff;
261
0
            break;
262
0
          case 2:
263
0
            imm &= 0xffff;
264
0
            break;
265
0
          case 4:
266
0
            imm &= 0xffffffff;
267
0
            break;
268
0
          }
269
0
        }
270
271
0
        SStream_concat(O, "$0x%" PRIx64, imm);
272
0
      } else {
273
0
        if (imm < -HEX_THRESHOLD)
274
0
          SStream_concat(O, "$-0x%" PRIx64, -imm);
275
0
        else
276
0
          SStream_concat(O, "$-%" PRIu64, -imm);
277
0
      }
278
0
    } else {
279
0
      if (imm > HEX_THRESHOLD)
280
0
        SStream_concat(O, "$0x%" PRIx64, imm);
281
0
      else
282
0
        SStream_concat(O, "$%" PRIu64, imm);
283
0
    }
284
0
  }
285
274k
}
286
287
// convert Intel access info to AT&T access info
288
static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access,
289
        uint64_t *eflags)
290
668k
{
291
668k
  uint8_t count, i;
292
668k
  const uint8_t *arr = X86_get_op_access(h, id, eflags);
293
294
  // initialize access
295
668k
  memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
296
668k
  if (!arr) {
297
0
    return;
298
0
  }
299
300
  // find the non-zero last entry
301
1.97M
  for (count = 0; arr[count]; count++)
302
1.30M
    ;
303
304
668k
  if (count == 0)
305
56.0k
    return;
306
307
  // copy in reverse order this access array from Intel syntax -> AT&T syntax
308
612k
  count--;
309
1.92M
  for (i = 0; i <= count && ((count - i) < CS_X86_MAXIMUM_OPERAND_SIZE) &&
310
1.30M
        i < CS_X86_MAXIMUM_OPERAND_SIZE;
311
1.30M
       i++) {
312
1.30M
    if (arr[count - i] != CS_AC_IGNORE)
313
1.12M
      access[i] = arr[count - i];
314
182k
    else
315
182k
      access[i] = 0;
316
1.30M
  }
317
612k
}
318
319
static void fixup_evex_opmask_access(MCInst *MI)
320
283k
{
321
283k
  cs_x86 *x86 = &MI->flat_insn->detail->x86;
322
283k
  const uint8_t *arr;
323
283k
  uint8_t count, i, access_index = 0;
324
283k
  if (!(MI->flags & X86_IP_HAS_EVEX_OPMASK))
325
262k
    return;
326
327
21.9k
  arr = X86_get_op_access(MI->csh, MCInst_getOpcode(MI), &x86->eflags);
328
21.9k
  if (!arr)
329
0
    return;
330
77.5k
  for (count = 0; count < CS_X86_MAXIMUM_OPERAND_SIZE; ++count) {
331
77.5k
    if (!arr[count])
332
21.9k
      break;
333
77.5k
  }
334
21.9k
  if (count < 2 || count != x86->op_count)
335
21.5k
    return;
336
337
1.27k
  for (i = count; i > 2; --i) {
338
850
    x86->operands[access_index].access = arr[i - 1];
339
850
    if (x86->operands[access_index].access == CS_AC_IGNORE)
340
0
      x86->operands[access_index].access = 0;
341
850
    access_index++;
342
850
  }
343
428
  x86->operands[access_index++].access = arr[0];
344
428
  x86->operands[access_index].access = arr[1];
345
428
}
346
347
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
348
19.7k
{
349
19.7k
  MCOperand *SegReg;
350
19.7k
  int reg;
351
352
19.7k
  if (MI->csh->detail_opt) {
353
19.7k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
354
355
19.7k
    MI->flat_insn->detail->x86
356
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
357
19.7k
      .type = X86_OP_MEM;
358
19.7k
    MI->flat_insn->detail->x86
359
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
360
19.7k
      .size = MI->x86opsize;
361
19.7k
    MI->flat_insn->detail->x86
362
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
363
19.7k
      .mem.segment = X86_REG_INVALID;
364
19.7k
    MI->flat_insn->detail->x86
365
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
366
19.7k
      .mem.base = X86_REG_INVALID;
367
19.7k
    MI->flat_insn->detail->x86
368
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
369
19.7k
      .mem.index = X86_REG_INVALID;
370
19.7k
    MI->flat_insn->detail->x86
371
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
372
19.7k
      .mem.scale = 1;
373
19.7k
    MI->flat_insn->detail->x86
374
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
375
19.7k
      .mem.disp = 0;
376
377
19.7k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
378
19.7k
            &MI->flat_insn->detail->x86.eflags);
379
19.7k
    MI->flat_insn->detail->x86
380
19.7k
      .operands[MI->flat_insn->detail->x86.op_count]
381
19.7k
      .access = access[MI->flat_insn->detail->x86.op_count];
382
19.7k
  }
383
384
19.7k
  SegReg = MCInst_getOperand(MI, Op + 1);
385
19.7k
  reg = MCOperand_getReg(SegReg);
386
  // If this has a segment register, print it.
387
19.7k
  if (reg) {
388
524
    _printOperand(MI, Op + 1, O);
389
524
    SStream_concat0(O, ":");
390
391
524
    if (MI->csh->detail_opt) {
392
524
      MI->flat_insn->detail->x86
393
524
        .operands[MI->flat_insn->detail->x86.op_count]
394
524
        .mem.segment = X86_register_map(reg);
395
524
    }
396
524
  }
397
398
19.7k
  SStream_concat0(O, "(");
399
19.7k
  set_mem_access(MI, true);
400
401
19.7k
  printOperand(MI, Op, O);
402
403
19.7k
  SStream_concat0(O, ")");
404
19.7k
  set_mem_access(MI, false);
405
19.7k
}
406
407
static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
408
13.5k
{
409
13.5k
  if (MI->csh->detail_opt) {
410
13.5k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
411
412
13.5k
    MI->flat_insn->detail->x86
413
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
414
13.5k
      .type = X86_OP_MEM;
415
13.5k
    MI->flat_insn->detail->x86
416
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
417
13.5k
      .size = MI->x86opsize;
418
13.5k
    MI->flat_insn->detail->x86
419
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
420
13.5k
      .mem.segment = X86_REG_INVALID;
421
13.5k
    MI->flat_insn->detail->x86
422
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
423
13.5k
      .mem.base = X86_REG_INVALID;
424
13.5k
    MI->flat_insn->detail->x86
425
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
426
13.5k
      .mem.index = X86_REG_INVALID;
427
13.5k
    MI->flat_insn->detail->x86
428
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
429
13.5k
      .mem.scale = 1;
430
13.5k
    MI->flat_insn->detail->x86
431
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
432
13.5k
      .mem.disp = 0;
433
434
13.5k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
435
13.5k
            &MI->flat_insn->detail->x86.eflags);
436
13.5k
    MI->flat_insn->detail->x86
437
13.5k
      .operands[MI->flat_insn->detail->x86.op_count]
438
13.5k
      .access = access[MI->flat_insn->detail->x86.op_count];
439
13.5k
  }
440
441
  // DI accesses are always ES-based on non-64bit mode
442
13.5k
  if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
443
6.63k
    SStream_concat0(O, "%es:(");
444
6.63k
    if (MI->csh->detail_opt) {
445
6.63k
      MI->flat_insn->detail->x86
446
6.63k
        .operands[MI->flat_insn->detail->x86.op_count]
447
6.63k
        .mem.segment = X86_REG_ES;
448
6.63k
    }
449
6.63k
  } else
450
6.93k
    SStream_concat0(O, "(");
451
452
13.5k
  set_mem_access(MI, true);
453
454
13.5k
  printOperand(MI, Op, O);
455
456
13.5k
  SStream_concat0(O, ")");
457
13.5k
  set_mem_access(MI, false);
458
13.5k
}
459
460
static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
461
5.99k
{
462
5.99k
  MI->x86opsize = 1;
463
5.99k
  printSrcIdx(MI, OpNo, O);
464
5.99k
}
465
466
static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
467
5.07k
{
468
5.07k
  MI->x86opsize = 2;
469
5.07k
  printSrcIdx(MI, OpNo, O);
470
5.07k
}
471
472
static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
473
6.52k
{
474
6.52k
  MI->x86opsize = 4;
475
6.52k
  printSrcIdx(MI, OpNo, O);
476
6.52k
}
477
478
static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
479
2.11k
{
480
2.11k
  MI->x86opsize = 8;
481
2.11k
  printSrcIdx(MI, OpNo, O);
482
2.11k
}
483
484
static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
485
7.34k
{
486
7.34k
  MI->x86opsize = 1;
487
7.34k
  printDstIdx(MI, OpNo, O);
488
7.34k
}
489
490
static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
491
4.57k
{
492
4.57k
  MI->x86opsize = 2;
493
4.57k
  printDstIdx(MI, OpNo, O);
494
4.57k
}
495
496
static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
497
6.94k
{
498
6.94k
  MI->x86opsize = 4;
499
6.94k
  printDstIdx(MI, OpNo, O);
500
6.94k
}
501
502
static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
503
2.66k
{
504
2.66k
  MI->x86opsize = 8;
505
2.66k
  printDstIdx(MI, OpNo, O);
506
2.66k
}
507
508
static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
509
5.49k
{
510
5.49k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op);
511
5.49k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
512
5.49k
  int reg;
513
514
5.49k
  if (MI->csh->detail_opt) {
515
5.49k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
516
517
5.49k
    MI->flat_insn->detail->x86
518
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
519
5.49k
      .type = X86_OP_MEM;
520
5.49k
    MI->flat_insn->detail->x86
521
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
522
5.49k
      .size = MI->x86opsize;
523
5.49k
    MI->flat_insn->detail->x86
524
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
525
5.49k
      .mem.segment = X86_REG_INVALID;
526
5.49k
    MI->flat_insn->detail->x86
527
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
528
5.49k
      .mem.base = X86_REG_INVALID;
529
5.49k
    MI->flat_insn->detail->x86
530
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
531
5.49k
      .mem.index = X86_REG_INVALID;
532
5.49k
    MI->flat_insn->detail->x86
533
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
534
5.49k
      .mem.scale = 1;
535
5.49k
    MI->flat_insn->detail->x86
536
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
537
5.49k
      .mem.disp = 0;
538
539
5.49k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
540
5.49k
            &MI->flat_insn->detail->x86.eflags);
541
5.49k
    MI->flat_insn->detail->x86
542
5.49k
      .operands[MI->flat_insn->detail->x86.op_count]
543
5.49k
      .access = access[MI->flat_insn->detail->x86.op_count];
544
5.49k
  }
545
546
  // If this has a segment register, print it.
547
5.49k
  reg = MCOperand_getReg(SegReg);
548
5.49k
  if (reg) {
549
411
    _printOperand(MI, Op + 1, O);
550
411
    SStream_concat0(O, ":");
551
552
411
    if (MI->csh->detail_opt) {
553
411
      MI->flat_insn->detail->x86
554
411
        .operands[MI->flat_insn->detail->x86.op_count]
555
411
        .mem.segment = X86_register_map(reg);
556
411
    }
557
411
  }
558
559
5.49k
  if (MCOperand_isImm(DispSpec)) {
560
5.49k
    int64_t imm = MCOperand_getImm(DispSpec);
561
5.49k
    if (MI->csh->detail_opt)
562
5.49k
      MI->flat_insn->detail->x86
563
5.49k
        .operands[MI->flat_insn->detail->x86.op_count]
564
5.49k
        .mem.disp = imm;
565
5.49k
    if (imm < 0) {
566
914
      SStream_concat(O, "0x%" PRIx64,
567
914
               x86_get_address_mask(MI->csh->mode) &
568
914
                 imm);
569
4.58k
    } else {
570
4.58k
      if (imm > HEX_THRESHOLD)
571
4.11k
        SStream_concat(O, "0x%" PRIx64, imm);
572
466
      else
573
466
        SStream_concat(O, "%" PRIu64, imm);
574
4.58k
    }
575
5.49k
  }
576
577
5.49k
  if (MI->csh->detail_opt)
578
5.49k
    MI->flat_insn->detail->x86.op_count++;
579
5.49k
}
580
581
static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
582
43.3k
{
583
43.3k
  uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff;
584
585
43.3k
  if (val > HEX_THRESHOLD)
586
37.2k
    SStream_concat(O, "$0x%x", val);
587
6.04k
  else
588
6.04k
    SStream_concat(O, "$%" PRIu8, val);
589
590
43.3k
  if (MI->csh->detail_opt) {
591
43.3k
    MI->flat_insn->detail->x86
592
43.3k
      .operands[MI->flat_insn->detail->x86.op_count]
593
43.3k
      .type = X86_OP_IMM;
594
43.3k
    MI->flat_insn->detail->x86
595
43.3k
      .operands[MI->flat_insn->detail->x86.op_count]
596
43.3k
      .imm = val;
597
43.3k
    MI->flat_insn->detail->x86
598
43.3k
      .operands[MI->flat_insn->detail->x86.op_count]
599
43.3k
      .size = 1;
600
43.3k
    MI->flat_insn->detail->x86.op_count++;
601
43.3k
  }
602
43.3k
}
603
604
static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
605
2.98k
{
606
2.98k
  MI->x86opsize = 1;
607
2.98k
  printMemOffset(MI, OpNo, O);
608
2.98k
}
609
610
static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
611
927
{
612
927
  MI->x86opsize = 2;
613
927
  printMemOffset(MI, OpNo, O);
614
927
}
615
616
static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
617
1.17k
{
618
1.17k
  MI->x86opsize = 4;
619
1.17k
  printMemOffset(MI, OpNo, O);
620
1.17k
}
621
622
static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
623
406
{
624
406
  MI->x86opsize = 8;
625
406
  printMemOffset(MI, OpNo, O);
626
406
}
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
17.8k
{
634
17.8k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
635
17.8k
  if (MCOperand_isImm(Op)) {
636
17.8k
    int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size +
637
17.8k
            MI->address;
638
639
    // truncate imm for non-64bit
640
17.8k
    if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
641
11.1k
      imm = imm & 0xffffffff;
642
11.1k
    } 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
17.8k
    if (imm < 0) {
648
435
      SStream_concat(O, "0x%" PRIx64, imm);
649
17.4k
    } else {
650
17.4k
      if (imm > HEX_THRESHOLD)
651
17.4k
        SStream_concat(O, "0x%" PRIx64, imm);
652
18
      else
653
18
        SStream_concat(O, "%" PRIu64, imm);
654
17.4k
    }
655
17.8k
    if (MI->csh->detail_opt) {
656
17.8k
      MI->flat_insn->detail->x86
657
17.8k
        .operands[MI->flat_insn->detail->x86.op_count]
658
17.8k
        .type = X86_OP_IMM;
659
17.8k
      MI->has_imm = true;
660
17.8k
      MI->flat_insn->detail->x86
661
17.8k
        .operands[MI->flat_insn->detail->x86.op_count]
662
17.8k
        .imm = imm;
663
17.8k
      MI->flat_insn->detail->x86.op_count++;
664
17.8k
    }
665
17.8k
  }
666
17.8k
}
667
668
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
669
294k
{
670
294k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
671
294k
  if (MCOperand_isReg(Op)) {
672
263k
    unsigned int reg = MCOperand_getReg(Op);
673
263k
    printRegName(O, reg);
674
263k
    if (MI->csh->detail_opt) {
675
263k
      if (MI->csh->doing_mem) {
676
25.0k
        MI->flat_insn->detail->x86
677
25.0k
          .operands[MI->flat_insn->detail->x86
678
25.0k
                .op_count]
679
25.0k
          .mem.base = X86_register_map(reg);
680
238k
      } else {
681
238k
        uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
682
683
238k
        MI->flat_insn->detail->x86
684
238k
          .operands[MI->flat_insn->detail->x86
685
238k
                .op_count]
686
238k
          .type = X86_OP_REG;
687
238k
        MI->flat_insn->detail->x86
688
238k
          .operands[MI->flat_insn->detail->x86
689
238k
                .op_count]
690
238k
          .reg = X86_register_map(reg);
691
238k
        MI->flat_insn->detail->x86
692
238k
          .operands[MI->flat_insn->detail->x86
693
238k
                .op_count]
694
238k
          .size =
695
238k
          MI->csh->regsize_map[X86_register_map(
696
238k
            reg)];
697
698
238k
        get_op_access(
699
238k
          MI->csh, MCInst_getOpcode(MI), access,
700
238k
          &MI->flat_insn->detail->x86.eflags);
701
238k
        MI->flat_insn->detail->x86
702
238k
          .operands[MI->flat_insn->detail->x86
703
238k
                .op_count]
704
238k
          .access =
705
238k
          access[MI->flat_insn->detail->x86
706
238k
                   .op_count];
707
708
238k
        MI->flat_insn->detail->x86.op_count++;
709
238k
      }
710
263k
    }
711
263k
  } else if (MCOperand_isImm(Op)) {
712
    // Print X86 immediates as signed values.
713
30.8k
    uint8_t encsize;
714
30.8k
    int64_t imm = MCOperand_getImm(Op);
715
30.8k
    uint8_t opsize =
716
30.8k
      X86_immediate_size(MCInst_getOpcode(MI), &encsize);
717
718
30.8k
    if (opsize == 1) { // print 1 byte immediate in positive form
719
13.8k
      imm = imm & 0xff;
720
13.8k
    }
721
722
30.8k
    switch (MI->flat_insn->id) {
723
14.2k
    default:
724
14.2k
      if (imm >= 0) {
725
12.3k
        if (imm > HEX_THRESHOLD)
726
11.0k
          SStream_concat(O, "$0x%" PRIx64, imm);
727
1.35k
        else
728
1.35k
          SStream_concat(O, "$%" PRIu64, imm);
729
12.3k
      } else {
730
1.89k
        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.89k
        } else {
752
1.89k
          if (imm ==
753
1.89k
              0x8000000000000000LL) // imm == -imm
754
0
            SStream_concat0(
755
0
              O,
756
0
              "$0x8000000000000000");
757
1.89k
          else if (imm < -HEX_THRESHOLD)
758
1.63k
            SStream_concat(O,
759
1.63k
                     "$-0x%" PRIx64,
760
1.63k
                     -imm);
761
261
          else
762
261
            SStream_concat(O, "$-%" PRIu64,
763
261
                     -imm);
764
1.89k
        }
765
1.89k
      }
766
14.2k
      break;
767
768
14.2k
    case X86_INS_MOVABS:
769
6.07k
    case X86_INS_MOV:
770
      // do not print number in negative form
771
      // Use unsigned comparison to handle values >= 2^63 correctly
772
6.07k
      if ((uint64_t)imm > HEX_THRESHOLD)
773
5.04k
        SStream_concat(O, "$0x%" PRIx64, imm);
774
1.02k
      else
775
1.02k
        SStream_concat(O, "$%" PRIu64, imm);
776
6.07k
      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
586
    case X86_INS_LCALL:
791
1.16k
    case X86_INS_LJMP:
792
1.16k
    case X86_INS_JMP:
793
      // always print address in positive form
794
1.16k
      if (OpNo == 1) { // selector is ptr16
795
581
        imm = imm & 0xffff;
796
581
        opsize = 2;
797
581
      } else
798
581
        opsize = 4;
799
1.16k
      SStream_concat(O, "$0x%" PRIx64, imm);
800
1.16k
      break;
801
802
2.25k
    case X86_INS_AND:
803
4.21k
    case X86_INS_OR:
804
6.11k
    case X86_INS_XOR:
805
      // do not print number in negative form
806
6.11k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
807
548
        SStream_concat(O, "$%" PRIu64, imm);
808
5.56k
      else {
809
5.56k
        imm = arch_masks[opsize ? opsize : MI->imm_size] &
810
5.56k
              imm;
811
5.56k
        SStream_concat(O, "$0x%" PRIx64, imm);
812
5.56k
      }
813
6.11k
      break;
814
815
2.87k
    case X86_INS_RET:
816
3.24k
    case X86_INS_RETF:
817
      // RET imm16
818
3.24k
      if (imm >= 0 && imm <= HEX_THRESHOLD)
819
243
        SStream_concat(O, "$%" PRIu64, imm);
820
3.00k
      else {
821
3.00k
        imm = 0xffff & imm;
822
3.00k
        SStream_concat(O, "$0x%x", imm);
823
3.00k
      }
824
3.24k
      break;
825
30.8k
    }
826
827
30.8k
    if (MI->csh->detail_opt) {
828
30.8k
      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
30.8k
      } else {
838
30.8k
        MI->flat_insn->detail->x86
839
30.8k
          .operands[MI->flat_insn->detail->x86
840
30.8k
                .op_count]
841
30.8k
          .type = X86_OP_IMM;
842
30.8k
        MI->has_imm = true;
843
30.8k
        MI->flat_insn->detail->x86
844
30.8k
          .operands[MI->flat_insn->detail->x86
845
30.8k
                .op_count]
846
30.8k
          .imm = imm;
847
848
30.8k
        if (opsize > 0) {
849
26.0k
          MI->flat_insn->detail->x86
850
26.0k
            .operands[MI->flat_insn->detail
851
26.0k
                  ->x86.op_count]
852
26.0k
            .size = opsize;
853
26.0k
          MI->flat_insn->detail->x86.encoding
854
26.0k
            .imm_size = encsize;
855
26.0k
        } 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
4.84k
        else
861
4.84k
          MI->flat_insn->detail->x86
862
4.84k
            .operands[MI->flat_insn->detail
863
4.84k
                  ->x86.op_count]
864
4.84k
            .size = MI->imm_size;
865
866
30.8k
        MI->flat_insn->detail->x86.op_count++;
867
30.8k
      }
868
30.8k
    }
869
30.8k
  }
870
294k
}
871
872
static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
873
203k
{
874
203k
  MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
875
203k
  MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
876
203k
  MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
877
203k
  MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
878
203k
  uint64_t ScaleVal;
879
203k
  int segreg;
880
203k
  int64_t DispVal = 1;
881
882
203k
  if (MI->csh->detail_opt) {
883
203k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE];
884
885
203k
    MI->flat_insn->detail->x86
886
203k
      .operands[MI->flat_insn->detail->x86.op_count]
887
203k
      .type = X86_OP_MEM;
888
203k
    MI->flat_insn->detail->x86
889
203k
      .operands[MI->flat_insn->detail->x86.op_count]
890
203k
      .size = MI->x86opsize;
891
203k
    MI->flat_insn->detail->x86
892
203k
      .operands[MI->flat_insn->detail->x86.op_count]
893
203k
      .mem.segment = X86_REG_INVALID;
894
203k
    MI->flat_insn->detail->x86
895
203k
      .operands[MI->flat_insn->detail->x86.op_count]
896
203k
      .mem.base = X86_register_map(MCOperand_getReg(BaseReg));
897
203k
    if (MCOperand_getReg(IndexReg) != X86_EIZ) {
898
203k
      MI->flat_insn->detail->x86
899
203k
        .operands[MI->flat_insn->detail->x86.op_count]
900
203k
        .mem.index =
901
203k
        X86_register_map(MCOperand_getReg(IndexReg));
902
203k
    }
903
203k
    MI->flat_insn->detail->x86
904
203k
      .operands[MI->flat_insn->detail->x86.op_count]
905
203k
      .mem.scale = 1;
906
203k
    MI->flat_insn->detail->x86
907
203k
      .operands[MI->flat_insn->detail->x86.op_count]
908
203k
      .mem.disp = 0;
909
910
203k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
911
203k
            &MI->flat_insn->detail->x86.eflags);
912
203k
    MI->flat_insn->detail->x86
913
203k
      .operands[MI->flat_insn->detail->x86.op_count]
914
203k
      .access = access[MI->flat_insn->detail->x86.op_count];
915
203k
  }
916
917
  // If this has a segment register, print it.
918
203k
  segreg = MCOperand_getReg(SegReg);
919
203k
  if (segreg) {
920
5.02k
    _printOperand(MI, Op + X86_AddrSegmentReg, O);
921
5.02k
    SStream_concat0(O, ":");
922
923
5.02k
    if (MI->csh->detail_opt) {
924
5.02k
      MI->flat_insn->detail->x86
925
5.02k
        .operands[MI->flat_insn->detail->x86.op_count]
926
5.02k
        .mem.segment = X86_register_map(segreg);
927
5.02k
    }
928
5.02k
  }
929
930
203k
  if (MCOperand_isImm(DispSpec)) {
931
203k
    DispVal = MCOperand_getImm(DispSpec);
932
203k
    if (MI->csh->detail_opt)
933
203k
      MI->flat_insn->detail->x86
934
203k
        .operands[MI->flat_insn->detail->x86.op_count]
935
203k
        .mem.disp = DispVal;
936
203k
    if (DispVal) {
937
59.8k
      if (MCOperand_getReg(IndexReg) ||
938
55.6k
          MCOperand_getReg(BaseReg)) {
939
55.6k
        printInt64(O, DispVal);
940
55.6k
      } else {
941
        // only immediate as address of memory
942
4.23k
        if (DispVal < 0) {
943
1.67k
          SStream_concat(O, "0x%" PRIx64,
944
1.67k
                   x86_get_address_mask(
945
1.67k
                     MI->csh->mode) &
946
1.67k
                     DispVal);
947
2.55k
        } else {
948
2.55k
          if (DispVal > HEX_THRESHOLD)
949
2.16k
            SStream_concat(O, "0x%" PRIx64,
950
2.16k
                     DispVal);
951
394
          else
952
394
            SStream_concat(O, "%" PRIu64,
953
394
                     DispVal);
954
2.55k
        }
955
4.23k
      }
956
59.8k
    }
957
203k
  }
958
959
203k
  if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
960
199k
    SStream_concat0(O, "(");
961
962
199k
    if (MCOperand_getReg(BaseReg))
963
198k
      _printOperand(MI, Op + X86_AddrBaseReg, O);
964
965
199k
    if (MCOperand_getReg(IndexReg) &&
966
71.0k
        MCOperand_getReg(IndexReg) != X86_EIZ) {
967
70.2k
      SStream_concat0(O, ", ");
968
70.2k
      _printOperand(MI, Op + X86_AddrIndexReg, O);
969
70.2k
      ScaleVal = MCOperand_getImm(
970
70.2k
        MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
971
70.2k
      if (MI->csh->detail_opt)
972
70.2k
        MI->flat_insn->detail->x86
973
70.2k
          .operands[MI->flat_insn->detail->x86
974
70.2k
                .op_count]
975
70.2k
          .mem.scale = (int)ScaleVal;
976
70.2k
      if (ScaleVal != 1) {
977
7.63k
        SStream_concat(O, ", %" PRIu64, ScaleVal);
978
7.63k
      }
979
70.2k
    }
980
981
199k
    SStream_concat0(O, ")");
982
199k
  } else {
983
4.75k
    if (!DispVal)
984
516
      SStream_concat0(O, "0");
985
4.75k
  }
986
987
203k
  if (MI->csh->detail_opt)
988
203k
    MI->flat_insn->detail->x86.op_count++;
989
203k
}
990
991
static void printanymem(MCInst *MI, unsigned OpNo, SStream *O)
992
6.40k
{
993
6.40k
  switch (MI->Opcode) {
994
418
  default:
995
418
    break;
996
1.01k
  case X86_LEA16r:
997
1.01k
    MI->x86opsize = 2;
998
1.01k
    break;
999
423
  case X86_LEA32r:
1000
905
  case X86_LEA64_32r:
1001
905
    MI->x86opsize = 4;
1002
905
    break;
1003
519
  case X86_LEA64r:
1004
519
    MI->x86opsize = 8;
1005
519
    break;
1006
0
#ifndef CAPSTONE_X86_REDUCE
1007
458
  case X86_BNDCL32rm:
1008
857
  case X86_BNDCN32rm:
1009
1.26k
  case X86_BNDCU32rm:
1010
1.83k
  case X86_BNDSTXmr:
1011
2.35k
  case X86_BNDLDXrm:
1012
2.75k
  case X86_BNDCL64rm:
1013
3.15k
  case X86_BNDCN64rm:
1014
3.54k
  case X86_BNDCU64rm:
1015
3.54k
    MI->x86opsize = 16;
1016
3.54k
    break;
1017
6.40k
#endif
1018
6.40k
  }
1019
1020
6.40k
  printMemReference(MI, OpNo, O);
1021
6.40k
}
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
728k
{
1036
728k
  SStream_concat(OS, "%%%s", getRegisterName(RegNo));
1037
728k
}
1038
1039
static void att_printInst(MCInst *MI, SStream *OS, void *info)
1040
283k
{
1041
283k
  x86_reg reg, reg2;
1042
283k
  enum cs_ac_type access1, access2;
1043
283k
  int i;
1044
1045
  // perhaps this instruction does not need printer
1046
283k
  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
283k
  if ((x86_has_feature(MI->csh->mode, CS_MODE_64)) &&
1058
104k
      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
283k
  X86_lockrep(MI, OS);
1066
283k
  printInstruction(MI, OS);
1067
1068
283k
  if (MI->has_imm) {
1069
    // if op_count > 1, then this operand's size is taken from the destination op
1070
47.6k
    if (MI->flat_insn->detail->x86.op_count > 1) {
1071
24.8k
      if (MI->flat_insn->id != X86_INS_LCALL &&
1072
24.5k
          MI->flat_insn->id != X86_INS_LJMP &&
1073
24.2k
          MI->flat_insn->id != X86_INS_JMP) {
1074
24.2k
        for (i = 0;
1075
73.7k
             i < MI->flat_insn->detail->x86.op_count;
1076
49.4k
             i++) {
1077
49.4k
          if (MI->flat_insn->detail->x86
1078
49.4k
                .operands[i]
1079
49.4k
                .type == X86_OP_IMM)
1080
24.7k
            MI->flat_insn->detail->x86
1081
24.7k
              .operands[i]
1082
24.7k
              .size =
1083
24.7k
              MI->flat_insn->detail
1084
24.7k
                ->x86
1085
24.7k
                .operands
1086
24.7k
                  [MI->flat_insn
1087
24.7k
                     ->detail
1088
24.7k
                     ->x86
1089
24.7k
                     .op_count -
1090
24.7k
                   1]
1091
24.7k
                .size;
1092
49.4k
        }
1093
24.2k
      }
1094
24.8k
    } 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
17.8k
      MI->flat_insn->detail->x86.operands[0].size =
1099
17.8k
        MI->imm_size;
1100
17.8k
    }
1101
47.6k
  }
1102
1103
283k
  if (MI->csh->detail_opt) {
1104
283k
    uint8_t access[CS_X86_MAXIMUM_OPERAND_SIZE] = { 0 };
1105
1106
    // some instructions need to supply immediate 1 in the first op
1107
283k
    switch (MCInst_getOpcode(MI)) {
1108
265k
    default:
1109
265k
      break;
1110
265k
    case X86_SHL8r1:
1111
443
    case X86_SHL16r1:
1112
771
    case X86_SHL32r1:
1113
1.06k
    case X86_SHL64r1:
1114
1.31k
    case X86_SAL8r1:
1115
1.60k
    case X86_SAL16r1:
1116
2.23k
    case X86_SAL32r1:
1117
2.52k
    case X86_SAL64r1:
1118
2.73k
    case X86_SHR8r1:
1119
2.94k
    case X86_SHR16r1:
1120
3.45k
    case X86_SHR32r1:
1121
3.73k
    case X86_SHR64r1:
1122
4.02k
    case X86_SAR8r1:
1123
4.39k
    case X86_SAR16r1:
1124
4.64k
    case X86_SAR32r1:
1125
5.04k
    case X86_SAR64r1:
1126
5.62k
    case X86_RCL8r1:
1127
5.93k
    case X86_RCL16r1:
1128
6.47k
    case X86_RCL32r1:
1129
6.76k
    case X86_RCL64r1:
1130
6.96k
    case X86_RCR8r1:
1131
7.24k
    case X86_RCR16r1:
1132
7.48k
    case X86_RCR32r1:
1133
7.75k
    case X86_RCR64r1:
1134
7.97k
    case X86_ROL8r1:
1135
8.24k
    case X86_ROL16r1:
1136
8.48k
    case X86_ROL32r1:
1137
8.81k
    case X86_ROL64r1:
1138
9.06k
    case X86_ROR8r1:
1139
9.29k
    case X86_ROR16r1:
1140
9.70k
    case X86_ROR32r1:
1141
10.0k
    case X86_ROR64r1:
1142
10.3k
    case X86_SHL8m1:
1143
10.5k
    case X86_SHL16m1:
1144
10.7k
    case X86_SHL32m1:
1145
10.9k
    case X86_SHL64m1:
1146
11.1k
    case X86_SAL8m1:
1147
11.4k
    case X86_SAL16m1:
1148
11.7k
    case X86_SAL32m1:
1149
11.9k
    case X86_SAL64m1:
1150
12.2k
    case X86_SHR8m1:
1151
12.5k
    case X86_SHR16m1:
1152
12.8k
    case X86_SHR32m1:
1153
13.0k
    case X86_SHR64m1:
1154
13.2k
    case X86_SAR8m1:
1155
13.4k
    case X86_SAR16m1:
1156
13.7k
    case X86_SAR32m1:
1157
13.9k
    case X86_SAR64m1:
1158
14.1k
    case X86_RCL8m1:
1159
14.4k
    case X86_RCL16m1:
1160
14.6k
    case X86_RCL32m1:
1161
14.8k
    case X86_RCL64m1:
1162
15.0k
    case X86_RCR8m1:
1163
15.3k
    case X86_RCR16m1:
1164
15.6k
    case X86_RCR32m1:
1165
15.8k
    case X86_RCR64m1:
1166
16.3k
    case X86_ROL8m1:
1167
16.6k
    case X86_ROL16m1:
1168
17.0k
    case X86_ROL32m1:
1169
17.3k
    case X86_ROL64m1:
1170
17.5k
    case X86_ROR8m1:
1171
17.7k
    case X86_ROR16m1:
1172
18.0k
    case X86_ROR32m1:
1173
18.3k
    case X86_ROR64m1:
1174
      // shift all the ops right to leave 1st slot for this new register op
1175
18.3k
      memmove(&(MI->flat_insn->detail->x86.operands[1]),
1176
18.3k
        &(MI->flat_insn->detail->x86.operands[0]),
1177
18.3k
        sizeof(MI->flat_insn->detail->x86.operands[0]) *
1178
18.3k
          (ARR_SIZE(MI->flat_insn->detail->x86
1179
18.3k
                .operands) -
1180
18.3k
           1));
1181
18.3k
      memset(&(MI->flat_insn->detail->x86.operands[0]), 0,
1182
18.3k
             sizeof(MI->flat_insn->detail->x86.operands[0]));
1183
18.3k
      MI->flat_insn->detail->x86.operands[0].type =
1184
18.3k
        X86_OP_IMM;
1185
18.3k
      MI->flat_insn->detail->x86.operands[0].imm = 1;
1186
18.3k
      MI->flat_insn->detail->x86.operands[0].size = 1;
1187
18.3k
      MI->flat_insn->detail->x86.op_count++;
1188
283k
    }
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
283k
    reg = X86_insn_reg_att_h(MI->csh, MCInst_getOpcode(MI),
1197
283k
           &access1);
1198
283k
    if (reg) {
1199
      // shift all the ops right to leave 1st slot for this new register op
1200
14.4k
      memmove(&(MI->flat_insn->detail->x86.operands[1]),
1201
14.4k
        &(MI->flat_insn->detail->x86.operands[0]),
1202
14.4k
        sizeof(MI->flat_insn->detail->x86.operands[0]) *
1203
14.4k
          (ARR_SIZE(MI->flat_insn->detail->x86
1204
14.4k
                .operands) -
1205
14.4k
           1));
1206
14.4k
      memset(&(MI->flat_insn->detail->x86.operands[0]), 0,
1207
14.4k
             sizeof(MI->flat_insn->detail->x86.operands[0]));
1208
14.4k
      MI->flat_insn->detail->x86.operands[0].type =
1209
14.4k
        X86_OP_REG;
1210
14.4k
      MI->flat_insn->detail->x86.operands[0].reg = reg;
1211
14.4k
      MI->flat_insn->detail->x86.operands[0].size =
1212
14.4k
        MI->csh->regsize_map[reg];
1213
14.4k
      MI->flat_insn->detail->x86.operands[0].access = access1;
1214
1215
14.4k
      MI->flat_insn->detail->x86.op_count++;
1216
269k
    } else {
1217
269k
      if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg,
1218
269k
                &access1, &reg2, &access2)) {
1219
4.22k
        MI->flat_insn->detail->x86.operands[0].type =
1220
4.22k
          X86_OP_REG;
1221
4.22k
        MI->flat_insn->detail->x86.operands[0].reg =
1222
4.22k
          reg;
1223
4.22k
        MI->flat_insn->detail->x86.operands[0].size =
1224
4.22k
          MI->csh->regsize_map[reg];
1225
4.22k
        MI->flat_insn->detail->x86.operands[0].access =
1226
4.22k
          access1;
1227
4.22k
        MI->flat_insn->detail->x86.operands[1].type =
1228
4.22k
          X86_OP_REG;
1229
4.22k
        MI->flat_insn->detail->x86.operands[1].reg =
1230
4.22k
          reg2;
1231
4.22k
        MI->flat_insn->detail->x86.operands[1].size =
1232
4.22k
          MI->csh->regsize_map[reg2];
1233
4.22k
        MI->flat_insn->detail->x86.operands[1].access =
1234
4.22k
          access2;
1235
4.22k
        MI->flat_insn->detail->x86.op_count = 2;
1236
4.22k
      }
1237
269k
    }
1238
1239
283k
#ifndef CAPSTONE_DIET
1240
283k
    get_op_access(MI->csh, MCInst_getOpcode(MI), access,
1241
283k
            &MI->flat_insn->detail->x86.eflags);
1242
804k
    for (i = 0; i < MI->flat_insn->detail->x86.op_count &&
1243
520k
          i < ARR_SIZE(access);
1244
520k
         i++) {
1245
520k
      MI->flat_insn->detail->x86.operands[i].access =
1246
520k
        access[i];
1247
520k
    }
1248
283k
    fixup_evex_opmask_access(MI);
1249
283k
#endif
1250
283k
  }
1251
283k
}
1252
1253
void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
1254
283k
{
1255
283k
  if (MI->csh->detail_opt & CS_OPT_DETAIL_INTEL_ORDER) {
1256
0
    X86_printInst_detail_syntax(MI, OS, info, att_printInst,
1257
0
              X86_Intel_printInst,
1258
0
              CS_OPT_SYNTAX_INTEL);
1259
0
    return;
1260
0
  }
1261
283k
  att_printInst(MI, OS, info);
1262
283k
}
1263
1264
#endif