Coverage Report

Created: 2026-06-15 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/M68K/M68KInstPrinter.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015-2016 */
3
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include "M68KInstPrinter.h"
9
10
#include "M68KDisassembler.h"
11
12
#include "../../Mapping.h"
13
#include "../../cs_priv.h"
14
#include "../../utils.h"
15
16
#include "../../MCInst.h"
17
#include "../../MCInstrDesc.h"
18
#include "../../MCRegisterInfo.h"
19
20
#ifndef CAPSTONE_DIET
21
static const char s_spacing[] = " ";
22
23
static const char *const s_reg_names[] = {
24
  "invalid",  "d0", "d1",  "d2",   "d3",   "d4",   "d5",   "d6",
25
  "d7",     "a0", "a1",  "a2",   "a3",   "a4",   "a5",   "a6",
26
  "a7",     "fp0",  "fp1",   "fp2",  "fp3",  "fp4",  "fp5",  "fp6",
27
  "fp7",      "pc", "sr",  "ccr",  "sfc",  "dfc",  "usp",  "vbr",
28
  "cacr",     "caar", "msp",   "isp",  "tc",   "itt0", "itt1", "dtt0",
29
  "dtt1",     "mmusr",  "urp",   "srp",
30
31
  "fpcr",     "fpsr", "fpiar",
32
33
  "tt0",      "tt1",  "crp",   "acc",  "acc0", "acc1", "acc2", "acc3",
34
  "accext01", "accext23", "macsr", "mask",
35
};
36
37
static const char *const s_instruction_names[] = {
38
  "invalid",   "abcd",   "add",      "adda",    "addi",
39
  "addq",      "addx",   "and",      "andi",    "asl",
40
  "asr",       "bhs",  "blo",      "bhi",   "bls",
41
  "bcc",       "bcs",  "bne",      "beq",   "bvc",
42
  "bvs",       "bpl",  "bmi",      "bge",   "blt",
43
  "bgt",       "ble",  "bra",      "bsr",   "bchg",
44
  "bclr",      "bset",   "btst",     "bitrev",    "byterev",
45
  "bfchg",     "bfclr",  "bfexts",   "bfextu",    "bfffo",
46
  "bfins",     "bfset",  "bftst",    "bkpt",    "callm",
47
  "cas",       "cas2",   "chk",      "chk2",    "clr",
48
  "cmp",       "cmpa",   "cmpi",     "cmpm",    "cmp2",
49
  "cinvl",     "cinvp",  "cinva",    "cpushl",    "cpushp",
50
  "cpusha",    "dbt",  "dbf",      "dbhi",    "dbls",
51
  "dbcc",      "dbcs",   "dbne",     "dbeq",    "dbvc",
52
  "dbvs",      "dbpl",   "dbmi",     "dbge",    "dblt",
53
  "dbgt",      "dble",   "dbra",     "divs",    "divsl",
54
  "divu",      "divul",  "eor",      "eori",    "exg",
55
  "ext",       "extb",   "ff1",      "fabs",    "fsabs",
56
  "fdabs",     "facos",  "fadd",     "fsadd",   "fdadd",
57
  "fasin",     "fatan",  "fatanh",   "fbf",   "fbeq",
58
  "fbogt",     "fboge",  "fbolt",    "fbole",   "fbogl",
59
  "fbor",      "fbun",   "fbueq",    "fbugt",   "fbuge",
60
  "fbult",     "fbule",  "fbne",     "fbt",   "fbsf",
61
  "fbseq",     "fbgt",   "fbge",     "fblt",    "fble",
62
  "fbgl",      "fbgle",  "fbngle",   "fbngl",   "fbnle",
63
  "fbnlt",     "fbnge",  "fbngt",    "fbsne",   "fbst",
64
  "fcmp",      "fcos",   "fcosh",    "fdbf",    "fdbeq",
65
  "fdbogt",    "fdboge",   "fdbolt",   "fdbole",    "fdbogl",
66
  "fdbor",     "fdbun",  "fdbueq",   "fdbugt",    "fdbuge",
67
  "fdbult",    "fdbule",   "fdbne",    "fdbt",    "fdbsf",
68
  "fdbseq",    "fdbgt",  "fdbge",    "fdblt",   "fdble",
69
  "fdbgl",     "fdbgle",   "fdbngle",  "fdbngl",    "fdbnle",
70
  "fdbnlt",    "fdbnge",   "fdbngt",   "fdbsne",    "fdbst",
71
  "fdiv",      "fsdiv",  "fddiv",    "fetox",   "fetoxm1",
72
  "fgetexp",   "fgetman",  "fint",     "fintrz",    "flog10",
73
  "flog2",     "flogn",  "flognp1",  "fmod",    "fmove",
74
  "fsmove",    "fdmove",   "fmovecr",  "fmovem",    "fmul",
75
  "fsmul",     "fdmul",  "fneg",     "fsneg",   "fdneg",
76
  "fnop",      "frem",   "frestore", "fsave",   "fscale",
77
  "fsgldiv",   "fsglmul",  "fsin",     "fsincos",   "fsinh",
78
  "fsqrt",     "fssqrt",   "fdsqrt",   "fsf",   "fseq",
79
  "fsogt",     "fsoge",  "fsolt",    "fsole",   "fsogl",
80
  "fsor",      "fsun",   "fsueq",    "fsugt",   "fsuge",
81
  "fsult",     "fsule",  "fsne",     "fst",   "fssf",
82
  "fsseq",     "fsgt",   "fsge",     "fslt",    "fsle",
83
  "fsgl",      "fsgle",  "fsngle",   "fsngl",   "fsnle",
84
  "fsnlt",     "fsnge",  "fsngt",    "fssne",   "fsst",
85
  "fsub",      "fssub",  "fdsub",    "ftan",    "ftanh",
86
  "ftentox",   "ftrapf",   "ftrapeq",  "ftrapogt",  "ftrapoge",
87
  "ftrapolt",  "ftrapole", "ftrapogl", "ftrapor",   "ftrapun",
88
  "ftrapueq",  "ftrapugt", "ftrapuge", "ftrapult",  "ftrapule",
89
  "ftrapne",   "ftrapt",   "ftrapsf",  "ftrapseq",  "ftrapgt",
90
  "ftrapge",   "ftraplt",  "ftraple",  "ftrapgl",   "ftrapgle",
91
  "ftrapngle", "ftrapngl", "ftrapnle", "ftrapnlt",  "ftrapnge",
92
  "ftrapngt",  "ftrapsne", "ftrapst",  "ftst",    "ftwotox",
93
  "halt",      "illegal",  "intouch",  "jmp",   "jsr",
94
  "lea",       "link",   "lpstop",   "lsl",   "lsr",
95
  "mac",       "move",   "movea",    "movec",   "movem",
96
  "movep",     "moveq",  "moves",    "move16",    "mov3q",
97
  "movclr",    "msac",   "muls",     "mulu",    "mvs",
98
  "mvz",       "nbcd",   "neg",      "negx",    "nop",
99
  "not",       "or",   "ori",      "pack",    "pea",
100
  "pflush",    "pflusha",  "pflushan", "pflushn",   "ploadr",
101
  "ploadw",    "plpar",  "plpaw",    "pmove",   "pmovefd",
102
  "ptestr",    "ptestw",   "pulse",    "rems",    "remu",
103
  "reset",     "rol",  "ror",      "roxl",    "roxr",
104
  "rtd",       "rte",  "rtm",      "rtr",   "rts",
105
  "sats",      "sbcd",   "st",       "sf",    "shi",
106
  "sls",       "scc",  "shs",      "scs",   "slo",
107
  "sne",       "seq",  "svc",      "svs",   "spl",
108
  "smi",       "sge",  "slt",      "sgt",   "sle",
109
  "stop",      "strldsr",  "sub",      "suba",    "subi",
110
  "subq",      "subx",   "swap",     "tas",   "trap",
111
  "trapv",     "trapt",  "trapf",    "traphi",    "trapls",
112
  "trapcc",    "traphs",   "trapcs",   "traplo",    "trapne",
113
  "trapeq",    "trapvc",   "trapvs",   "trappl",    "trapmi",
114
  "trapge",    "traplt",   "trapgt",   "traple",    "tst",
115
  "unlk",      "unpk",   "wddata",   "wdebug",    "bgnd",
116
  "tbls",      "tblu",   "tblsn",    "tblun",   "cp0bcbusy",
117
  "cp0ld",     "cp0nop",   "cp0st",    "cp1bcbusy", "cp1ld",
118
  "cp1nop",    "cp1st",  "tpf",
119
};
120
#endif
121
122
#ifndef CAPSTONE_DIET
123
static const char *getRegName(m68k_reg reg)
124
159k
{
125
159k
  return s_reg_names[(int)reg];
126
159k
}
127
128
static void printRegbits(SStream *O, bool *need_sep, uint32_t data,
129
       const char *prefix)
