Coverage Report

Created: 2026-06-06 06:15

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
153k
{
125
153k
  return s_reg_names[(int)reg];
126
153k
}
127
128
static void printRegbits(SStream *O, bool *need_sep, uint32_t data,
129
       const char *prefix)
130
9.76k
{
131
9.76k
  unsigned int first;
132
9.76k
  int i;
133
134
73.9k
  for (i = 0; i < 8; ++i) {
135
64.2k
    if (!(data & (1 << i)))
136
54.2k
      continue;
137
138
9.96k
    first = i;
139
23.8k
    while (i < 7 && (data & (1 << (i + 1))))
140
13.8k
      i++;
141
142
9.96k
    if (*need_sep)
143
6.70k
      SStream_concat1(O, '/');
144
9.96k
    *need_sep = true;
145
146
9.96k
    SStream_concat(O, "%s%" PRIu32, prefix, first);
147
148
9.96k
    if ((unsigned int)i > first)
149
3.96k
      SStream_concat(O, "-%s%" PRIu32, prefix,
150
3.96k
               (unsigned int)i);
151
9.96k
  }
152
9.76k
}
153
154
static void registerBits(SStream *O, const cs_m68k_op *op)
155
9.16k
{
156
9.16k
  unsigned int data = op->register_bits;
157
9.16k
  bool need_sep = false;
158
159
9.16k
  if (!data) {
160
832
    SStream_concat(O, "%s", "#$0");
161
832
    return;
162
832
  }
163
164
8.33k
  printRegbits(O, &need_sep, data & 0xff, "d");
165
8.33k
  printRegbits(O, &need_sep, (data >> 8) & 0xff, "a");
166
8.33k
  printRegbits(O, &need_sep, (data >> 16) & 0xff, "fp");
167
8.33k
}
168
169
static void registerPair(SStream *O, const cs_m68k_op *op)
170
3.08k
{
171
3.08k
  SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
172
3.08k
           s_reg_names[op->reg_pair.reg_1]);
173
3.08k
}
174
175
static void printRegisterName(SStream *O, const cs_m68k_op *op)
176
105k
{
177
105k
  SStream_concat(O, "%s", getRegName(op->reg));
178
105k
  if (op->flags & M68K_OP_FLAG_REG_LOWER)
179
0
    SStream_concat0(O, "l");
180
105k
  else if (op->flags & M68K_OP_FLAG_REG_UPPER)
181
0
    SStream_concat0(O, "u");
182
105k
}
183
184
static void printScaleFactor(SStream *O, uint8_t scale, int threshold)
185
10.9k
{
186
10.9k
  if (scale > threshold)
187
6.30k
    SStream_concat(O, "%s*%s%" PRId8, s_spacing, s_spacing, scale);
188
10.9k
}
189
190
static void printIndexReg(SStream *O, const cs_m68k_op *op)
191
9.98k
{
192
9.98k
  SStream_concat(O, "%s.%c", getRegName(op->mem.index_reg),
193
9.98k
           op->mem.index_size ? 'l' : 'w');
194
9.98k
}
195
196
static void printBitfield(SStream *O, const cs_m68k_op *op)
197
233k
{
198
233k
  if (!op->mem.bitfield)
199
231k
    return;
200
1.00k
  SStream_concat0(O, "{");
201
1.00k
  if (M68K_BF_IS_REG(op->mem.offset))
202
723
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.offset));
203
284
  else
204
284
    SStream_concat(O, "%" PRId8, op->mem.offset);
205
1.00k
  SStream_concat0(O, ":");
206
1.00k
  if (M68K_BF_IS_REG(op->mem.width))
207
277
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.width));
208
730
  else
209
730
    SStream_concat(O, "%" PRId8, op->mem.width);
210
1.00k
  SStream_concat0(O, "}");
211
1.00k
}
212
213
static void printImmediate(SStream *O, const cs_m68k *inst,
214
         const cs_m68k_op *op)
