Coverage Report

Created: 2026-07-16 06:55

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