130
10.1k
{
131
10.1k
  unsigned int first;
132
10.1k
  int i;
133
134
77.4k
  for (i = 0; i < 8; ++i) {
135
67.3k
    if (!(data & (1 << i)))
136
56.8k
      continue;
137
138
10.5k
    first = i;
139
24.3k
    while (i < 7 && (data & (1 << (i + 1))))
140
13.8k
      i++;
141
142
10.5k
    if (*need_sep)
143
7.12k
      SStream_concat1(O, '/');
144
10.5k
    *need_sep = true;
145
146
10.5k
    SStream_concat(O, "%s%" PRIu32, prefix, first);
147
148
10.5k
    if ((unsigned int)i > first)
149
4.09k
      SStream_concat(O, "-%s%" PRIu32, prefix,
150
4.09k
               (unsigned int)i);
151
10.5k
  }
152
10.1k
}
153
154
static void registerBits(SStream *O, const cs_m68k_op *op)
155
9.29k
{
156
9.29k
  unsigned int data = op->register_bits;
157
9.29k
  bool need_sep = false;
158
159
9.29k
  if (!data) {
160
830
    SStream_concat(O, "%s", "#$0");
161
830
    return;
162
830
  }
163
164
8.46k
  printRegbits(O, &need_sep, data & 0xff, "d");
165
8.46k
  printRegbits(O, &need_sep, (data >> 8) & 0xff, "a");
166
8.46k
  printRegbits(O, &need_sep, (data >> 16) & 0xff, "fp");
167
8.46k
}
168
169
static void registerPair(SStream *O, const cs_m68k_op *op)
170
3.26k
{
171
3.26k
  SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
172
3.26k
           s_reg_names[op->reg_pair.reg_1]);