215
34.5k
{
216
34.5k
  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
182
    if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
222
26
      SStream_concat(O, "#%f", op->simm);
223
156
    else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
224
51
      SStream_concat(O, "#%f", op->dimm);
225
105
    else
226
105
      SStream_concat(O, "#<unsupported>");
227
182
    return;
228
182
#endif
229
182
  }
230
34.3k
  SStream_concat(O, "#$%" PRIx64, op->imm);
231
34.3k
}
232
233
static void printIndex8BitDisp(SStream *O, unsigned int pc,
234
             const cs_m68k_op *op)
235
6.72k
{
236
6.72k
  if (op->address_mode == M68K_AM_PCI_INDEX_8_BIT_DISP) {
237
478
    SStream_concat(O, "$%" PRIx32 "(pc,%s", pc + 2 + op->mem.disp,
238
478
             s_spacing);
239
6.24k
  } else {
240
6.24k
    SStream_concat(O, "%s$%" PRIx16 "(%s,%s",
241
6.24k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
242
6.24k
             getRegName(op->mem.base_reg), s_spacing);
243
6.24k
  }
244
6.72k
  printIndexReg(O, op);
245
6.72k
  printScaleFactor(O, op->mem.scale, 1);
246
6.72k
  SStream_concat0(O, ")");
247
6.72k
}
248
249
static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op)
250
154k
{
251
154k
  m68k_reg base_reg = op->type == M68K_OP_MEM ? op->mem.base_reg :
252
154k
                  op->reg;
253
254
154k
  switch (op->address_mode) {
255
80.8k
  case M68K_AM_REG_DIRECT_DATA:
256
80.8k
    printRegisterName(O, op);
257
80.8k
    break;
258
10.4k
  case M68K_AM_REG_DIRECT_ADDR:
259
10.4k
    printRegisterName(O, op);
260
10.4k
    break;
261
15.3k
  case M68K_AM_REGI_ADDR:
262
15.3k
    SStream_concat(O, "(a%" PRId32 ")", (base_reg - M68K_REG_A0));
263
15.3k
    break;
264
13.7k
  case M68K_AM_REGI_ADDR_POST_INC:
265
13.7k
    SStream_concat(O, "(a%" PRId32 ")+", (base_reg - M68K_REG_A0));
266
13.7k
    break;
267
23.0k
  case M68K_AM_REGI_ADDR_PRE_DEC:
268
23.0k
    SStream_concat(O, "-(a%" PRId32 ")", (base_reg - M68K_REG_A0));
269
23.0k
    break;
270
10.2k
  case M68K_AM_REGI_ADDR_DISP:
271
10.2k
    SStream_concat(O, "%s$%" PRIx16 "(a%" PRId32 ")",
272
10.2k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
273
10.2k
             (base_reg - M68K_REG_A0));
274
10.2k
    break;
275
1.11k
  case M68K_AM_PCI_DISP:
276
1.11k
    SStream_concat(O, "$%" PRIx32 "(pc)", pc + 2 + op->mem.disp);
277
1.11k
    break;
278
0
  default:
279
0
    break;
280
154k
  }
281
154k
}
282
283
static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op)
284
1.94k
{
285
1.94k
  int is_pc = (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP);
286
287
1.94k
  if (is_pc) {
288
113
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
289
1.83k
  } else if (op->mem.in_disp != 0) {
290
1.02k
    SStream_concat(O, "%s$%" PRIx32,
291
1.02k
             op->mem.in_disp >= 0 ? "" : "-",
292
1.02k
             abs(op->mem.in_disp));
293
1.02k
  }
294
295
1.94k
  SStream_concat0(O, "(");
296
297
1.94k
  if (is_pc) {
298
113
    SStream_concat0(O, "pc");
299
1.83k
  } else if (op->mem.base_reg != M68K_REG_INVALID) {
300
1.36k
    SStream_concat(O, "a%" PRId32, op->mem.base_reg - M68K_REG_A0);
301
1.36k
  }
302
303
1.94k
  if ((is_pc || op->mem.base_reg != M68K_REG_INVALID) &&
304
1.47k
      op->mem.index_reg != M68K_REG_INVALID)
305
916
    SStream_concat(O, ",%s", s_spacing);
306
307
1.94k
  if (op->mem.index_reg != M68K_REG_INVALID) {
308
973
    printIndexReg(O, op);
309
973
    printScaleFactor(O, op->mem.scale, 0);
310
973
  }
311
312
1.94k
  SStream_concat0(O, ")");
313
1.94k
}
314
315
static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op)
316
3.23k
{
317
3.23k
  int is_pc = (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
318
3.06k
         op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
319
3.23k
  int is_post = (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
320
1.96k
           op->address_mode == M68K_AM_PC_MEMI_POST_INDEX);
321
3.23k
  int is_pre = (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
322
1.56k
          op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
323
324
3.23k
  SStream_concat0(O, "([");
325
326
3.23k
  if (is_pc) {
327
295
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
328
2.93k
  } else if (op->mem.in_disp != 0) {
329
1.96k
    SStream_concat(O, "%s$%" PRIx32,
330
1.96k
             op->mem.in_disp >= 0 ? "" : "-",
331
1.96k
             abs(op->mem.in_disp));
332
1.96k
  }
333
334
3.23k
  if (op->mem.base_reg != M68K_REG_INVALID) {
335
2.17k
    if (op->mem.in_disp != 0)
336
1.51k
      SStream_concat(O, ",%s%s", s_spacing,
337
1.51k
               getRegName(op->mem.base_reg));
338
669
    else
339
669
      SStream_concat(O, "%s", getRegName(op->mem.base_reg));
340
2.17k
  }
341
342
3.23k
  if (is_post)
343
1.43k
    SStream_concat0(O, "]");
344
345
3.23k
  if (op->mem.index_reg != M68K_REG_INVALID) {
346
2.28k
    SStream_concat(O, ",%s", s_spacing);
347
2.28k
    printIndexReg(O, op);
348
2.28k
  }
349
350
3.23k
  printScaleFactor(O, op->mem.scale, 0);
351
352
3.23k
  if (is_pre)
353
1.79k
    SStream_concat0(O, "]");
354
355
3.23k
  if (op->mem.out_disp != 0) {
356
1.61k
    SStream_concat(O, ",%s%s$%" PRIx32, s_spacing,
357
1.61k
             op->mem.out_disp >= 0 ? "" : "-",
358
1.61k
             abs(op->mem.out_disp));
359
1.61k
  }
360
361
3.23k
  SStream_concat0(O, ")");
362
3.23k
}
363
364
static void printAddressingMode(SStream *O, unsigned int pc,
365
        const cs_m68k *inst, const cs_m68k_op *op)
366
233k
{
367
233k
  switch (op->address_mode) {
368
17.7k
  case M68K_AM_NONE:
369
17.7k
    switch (op->type) {
370
3.30k
    case M68K_OP_REG_BITS:
371
3.30k
      registerBits(O, op);
372
3.30k
      break;
373
525
    case M68K_OP_REG_PAIR:
374
525
      registerPair(O, op);
375
525
      break;
376
13.8k
    case M68K_OP_REG:
377
13.8k
      printRegisterName(O, op);
378
13.8k
      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
71
    default:
386
71
      break;
387
17.7k
    }
388
17.7k
    break;
389
390
80.8k
  case M68K_AM_REG_DIRECT_DATA:
391
91.3k
  case M68K_AM_REG_DIRECT_ADDR:
392
106k
  case M68K_AM_REGI_ADDR:
393
120k
  case M68K_AM_REGI_ADDR_POST_INC:
394
143k
  case M68K_AM_REGI_ADDR_PRE_DEC:
395
153k
  case M68K_AM_REGI_ADDR_DISP:
396
154k
  case M68K_AM_PCI_DISP:
397
154k
    printRegAddrMode(O, pc, op);
398
154k
    break;
399
2.40k
  case M68K_AM_ABSOLUTE_DATA_SHORT:
400
2.40k
    SStream_concat(O, "$%" PRIx32 ".w", (uint32_t)op->mem.address);
401
2.40k
    break;
402
1.29k
  case M68K_AM_ABSOLUTE_DATA_LONG:
403
1.29k
    SStream_concat(O, "$%" PRIx64 ".l", (uint64_t)op->mem.address);
404
1.29k
    break;
405
34.5k
  case M68K_AM_IMMEDIATE:
406
34.5k
    printImmediate(O, inst, op);
407
34.5k
    break;
408
478
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
409
6.72k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
410
6.72k
    printIndex8BitDisp(O, pc, op);
411
6.72k
    break;
412
113
  case M68K_AM_PCI_INDEX_BASE_DISP:
413
1.94k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
414
1.94k
    printBaseDisp(O, pc, op);
415
1.94k
    break;
416
167
  case M68K_AM_PC_MEMI_POST_INDEX:
417
295
  case M68K_AM_PC_MEMI_PRE_INDEX:
418
1.96k
  case M68K_AM_MEMI_PRE_INDEX:
419
3.23k
  case M68K_AM_MEMI_POST_INDEX:
420
3.23k
    printMemIndirect(O, pc, op);
421
3.23k
    break;
422
10.1k
  case M68K_AM_BRANCH_DISPLACEMENT:
423
10.1k
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->br_disp.disp);
424
10.1k
  default:
425
10.1k
    break;
426
233k
  }
427
428
233k
  printBitfield(O, op);
429
233k
  if (op->flags & M68K_OP_FLAG_MEM_UPDATE)
430
0
    SStream_concat0(O, "&");
431
233k
}
432
433
static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext)
434
211
{
435
211
  printAddressingMode(O, pc, ext, &ext->operands[0]);
436
211
  SStream_concat0(O, ",");
437
211
  printAddressingMode(O, pc, ext, &ext->operands[1]);
438
211
  SStream_concat0(O, ",");
439
440
211
  SStream_concat(O, "(%s):(%s)",
441
211
           s_reg_names[ext->operands[2].reg_pair.reg_0],
442
211
           s_reg_names[ext->operands[2].reg_pair.reg_1]);
443
211
}
444
445
static void printCacheOp(SStream *O, unsigned int pc, const cs_m68k *ext)
446
881
{
447
881
  static const char *const cache_names[] = { "nc", "dc", "ic", "bc" };
448
881
  unsigned int sel = (unsigned int)ext->operands[0].imm;
449
881
  int i;
450
451
881
  if (sel < ARR_SIZE(cache_names))
452
881
    SStream_concat0(O, cache_names[sel]);
453
0
  else
454
0
    SStream_concat(O, "#$%" PRIx64, ext->operands[0].imm);
455
456
1.65k
  for (i = 1; i < ext->op_count; ++i) {
457
774
    SStream_concat(O, ",%s", s_spacing);
458
774
    printAddressingMode(O, pc, ext, &ext->operands[i]);
459
774
  }
460
881
}
461
462
#endif
463
464
static void printOpSize(SStream *O, const cs_m68k *ext)
465
128k
{
466
128k
  switch (ext->op_size.type) {
467
0
  case M68K_SIZE_TYPE_INVALID:
468
0
    break;
469
127k
  case M68K_SIZE_TYPE_CPU:
470
127k
    switch (ext->op_size.cpu_size) {
471
42.6k
    case M68K_CPU_SIZE_BYTE:
472
42.6k
      SStream_concat0(O, ".b");
473
42.6k
      break;
474
35.9k
    case M68K_CPU_SIZE_WORD:
475
35.9k
      SStream_concat0(O, ".w");
476
35.9k
      break;
477
31.1k
    case M68K_CPU_SIZE_LONG:
478
31.1k
      SStream_concat0(O, ".l");
479
31.1k
      break;
480
18.1k
    case M68K_CPU_SIZE_NONE:
481
18.1k
      break;
482
127k
    }
483
127k
    break;
484
127k
  case M68K_SIZE_TYPE_FPU:
485
891
    switch (ext->op_size.fpu_size) {
486
65
    case M68K_FPU_SIZE_SINGLE:
487
65
      SStream_concat0(O, ".s");
488
65
      break;
489
145
    case M68K_FPU_SIZE_DOUBLE:
490
145
      SStream_concat0(O, ".d");
491
145
      break;
492
681
    case M68K_FPU_SIZE_EXTENDED:
493
681
      SStream_concat0(O, ".x");
494
681
      break;
495
0
    case M68K_FPU_SIZE_NONE:
496
0
      break;
497
891
    }
498
891
    break;
499
128k
  }
500
128k
}
501
502
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
503
158k
{
504
158k
#ifndef CAPSTONE_DIET
505
158k
  m68k_info *info = (m68k_info *)PrinterInfo;
506
158k
  cs_m68k *ext = &info->extension;
507
158k
  cs_detail *detail = NULL;
508
158k
  int i = 0;
509
510
158k
  if (detail_is_set(MI)) {
511
158k
    detail = get_detail(MI);
512
158k
    int regs_read_count = MIN((int)ARR_SIZE(detail->regs_read),
513
158k
            info->regs_read_count);
514
158k
    int regs_write_count = MIN((int)ARR_SIZE(detail->regs_write),
515
158k
             info->regs_write_count);
516
158k
    int groups_count =
517
158k
      MIN((int)ARR_SIZE(detail->groups), info->groups_count);
518
519
158k
    memcpy(&detail->m68k, ext, sizeof(cs_m68k));
520
158k
    memcpy(&detail->regs_read, &info->regs_read,
521
158k
           regs_read_count * sizeof(info->regs_read[0]));
522
158k
    detail->regs_read_count = regs_read_count;
523
524
158k
    memcpy(&detail->regs_write, &info->regs_write,
525
158k
           regs_write_count * sizeof(info->regs_write[0]));
526
158k
    detail->regs_write_count = regs_write_count;
527
528
158k
    memcpy(&detail->groups, &info->groups, groups_count);
529
158k
    detail->groups_count = groups_count;
530
158k
  }
531
532
158k
  if (MI->Opcode == M68K_INS_INVALID) {
533
29.4k
    if (ext->op_count)
534
29.4k
      SStream_concat(O, "dc.w $%" PRIx32,
535
29.4k
               (uint32_t)ext->operands[0].imm);
536
0
    else
537
0
      SStream_concat(O, "dc.w $<unknown>");
538
29.4k
    return;
539
29.4k
  }
540
541
128k
  SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
542
128k
  printOpSize(O, ext);
543
128k
  SStream_concat0(O, " ");
544
545
128k
  if (MI->Opcode == M68K_INS_CAS2) {
546
211
    printCAS2(O, info->pc, ext);
547
211
    return;
548
211
  }
549
550
128k
  if (MI->Opcode >= M68K_INS_CINVL && MI->Opcode <= M68K_INS_CPUSHA) {
551
881
    printCacheOp(O, info->pc, ext);
552
881
    return;
553
881
  }
554
555
359k
  for (i = 0; i < ext->op_count; ++i) {
556
231k
    printAddressingMode(O, info->pc, ext, &ext->operands[i]);
557
231k
    if ((i + 1) != ext->op_count)
558
105k
      SStream_concat(O, ",%s", s_spacing);
559
231k
  }
560
127k
#endif
561
127k
}
562
563
const char *M68K_reg_name(csh handle, unsigned int reg)
564
583k
{
565
#ifdef CAPSTONE_DIET
566
  return NULL;
567
#else
568
583k
  if (reg >= ARR_SIZE(s_reg_names)) {
569
0
    return NULL;
570
0
  }
571
583k
  return s_reg_names[(int)reg];
572
583k
#endif
573
583k
}
574
575
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
576
460k
{
577
460k
  insn->id = id; // These id's matches for 68k
578
460k
}
579
580
const char *M68K_insn_name(csh handle, unsigned int id)
581
460k
{
582
#ifdef CAPSTONE_DIET
583
  return NULL;
584
#else
585
460k
  if (id > ARR_SIZE(s_instruction_names)) {
586
0
    return NULL;
587
0
  }
588
460k
  return s_instruction_names[id];
589
460k
#endif
590
460k
}
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
82.9k
{
604
82.9k
#ifndef CAPSTONE_DIET
605
82.9k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
606
#else
607
  return NULL;
608
#endif
609
82.9k
}
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