173
3.26k
}
174
175
static void printRegisterName(SStream *O, const cs_m68k_op *op)
176
111k
{
177
111k
  SStream_concat(O, "%s", getRegName(op->reg));
178
111k
  if (op->flags & M68K_OP_FLAG_REG_LOWER)
179
0
    SStream_concat0(O, "l");
180
111k
  else if (op->flags & M68K_OP_FLAG_REG_UPPER)
181
0
    SStream_concat0(O, "u");
182
111k
}
183
184
static void printScaleFactor(SStream *O, uint8_t scale, int threshold)
185
11.1k
{
186
11.1k
  if (scale > threshold)
187
6.10k
    SStream_concat(O, "%s*%s%" PRId8, s_spacing, s_spacing, scale);
188
11.1k
}
189
190
static void printIndexReg(SStream *O, const cs_m68k_op *op)
191
10.0k
{
192
10.0k
  SStream_concat(O, "%s.%c", getRegName(op->mem.index_reg),
193
10.0k
           op->mem.index_size ? 'l' : 'w');
194
10.0k
}
195
196
static void printBitfield(SStream *O, const cs_m68k_op *op)
197
250k
{
198
250k
  if (!op->mem.bitfield)
199
249k
    return;
200
740
  SStream_concat0(O, "{");
201
740
  if (M68K_BF_IS_REG(op->mem.offset))
202
420
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.offset));
203
320
  else
204
320
    SStream_concat(O, "%" PRId8, op->mem.offset);
205
740
  SStream_concat0(O, ":");
206
740
  if (M68K_BF_IS_REG(op->mem.width))
207
266
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.width));
208
474
  else
209
474
    SStream_concat(O, "%" PRId8, op->mem.width);
210
740
  SStream_concat0(O, "}");
211
740
}
212
213
static void printImmediate(SStream *O, const cs_m68k *inst,
214
         const cs_m68k_op *op)
215
37.9k
{
216
37.9k
  if (inst->op_size.type == M68K_SIZE_TYPE_FPU) {
217
#if defined(_KERNEL_MODE)
218
    SStream_concat(O, "#<float_point_unsupported>");
219
    return;
220
#else
221
231
    if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
222
27
      SStream_concat(O, "#%f", op->simm);
223
204
    else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
224
93
      SStream_concat(O, "#%f", op->dimm);
225
111
    else
226
111
      SStream_concat(O, "#<unsupported>");
227
231
    return;
228
231
#endif
229
231
  }
230
37.7k
  SStream_concat(O, "#$%" PRIx64, op->imm);
231
37.7k
}
232
233
static void printIndex8BitDisp(SStream *O, unsigned int pc,
234
             const cs_m68k_op *op)
235
6.62k
{
236
6.62k
  if (op->address_mode == M68K_AM_PCI_INDEX_8_BIT_DISP) {
237
576
    SStream_concat(O, "$%" PRIx32 "(pc,%s", pc + 2 + op->mem.disp,
238
576
             s_spacing);
239
6.04k
  } else {
240
6.04k
    SStream_concat(O, "%s$%" PRIx16 "(%s,%s",
241
6.04k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
242
6.04k
             getRegName(op->mem.base_reg), s_spacing);
243
6.04k
  }
244
6.62k
  printIndexReg(O, op);
245
6.62k
  printScaleFactor(O, op->mem.scale, 1);
246
6.62k
  SStream_concat0(O, ")");
247
6.62k
}
248
249
static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op)
250
167k
{
251
167k
  m68k_reg base_reg = op->type == M68K_OP_MEM ? op->mem.base_reg :
252
167k
                  op->reg;
253
254
167k
  switch (op->address_mode) {
255
86.3k
  case M68K_AM_REG_DIRECT_DATA:
256
86.3k
    printRegisterName(O, op);
257
86.3k
    break;
258
10.9k
  case M68K_AM_REG_DIRECT_ADDR:
259
10.9k
    printRegisterName(O, op);
260
10.9k
    break;
261
16.9k
  case M68K_AM_REGI_ADDR:
262
16.9k
    SStream_concat(O, "(a%" PRId32 ")", (base_reg - M68K_REG_A0));
263
16.9k
    break;
264
15.3k
  case M68K_AM_REGI_ADDR_POST_INC:
265
15.3k
    SStream_concat(O, "(a%" PRId32 ")+", (base_reg - M68K_REG_A0));
266
15.3k
    break;
267
26.0k
  case M68K_AM_REGI_ADDR_PRE_DEC:
268
26.0k
    SStream_concat(O, "-(a%" PRId32 ")", (base_reg - M68K_REG_A0));
269
26.0k
    break;
270
10.9k
  case M68K_AM_REGI_ADDR_DISP:
271
10.9k
    SStream_concat(O, "%s$%" PRIx16 "(a%" PRId32 ")",
272
10.9k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
273
10.9k
             (base_reg - M68K_REG_A0));
274
10.9k
    break;
275
1.14k
  case M68K_AM_PCI_DISP:
276
1.14k
    SStream_concat(O, "$%" PRIx32 "(pc)", pc + 2 + op->mem.disp);
277
1.14k
    break;
278
0
  default:
279
0
    break;
280
167k
  }
281
167k
}
282
283
static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op)
284
2.13k
{
285
2.13k
  int is_pc = (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP);
286
287
2.13k
  if (is_pc) {
288
137
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
289
1.99k
  } else if (op->mem.in_disp != 0) {
290
1.15k
    SStream_concat(O, "%s$%" PRIx32,
291
1.15k
             op->mem.in_disp >= 0 ? "" : "-",
292
1.15k
             abs(op->mem.in_disp));
293
1.15k
  }
294
295
2.13k
  SStream_concat0(O, "(");
296
297
2.13k
  if (is_pc) {
298
137
    SStream_concat0(O, "pc");
299
1.99k
  } else if (op->mem.base_reg != M68K_REG_INVALID) {
300
1.47k
    SStream_concat(O, "a%" PRId32, op->mem.base_reg - M68K_REG_A0);
301
1.47k
  }
302
303
2.13k
  if ((is_pc || op->mem.base_reg != M68K_REG_INVALID) &&
304
1.61k
      op->mem.index_reg != M68K_REG_INVALID)
305
1.01k
    SStream_concat(O, ",%s", s_spacing);
306
307
2.13k
  if (op->mem.index_reg != M68K_REG_INVALID) {
308
1.09k
    printIndexReg(O, op);
309
1.09k
    printScaleFactor(O, op->mem.scale, 0);
310
1.09k
  }
311
312
2.13k
  SStream_concat0(O, ")");
313
2.13k
}
314
315
static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op)
316
3.39k
{
317
3.39k
  int is_pc = (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
318
3.26k
         op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
319
3.39k
  int is_post = (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
320
2.03k
           op->address_mode == M68K_AM_PC_MEMI_POST_INDEX);
321
3.39k
  int is_pre = (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
322
1.61k
          op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
323
324
3.39k
  SStream_concat0(O, "([");
325
326
3.39k
  if (is_pc) {
327
252
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
328
3.14k
  } else if (op->mem.in_disp != 0) {
329
2.01k
    SStream_concat(O, "%s$%" PRIx32,
330
2.01k
             op->mem.in_disp >= 0 ? "" : "-",
331
2.01k
             abs(op->mem.in_disp));
332
2.01k
  }
333
334
3.39k
  if (op->mem.base_reg != M68K_REG_INVALID) {
335
2.15k
    if (op->mem.in_disp != 0)
336
1.39k
      SStream_concat(O, ",%s%s", s_spacing,
337
1.39k
               getRegName(op->mem.base_reg));
338
758
    else
339
758
      SStream_concat(O, "%s", getRegName(op->mem.base_reg));
340
2.15k
  }
341
342
3.39k
  if (is_post)
343
1.49k
    SStream_concat0(O, "]");
344
345
3.39k
  if (op->mem.index_reg != M68K_REG_INVALID) {
346
2.29k
    SStream_concat(O, ",%s", s_spacing);
347
2.29k
    printIndexReg(O, op);
348
2.29k
  }
349
350
3.39k
  printScaleFactor(O, op->mem.scale, 0);
351
352
3.39k
  if (is_pre)
353
1.90k
    SStream_concat0(O, "]");
354
355
3.39k
  if (op->mem.out_disp != 0) {
356
1.67k
    SStream_concat(O, ",%s%s$%" PRIx32, s_spacing,
357
1.67k
             op->mem.out_disp >= 0 ? "" : "-",
358
1.67k
             abs(op->mem.out_disp));
359
1.67k
  }
360
361
3.39k
  SStream_concat0(O, ")");
362
3.39k
}
363
364
static void printAddressingMode(SStream *O, unsigned int pc,
365
        const cs_m68k *inst, const cs_m68k_op *op)
366
250k
{
367
250k
  switch (op->address_mode) {
368
18.4k
  case M68K_AM_NONE:
369
18.4k
    switch (op->type) {
370
3.43k
    case M68K_OP_REG_BITS:
371
3.43k
      registerBits(O, op);
372
3.43k
      break;
373
700
    case M68K_OP_REG_PAIR:
374
700
      registerPair(O, op);
375
700
      break;
376
14.2k
    case M68K_OP_REG:
377
14.2k
      printRegisterName(O, op);
378
14.2k
      break;
379
0
    case M68K_OP_SHIFT:
380
0
      if (op->flags & M68K_OP_FLAG_SHIFT_LEFT)
381
0
        SStream_concat0(O, "<<");
382
0
      else if (op->flags & M68K_OP_FLAG_SHIFT_RIGHT)
383
0
        SStream_concat0(O, ">>");
384
0
      break;
385
101
    default:
386
101
      break;
387
18.4k
    }
388
18.4k
    break;
389
390
86.3k
  case M68K_AM_REG_DIRECT_DATA:
391
97.2k
  case M68K_AM_REG_DIRECT_ADDR:
392
114k
  case M68K_AM_REGI_ADDR:
393
129k
  case M68K_AM_REGI_ADDR_POST_INC:
394
155k
  case M68K_AM_REGI_ADDR_PRE_DEC:
395
166k
  case M68K_AM_REGI_ADDR_DISP:
396
167k
  case M68K_AM_PCI_DISP:
397
167k
    printRegAddrMode(O, pc, op);
398
167k
    break;
399
2.50k
  case M68K_AM_ABSOLUTE_DATA_SHORT:
400
2.50k
    SStream_concat(O, "$%" PRIx32 ".w", (uint32_t)op->mem.address);
401
2.50k
    break;
402
1.30k
  case M68K_AM_ABSOLUTE_DATA_LONG:
403
1.30k
    SStream_concat(O, "$%" PRIx64 ".l", (uint64_t)op->mem.address);
404
1.30k
    break;
405
37.9k
  case M68K_AM_IMMEDIATE:
406
37.9k
    printImmediate(O, inst, op);
407
37.9k
    break;
408
576
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
409
6.62k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
410
6.62k
    printIndex8BitDisp(O, pc, op);
411
6.62k
    break;
412
137
  case M68K_AM_PCI_INDEX_BASE_DISP:
413
2.13k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
414
2.13k
    printBaseDisp(O, pc, op);
415
2.13k
    break;
416
130
  case M68K_AM_PC_MEMI_POST_INDEX:
417
252
  case M68K_AM_PC_MEMI_PRE_INDEX:
418
2.03k
  case M68K_AM_MEMI_PRE_INDEX:
419
3.39k
  case M68K_AM_MEMI_POST_INDEX:
420
3.39k
    printMemIndirect(O, pc, op);
421
3.39k
    break;
422
10.4k
  case M68K_AM_BRANCH_DISPLACEMENT:
423
10.4k
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->br_disp.disp);
424
10.4k
  default:
425
10.4k
    break;
426
250k
  }
427
428
250k
  printBitfield(O, op);
429
250k
  if (op->flags & M68K_OP_FLAG_MEM_UPDATE)
430
0
    SStream_concat0(O, "&");
431
250k
}
432
433
static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext)
434
217
{
435
217
  printAddressingMode(O, pc, ext, &ext->operands[0]);
436
217
  SStream_concat0(O, ",");
437
217
  printAddressingMode(O, pc, ext, &ext->operands[1]);
438
217
  SStream_concat0(O, ",");
439
440
217
  SStream_concat(O, "(%s):(%s)",
441
217
           s_reg_names[ext->operands[2].reg_pair.reg_0],
442
217
           s_reg_names[ext->operands[2].reg_pair.reg_1]);
443
217
}
444
445
static void printCacheOp(SStream *O, unsigned int pc, const cs_m68k *ext)
446
1.03k
{
447
1.03k
  static const char *const cache_names[] = { "nc", "dc", "ic", "bc" };
448
1.03k
  unsigned int sel = (unsigned int)ext->operands[0].imm;
449
1.03k
  int i;
450
451
1.03k
  if (sel < ARR_SIZE(cache_names))
452
1.03k
    SStream_concat0(O, cache_names[sel]);
453
0
  else
454
0
    SStream_concat(O, "#$%" PRIx64, ext->operands[0].imm);
455
456
1.95k
  for (i = 1; i < ext->op_count; ++i) {
457
921
    SStream_concat(O, ",%s", s_spacing);
458
921
    printAddressingMode(O, pc, ext, &ext->operands[i]);
459
921
  }
460
1.03k
}
461
462
#endif
463
464
static void printOpSize(SStream *O, const cs_m68k *ext)
465
138k
{
466
138k
  switch (ext->op_size.type) {
467
0
  case M68K_SIZE_TYPE_INVALID:
468
0
    break;
469
137k
  case M68K_SIZE_TYPE_CPU:
470
137k
    switch (ext->op_size.cpu_size) {
471
46.0k
    case M68K_CPU_SIZE_BYTE:
472
46.0k
      SStream_concat0(O, ".b");
473
46.0k
      break;
474
38.1k
    case M68K_CPU_SIZE_WORD:
475
38.1k
      SStream_concat0(O, ".w");
476
38.1k
      break;
477
34.6k
    case M68K_CPU_SIZE_LONG:
478
34.6k
      SStream_concat0(O, ".l");
479
34.6k
      break;
480
18.8k
    case M68K_CPU_SIZE_NONE:
481
18.8k
      break;
482
137k
    }
483
137k
    break;
484
137k
  case M68K_SIZE_TYPE_FPU:
485
887
    switch (ext->op_size.fpu_size) {
486
104
    case M68K_FPU_SIZE_SINGLE:
487
104
      SStream_concat0(O, ".s");
488
104
      break;
489
189
    case M68K_FPU_SIZE_DOUBLE:
490
189
      SStream_concat0(O, ".d");
491
189
      break;
492
594
    case M68K_FPU_SIZE_EXTENDED:
493
594
      SStream_concat0(O, ".x");
494
594
      break;
495
0
    case M68K_FPU_SIZE_NONE:
496
0
      break;
497
887
    }
498
887
    break;
499
138k
  }
500
138k
}
501
502
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
503
171k
{
504
171k
#ifndef CAPSTONE_DIET
505
171k
  m68k_info *info = (m68k_info *)PrinterInfo;
506
171k
  cs_m68k *ext = &info->extension;
507
171k
  cs_detail *detail = NULL;
508
171k
  int i = 0;
509
510
171k
  if (detail_is_set(MI)) {
511
171k
    detail = get_detail(MI);
512
171k
    int regs_read_count = MIN((int)ARR_SIZE(detail->regs_read),
513
171k
            info->regs_read_count);
514
171k
    int regs_write_count = MIN((int)ARR_SIZE(detail->regs_write),
515
171k
             info->regs_write_count);
516
171k
    int groups_count =
517
171k
      MIN((int)ARR_SIZE(detail->groups), info->groups_count);
518
519
171k
    memcpy(&detail->m68k, ext, sizeof(cs_m68k));
520
171k
    memcpy(&detail->regs_read, &info->regs_read,
521
171k
           regs_read_count * sizeof(info->regs_read[0]));
522
171k
    detail->regs_read_count = regs_read_count;
523
524
171k
    memcpy(&detail->regs_write, &info->regs_write,
525
171k
           regs_write_count * sizeof(info->regs_write[0]));
526
171k
    detail->regs_write_count = regs_write_count;
527
528
171k
    memcpy(&detail->groups, &info->groups, groups_count);
529
171k
    detail->groups_count = groups_count;
530
171k
  }
531
532
171k
  if (MI->Opcode == M68K_INS_INVALID) {
533
33.5k
    if (ext->op_count)
534
33.5k
      SStream_concat(O, "dc.w $%" PRIx32,
535
33.5k
               (uint32_t)ext->operands[0].imm);
536
0
    else
537
0
      SStream_concat(O, "dc.w $<unknown>");
538
33.5k
    return;
539
33.5k
  }
540
541
138k
  SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
542
138k
  printOpSize(O, ext);
543
138k
  SStream_concat0(O, " ");
544
545
138k
  if (MI->Opcode == M68K_INS_CAS2) {
546
217
    printCAS2(O, info->pc, ext);
547
217
    return;
548
217
  }
549
550
138k
  if (MI->Opcode >= M68K_INS_CINVL && MI->Opcode <= M68K_INS_CPUSHA) {
551
1.03k
    printCacheOp(O, info->pc, ext);
552
1.03k
    return;
553
1.03k
  }
554
555
386k
  for (i = 0; i < ext->op_count; ++i) {
556
249k
    printAddressingMode(O, info->pc, ext, &ext->operands[i]);
557
249k
    if ((i + 1) != ext->op_count)
558
113k
      SStream_concat(O, ",%s", s_spacing);
559
249k
  }
560
137k
#endif
561
137k
}
562
563
const char *M68K_reg_name(csh handle, unsigned int reg)
564
596k
{
565
#ifdef CAPSTONE_DIET
566
  return NULL;
567
#else
568
596k
  if (reg >= ARR_SIZE(s_reg_names)) {
569
0
    return NULL;
570
0
  }
571
596k
  return s_reg_names[(int)reg];
572
596k
#endif
573
596k
}
574
575
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
576
474k
{
577
474k
  insn->id = id; // These id's matches for 68k
578
474k
}
579
580
const char *M68K_insn_name(csh handle, unsigned int id)
581
474k
{
582
#ifdef CAPSTONE_DIET
583
  return NULL;
584
#else
585
474k
  if (id > ARR_SIZE(s_instruction_names)) {
586
0
    return NULL;
587
0
  }
588
474k
  return s_instruction_names[id];
589
474k
#endif
590
474k
}
591
592
#ifndef CAPSTONE_DIET
593
static const name_map group_name_maps[] = {
594
  { M68K_GRP_INVALID, NULL },
595
  { M68K_GRP_JUMP, "jump" },
596
  { M68K_GRP_RET, "ret" },
597
  { M68K_GRP_IRET, "iret" },
598
  { M68K_GRP_BRANCH_RELATIVE, "branch_relative" },
599
};
600
#endif
601
602
const char *M68K_group_name(csh handle, unsigned int id)
603
83.4k
{
604
83.4k
#ifndef CAPSTONE_DIET
605
83.4k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
606
#else
607
  return NULL;
608
#endif
609
83.4k
}
610
611
#ifndef CAPSTONE_DIET
612
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
613
         uint8_t *regs_read_count, cs_regs regs_write,
614
         uint8_t *regs_write_count)
615
0
{
616
0
  uint8_t read_count, write_count;
617
618
0
  read_count = insn->detail->regs_read_count;
619
0
  write_count = insn->detail->regs_write_count;
620
621
  // implicit registers
622
0
  memcpy(regs_read, insn->detail->regs_read,
623
0
         read_count * sizeof(insn->detail->regs_read[0]));
624
0
  memcpy(regs_write, insn->detail->regs_write,
625
0
         write_count * sizeof(insn->detail->regs_write[0]));
626
627
0
  *regs_read_count = read_count;
628
0
  *regs_write_count = write_count;
629
0
}
630
#endif