Coverage Report

Created: 2026-04-29 06:06

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",
34
};
35
36
static const char *const s_instruction_names[] = {
37
  "invalid",  "abcd", "add",      "adda", "addi",      "addq",
38
  "addx",     "and",  "andi",     "asl",  "asr",       "bhs",
39
  "blo",      "bhi",  "bls",      "bcc",  "bcs",       "bne",
40
  "beq",      "bvc",  "bvs",      "bpl",  "bmi",       "bge",
41
  "blt",      "bgt",  "ble",      "bra",  "bsr",       "bchg",
42
  "bclr",     "bset", "btst",     "bfchg",  "bfclr",     "bfexts",
43
  "bfextu",   "bfffo",  "bfins",    "bfset",  "bftst",     "bkpt",
44
  "callm",    "cas",  "cas2",     "chk",  "chk2",      "clr",
45
  "cmp",      "cmpa", "cmpi",     "cmpm", "cmp2",      "cinvl",
46
  "cinvp",    "cinva",  "cpushl",   "cpushp", "cpusha",    "dbt",
47
  "dbf",      "dbhi", "dbls",     "dbcc", "dbcs",      "dbne",
48
  "dbeq",     "dbvc", "dbvs",     "dbpl", "dbmi",      "dbge",
49
  "dblt",     "dbgt", "dble",     "dbra", "divs",      "divsl",
50
  "divu",     "divul",  "eor",      "eori", "exg",       "ext",
51
  "extb",     "fabs", "fsabs",    "fdabs",  "facos",     "fadd",
52
  "fsadd",    "fdadd",  "fasin",    "fatan",  "fatanh",    "fbf",
53
  "fbeq",     "fbogt",  "fboge",    "fbolt",  "fbole",     "fbogl",
54
  "fbor",     "fbun", "fbueq",    "fbugt",  "fbuge",     "fbult",
55
  "fbule",    "fbne", "fbt",      "fbsf", "fbseq",     "fbgt",
56
  "fbge",     "fblt", "fble",     "fbgl", "fbgle",     "fbngle",
57
  "fbngl",    "fbnle",  "fbnlt",    "fbnge",  "fbngt",     "fbsne",
58
  "fbst",     "fcmp", "fcos",     "fcosh",  "fdbf",      "fdbeq",
59
  "fdbogt",   "fdboge", "fdbolt",   "fdbole", "fdbogl",    "fdbor",
60
  "fdbun",    "fdbueq", "fdbugt",   "fdbuge", "fdbult",    "fdbule",
61
  "fdbne",    "fdbt", "fdbsf",    "fdbseq", "fdbgt",     "fdbge",
62
  "fdblt",    "fdble",  "fdbgl",    "fdbgle", "fdbngle",   "fdbngl",
63
  "fdbnle",   "fdbnlt", "fdbnge",   "fdbngt", "fdbsne",    "fdbst",
64
  "fdiv",     "fsdiv",  "fddiv",    "fetox",  "fetoxm1",   "fgetexp",
65
  "fgetman",  "fint", "fintrz",   "flog10", "flog2",     "flogn",
66
  "flognp1",  "fmod", "fmove",    "fsmove", "fdmove",    "fmovecr",
67
  "fmovem",   "fmul", "fsmul",    "fdmul",  "fneg",      "fsneg",
68
  "fdneg",    "fnop", "frem",     "frestore", "fsave",     "fscale",
69
  "fsgldiv",  "fsglmul",  "fsin",     "fsincos",  "fsinh",     "fsqrt",
70
  "fssqrt",   "fdsqrt", "fsf",      "fseq", "fsogt",     "fsoge",
71
  "fsolt",    "fsole",  "fsogl",    "fsor", "fsun",      "fsueq",
72
  "fsugt",    "fsuge",  "fsult",    "fsule",  "fsne",      "fst",
73
  "fssf",     "fsseq",  "fsgt",     "fsge", "fslt",      "fsle",
74
  "fsgl",     "fsgle",  "fsngle",   "fsngl",  "fsnle",     "fsnlt",
75
  "fsnge",    "fsngt",  "fssne",    "fsst", "fsub",      "fssub",
76
  "fdsub",    "ftan", "ftanh",    "ftentox",  "ftrapf",    "ftrapeq",
77
  "ftrapogt", "ftrapoge", "ftrapolt", "ftrapole", "ftrapogl",  "ftrapor",
78
  "ftrapun",  "ftrapueq", "ftrapugt", "ftrapuge", "ftrapult",  "ftrapule",
79
  "ftrapne",  "ftrapt", "ftrapsf",  "ftrapseq", "ftrapgt",   "ftrapge",
80
  "ftraplt",  "ftraple",  "ftrapgl",  "ftrapgle", "ftrapngle", "ftrapngl",
81
  "ftrapnle", "ftrapnlt", "ftrapnge", "ftrapngt", "ftrapsne",  "ftrapst",
82
  "ftst",     "ftwotox",  "halt",     "illegal",  "jmp",       "jsr",
83
  "lea",      "link", "lpstop",   "lsl",  "lsr",       "move",
84
  "movea",    "movec",  "movem",    "movep",  "moveq",     "moves",
85
  "move16",   "muls", "mulu",     "nbcd", "neg",       "negx",
86
  "nop",      "not",  "or",     "ori",  "pack",      "pea",
87
  "pflush",   "pflusha",  "pflushan", "pflushn",  "ploadr",    "ploadw",
88
  "plpar",    "plpaw",  "pmove",    "pmovefd",  "ptestr",    "ptestw",
89
  "pulse",    "rems", "remu",     "reset",  "rol",       "ror",
90
  "roxl",     "roxr", "rtd",      "rte",  "rtm",       "rtr",
91
  "rts",      "sbcd", "st",     "sf", "shi",       "sls",
92
  "scc",      "shs",  "scs",      "slo",  "sne",       "seq",
93
  "svc",      "svs",  "spl",      "smi",  "sge",       "slt",
94
  "sgt",      "sle",  "stop",     "sub",  "suba",      "subi",
95
  "subq",     "subx", "swap",     "tas",  "trap",      "trapv",
96
  "trapt",    "trapf",  "traphi",   "trapls", "trapcc",    "traphs",
97
  "trapcs",   "traplo", "trapne",   "trapeq", "trapvc",    "trapvs",
98
  "trappl",   "trapmi", "trapge",   "traplt", "trapgt",    "traple",
99
  "tst",      "unlk", "unpk",     "bgnd", "tbls",      "tblu",
100
  "tblsn",    "tblun",
101
};
102
#endif
103
104
#ifndef CAPSTONE_DIET
105
static const char *getRegName(m68k_reg reg)
106
48.0k
{
107
48.0k
  return s_reg_names[(int)reg];
108
48.0k
}
109
110
static void printRegbits(SStream *O, bool *need_sep, uint32_t data,
111
       const char *prefix)
112
8.43k
{
113
8.43k
  unsigned int first;
114
8.43k
  int i;
115
116
67.4k
  for (i = 0; i < 8; ++i) {
117
59.0k
    if (!(data & (1 << i)))
118
49.0k
      continue;
119
120
9.95k
    first = i;
121
18.3k
    while (i < 7 && (data & (1 << (i + 1))))
122
8.43k
      i++;
123
124
9.95k
    if (*need_sep)
125
7.14k
      SStream_concat1(O, '/');
126
9.95k
    *need_sep = true;
127
128
9.95k
    SStream_concat(O, "%s%" PRIu32, prefix, first);
129
130
9.95k
    if ((unsigned int)i > first)
131
3.86k
      SStream_concat(O, "-%s%" PRIu32, prefix,
132
3.86k
               (unsigned int)i);
133
9.95k
  }
134
8.43k
}
135
136
static void registerBits(SStream *O, const cs_m68k_op *op)
137
6.81k
{
138
6.81k
  unsigned int data = op->register_bits;
139
6.81k
  bool need_sep = false;
140
141
6.81k
  if (!data) {
142
626
    SStream_concat(O, "%s", "#$0");
143
626
    return;
144
626
  }
145
146
6.18k
  printRegbits(O, &need_sep, data & 0xff, "d");
147
6.18k
  printRegbits(O, &need_sep, (data >> 8) & 0xff, "a");
148
6.18k
  printRegbits(O, &need_sep, (data >> 16) & 0xff, "fp");
149
6.18k
}
150
151
static void registerPair(SStream *O, const cs_m68k_op *op)
152
2.14k
{
153
2.14k
  SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
154
2.14k
           s_reg_names[op->reg_pair.reg_1]);
155
2.14k
}
156
157
static void printScaleFactor(SStream *O, uint8_t scale, int threshold)
158
15.4k
{
159
15.4k
  if (scale > threshold)
160
9.32k
    SStream_concat(O, "%s*%s%" PRId8, s_spacing, s_spacing, scale);
161
15.4k
}
162
163
static void printIndexReg(SStream *O, const cs_m68k_op *op)
164
14.1k
{
165
14.1k
  SStream_concat(O, "%s.%c", getRegName(op->mem.index_reg),
166
14.1k
           op->mem.index_size ? 'l' : 'w');
167
14.1k
}
168
169
static void printBitfield(SStream *O, const cs_m68k_op *op)
170
387k
{
171
387k
  if (!op->mem.bitfield)
172
386k
    return;
173
1.17k
  SStream_concat0(O, "{");
174
1.17k
  if (M68K_BF_IS_REG(op->mem.offset))
175
738
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.offset));
176
435
  else
177
435
    SStream_concat(O, "%" PRId8, op->mem.offset);
178
1.17k
  SStream_concat0(O, ":");
179
1.17k
  if (M68K_BF_IS_REG(op->mem.width))
180
465
    SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.width));
181
708
  else
182
708
    SStream_concat(O, "%" PRId8, op->mem.width);
183
1.17k
  SStream_concat0(O, "}");
184
1.17k
}
185
186
static void printImmediate(SStream *O, const cs_m68k *inst,
187
         const cs_m68k_op *op)
188
58.7k
{
189
58.7k
  if (inst->op_size.type == M68K_SIZE_TYPE_FPU) {
190
#if defined(_KERNEL_MODE)
191
    SStream_concat(O, "#<float_point_unsupported>");
192
    return;
193
#else
194
0
    if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
195
0
      SStream_concat(O, "#%f", op->simm);
196
0
    else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
197
0
      SStream_concat(O, "#%f", op->dimm);
198
0
    else
199
0
      SStream_concat(O, "#<unsupported>");
200
0
    return;
201
0
#endif
202
0
  }
203
58.7k
  SStream_concat(O, "#$%" PRIx64, op->imm);
204
58.7k
}
205
206
static void printIndex8BitDisp(SStream *O, unsigned int pc,
207
             const cs_m68k_op *op)
208
8.85k
{
209
8.85k
  if (op->address_mode == M68K_AM_PCI_INDEX_8_BIT_DISP) {
210
1.21k
    SStream_concat(O, "$%" PRIx32 "(pc,%s", pc + 2 + op->mem.disp,
211
1.21k
             s_spacing);
212
7.64k
  } else {
213
7.64k
    SStream_concat(O, "%s$%" PRIx16 "(%s,%s",
214
7.64k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
215
7.64k
             getRegName(op->mem.base_reg), s_spacing);
216
7.64k
  }
217
8.85k
  printIndexReg(O, op);
218
8.85k
  printScaleFactor(O, op->mem.scale, 1);
219
8.85k
  SStream_concat0(O, ")");
220
8.85k
}
221
222
static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op)
223
272k
{
224
272k
  switch (op->address_mode) {
225
141k
  case M68K_AM_REG_DIRECT_DATA:
226
141k
    SStream_concat(O, "d%" PRId32, (op->reg - M68K_REG_D0));
227
141k
    break;
228
20.0k
  case M68K_AM_REG_DIRECT_ADDR:
229
20.0k
    SStream_concat(O, "a%" PRId32, (op->reg - M68K_REG_A0));
230
20.0k
    break;
231
21.3k
  case M68K_AM_REGI_ADDR:
232
21.3k
    SStream_concat(O, "(a%" PRId32 ")", (op->reg - M68K_REG_A0));
233
21.3k
    break;
234
22.0k
  case M68K_AM_REGI_ADDR_POST_INC:
235
22.0k
    SStream_concat(O, "(a%" PRId32 ")+", (op->reg - M68K_REG_A0));
236
22.0k
    break;
237
47.5k
  case M68K_AM_REGI_ADDR_PRE_DEC:
238
47.5k
    SStream_concat(O, "-(a%" PRId32 ")", (op->reg - M68K_REG_A0));
239
47.5k
    break;
240
17.7k
  case M68K_AM_REGI_ADDR_DISP:
241
17.7k
    SStream_concat(O, "%s$%" PRIx16 "(a%" PRId32 ")",
242
17.7k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
243
17.7k
             (op->mem.base_reg - M68K_REG_A0));
244
17.7k
    break;
245
1.74k
  case M68K_AM_PCI_DISP:
246
1.74k
    SStream_concat(O, "$%" PRIx32 "(pc)", pc + 2 + op->mem.disp);
247
1.74k
    break;
248
0
  default:
249
0
    break;
250
272k
  }
251
272k
}
252
253
static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op)
254
2.32k
{
255
2.32k
  int is_pc = (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP);
256
257
2.32k
  if (is_pc) {
258
280
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
259
2.04k
  } else if (op->mem.in_disp != 0) {
260
1.07k
    SStream_concat(O, "%s$%" PRIx32,
261
1.07k
             op->mem.in_disp >= 0 ? "" : "-",
262
1.07k
             abs(op->mem.in_disp));
263
1.07k
  }
264
265
2.32k
  SStream_concat0(O, "(");
266
267
2.32k
  if (is_pc) {
268
280
    SStream_concat0(O, "pc");
269
2.04k
  } else if (op->mem.base_reg != M68K_REG_INVALID) {
270
1.29k
    SStream_concat(O, "a%" PRId32, op->mem.base_reg - M68K_REG_A0);
271
1.29k
  }
272
273
2.32k
  if ((is_pc || op->mem.base_reg != M68K_REG_INVALID) &&
274
1.57k
      op->mem.index_reg != M68K_REG_INVALID)
275
1.23k
    SStream_concat(O, ",%s", s_spacing);
276
277
2.32k
  if (op->mem.index_reg != M68K_REG_INVALID) {
278
1.59k
    printIndexReg(O, op);
279
1.59k
    printScaleFactor(O, op->mem.scale, 0);
280
1.59k
  }
281
282
2.32k
  SStream_concat0(O, ")");
283
2.32k
}
284
285
static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op)
286
5.00k
{
287
5.00k
  int is_pc = (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
288
4.65k
         op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
289
5.00k
  int is_post = (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
290
2.96k
           op->address_mode == M68K_AM_PC_MEMI_POST_INDEX);
291
5.00k
  int is_pre = (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
292
2.73k
          op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
293
294
5.00k
  SStream_concat0(O, "([");
295
296
5.00k
  if (is_pc) {
297
693
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
298
4.31k
  } else if (op->mem.in_disp != 0) {
299
2.88k
    SStream_concat(O, "%s$%" PRIx32,
300
2.88k
             op->mem.in_disp >= 0 ? "" : "-",
301
2.88k
             abs(op->mem.in_disp));
302
2.88k
  }
303
304
5.00k
  if (op->mem.base_reg != M68K_REG_INVALID) {
305
2.87k
    if (op->mem.in_disp != 0)
306
1.80k
      SStream_concat(O, ",%s%s", s_spacing,
307
1.80k
               getRegName(op->mem.base_reg));
308
1.06k
    else
309
1.06k
      SStream_concat(O, "%s", getRegName(op->mem.base_reg));
310
2.87k
  }
311
312
5.00k
  if (is_post)
313
2.39k
    SStream_concat0(O, "]");
314
315
5.00k
  if (op->mem.index_reg != M68K_REG_INVALID) {
316
3.68k
    SStream_concat(O, ",%s", s_spacing);
317
3.68k
    printIndexReg(O, op);
318
3.68k
  }
319
320
5.00k
  printScaleFactor(O, op->mem.scale, 0);
321
322
5.00k
  if (is_pre)
323
2.61k
    SStream_concat0(O, "]");
324
325
5.00k
  if (op->mem.out_disp != 0) {
326
2.28k
    SStream_concat(O, ",%s%s$%" PRIx32, s_spacing,
327
2.28k
             op->mem.out_disp >= 0 ? "" : "-",
328
2.28k
             abs(op->mem.out_disp));
329
2.28k
  }
330
331
5.00k
  SStream_concat0(O, ")");
332
5.00k
}
333
334
static void printAddressingMode(SStream *O, unsigned int pc,
335
        const cs_m68k *inst, const cs_m68k_op *op)
336
387k
{
337
387k
  switch (op->address_mode) {
338
19.3k
  case M68K_AM_NONE:
339
19.3k
    switch (op->type) {
340
2.90k
    case M68K_OP_REG_BITS:
341
2.90k
      registerBits(O, op);
342
2.90k
      break;
343
556
    case M68K_OP_REG_PAIR:
344
556
      registerPair(O, op);
345
556
      break;
346
15.8k
    case M68K_OP_REG:
347
15.8k
      SStream_concat(O, "%s", s_reg_names[op->reg]);
348
15.8k
      break;
349
3
    default:
350
3
      break;
351
19.3k
    }
352
19.3k
    break;
353
354
141k
  case M68K_AM_REG_DIRECT_DATA:
355
161k
  case M68K_AM_REG_DIRECT_ADDR:
356
183k
  case M68K_AM_REGI_ADDR:
357
205k
  case M68K_AM_REGI_ADDR_POST_INC:
358
252k
  case M68K_AM_REGI_ADDR_PRE_DEC:
359
270k
  case M68K_AM_REGI_ADDR_DISP:
360
272k
  case M68K_AM_PCI_DISP:
361
272k
    printRegAddrMode(O, pc, op);
362
272k
    break;
363
4.25k
  case M68K_AM_ABSOLUTE_DATA_SHORT:
364
4.25k
    SStream_concat(O, "$%" PRIx32 ".w", (uint32_t)op->imm);
365
4.25k
    break;
366
1.82k
  case M68K_AM_ABSOLUTE_DATA_LONG:
367
1.82k
    SStream_concat(O, "$%" PRIx64 ".l", (uint64_t)op->imm);
368
1.82k
    break;
369
58.7k
  case M68K_AM_IMMEDIATE:
370
58.7k
    printImmediate(O, inst, op);
371
58.7k
    break;
372
1.21k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
373
8.85k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
374
8.85k
    printIndex8BitDisp(O, pc, op);
375
8.85k
    break;
376
280
  case M68K_AM_PCI_INDEX_BASE_DISP:
377
2.32k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
378
2.32k
    printBaseDisp(O, pc, op);
379
2.32k
    break;
380
353
  case M68K_AM_PC_MEMI_POST_INDEX:
381
693
  case M68K_AM_PC_MEMI_PRE_INDEX:
382
2.96k
  case M68K_AM_MEMI_PRE_INDEX:
383
5.00k
  case M68K_AM_MEMI_POST_INDEX:
384
5.00k
    printMemIndirect(O, pc, op);
385
5.00k
    break;
386
14.9k
  case M68K_AM_BRANCH_DISPLACEMENT:
387
14.9k
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->br_disp.disp);
388
14.9k
  default:
389
14.9k
    break;
390
387k
  }
391
392
387k
  printBitfield(O, op);
393
387k
}
394
395
static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext)
396
16
{
397
16
  printAddressingMode(O, pc, ext, &ext->operands[0]);
398
16
  SStream_concat0(O, ",");
399
16
  printAddressingMode(O, pc, ext, &ext->operands[1]);
400
16
  SStream_concat0(O, ",");
401
402
16
  SStream_concat(O, "(%s):(%s)",
403
16
           s_reg_names[ext->operands[2].reg_pair.reg_0],
404
16
           s_reg_names[ext->operands[2].reg_pair.reg_1]);
405
16
}
406
407
static void printCacheOp(SStream *O, unsigned int pc, const cs_m68k *ext)
408
544
{
409
544
  static const char *const cache_names[] = { "nc", "dc", "ic", "bc" };
410
544
  unsigned int sel = (unsigned int)ext->operands[0].imm;
411
544
  int i;
412
413
544
  if (sel < ARR_SIZE(cache_names))
414
544
    SStream_concat0(O, cache_names[sel]);
415
0
  else
416
0
    SStream_concat(O, "#$%" PRIx64, ext->operands[0].imm);
417
418
995
  for (i = 1; i < ext->op_count; ++i) {
419
451
    SStream_concat(O, ",%s", s_spacing);
420
451
    printAddressingMode(O, pc, ext, &ext->operands[i]);
421
451
  }
422
544
}
423
#endif
424
425
static void printOpSize(SStream *O, const cs_m68k *ext)
426
213k
{
427
213k
  switch (ext->op_size.type) {
428
0
  case M68K_SIZE_TYPE_INVALID:
429
0
    break;
430
213k
  case M68K_SIZE_TYPE_CPU:
431
213k
    switch (ext->op_size.cpu_size) {
432
77.1k
    case M68K_CPU_SIZE_BYTE:
433
77.1k
      SStream_concat0(O, ".b");
434
77.1k
      break;
435
60.0k
    case M68K_CPU_SIZE_WORD:
436
60.0k
      SStream_concat0(O, ".w");
437
60.0k
      break;
438
53.5k
    case M68K_CPU_SIZE_LONG:
439
53.5k
      SStream_concat0(O, ".l");
440
53.5k
      break;
441
22.8k
    case M68K_CPU_SIZE_NONE:
442
22.8k
      break;
443
213k
    }
444
213k
    break;
445
213k
  case M68K_SIZE_TYPE_FPU:
446
183
    switch (ext->op_size.fpu_size) {
447
127
    case M68K_FPU_SIZE_SINGLE:
448
127
      SStream_concat0(O, ".s");
449
127
      break;
450
0
    case M68K_FPU_SIZE_DOUBLE:
451
0
      SStream_concat0(O, ".d");
452
0
      break;
453
56
    case M68K_FPU_SIZE_EXTENDED:
454
56
      SStream_concat0(O, ".x");
455
56
      break;
456
0
    case M68K_FPU_SIZE_NONE:
457
0
      break;
458
183
    }
459
183
    break;
460
213k
  }
461
213k
}
462
463
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
464
267k
{
465
267k
#ifndef CAPSTONE_DIET
466
267k
  m68k_info *info = (m68k_info *)PrinterInfo;
467
267k
  cs_m68k *ext = &info->extension;
468
267k
  cs_detail *detail = NULL;
469
267k
  int i = 0;
470
471
267k
  if (detail_is_set(MI)) {
472
267k
    detail = get_detail(MI);
473
267k
    int regs_read_count = MIN((int)ARR_SIZE(detail->regs_read),
474
267k
            info->regs_read_count);
475
267k
    int regs_write_count = MIN((int)ARR_SIZE(detail->regs_write),
476
267k
             info->regs_write_count);
477
267k
    int groups_count =
478
267k
      MIN((int)ARR_SIZE(detail->groups), info->groups_count);
479
480
267k
    memcpy(&detail->m68k, ext, sizeof(cs_m68k));
481
267k
    memcpy(&detail->regs_read, &info->regs_read,
482
267k
           regs_read_count * sizeof(info->regs_read[0]));
483
267k
    detail->regs_read_count = regs_read_count;
484
485
267k
    memcpy(&detail->regs_write, &info->regs_write,
486
267k
           regs_write_count * sizeof(info->regs_write[0]));
487
267k
    detail->regs_write_count = regs_write_count;
488
489
267k
    memcpy(&detail->groups, &info->groups, groups_count);
490
267k
    detail->groups_count = groups_count;
491
267k
  }
492
493
267k
  if (MI->Opcode == M68K_INS_INVALID) {
494
53.4k
    if (ext->op_count)
495
53.4k
      SStream_concat(O, "dc.w $%" PRIx32,
496
53.4k
               (uint32_t)ext->operands[0].imm);
497
0
    else
498
0
      SStream_concat(O, "dc.w $<unknown>");
499
53.4k
    return;
500
53.4k
  }
501
502
213k
  SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
503
213k
  printOpSize(O, ext);
504
213k
  SStream_concat0(O, " ");
505
506
213k
  if (MI->Opcode == M68K_INS_CAS2) {
507
16
    printCAS2(O, info->pc, ext);
508
16
    return;
509
16
  }
510
511
213k
  if (MI->Opcode >= M68K_INS_CINVL && MI->Opcode <= M68K_INS_CPUSHA) {
512
544
    printCacheOp(O, info->pc, ext);
513
544
    return;
514
544
  }
515
516
600k
  for (i = 0; i < ext->op_count; ++i) {
517
387k
    printAddressingMode(O, info->pc, ext, &ext->operands[i]);
518
387k
    if ((i + 1) != ext->op_count)
519
175k
      SStream_concat(O, ",%s", s_spacing);
520
387k
  }
521
213k
#endif
522
213k
}
523
524
const char *M68K_reg_name(csh handle, unsigned int reg)
525
575k
{
526
#ifdef CAPSTONE_DIET
527
  return NULL;
528
#else
529
575k
  if (reg >= ARR_SIZE(s_reg_names)) {
530
0
    return NULL;
531
0
  }
532
575k
  return s_reg_names[(int)reg];
533
575k
#endif
534
575k
}
535
536
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
537
472k
{
538
472k
  insn->id = id; // These id's matches for 68k
539
472k
}
540
541
const char *M68K_insn_name(csh handle, unsigned int id)
542
472k
{
543
#ifdef CAPSTONE_DIET
544
  return NULL;
545
#else
546
472k
  return s_instruction_names[id];
547
472k
#endif
548
472k
}
549
550
#ifndef CAPSTONE_DIET
551
static const name_map group_name_maps[] = {
552
  { M68K_GRP_INVALID, NULL },
553
  { M68K_GRP_JUMP, "jump" },
554
  { M68K_GRP_RET, "ret" },
555
  { M68K_GRP_IRET, "iret" },
556
  { M68K_GRP_BRANCH_RELATIVE, "branch_relative" },
557
};
558
#endif
559
560
const char *M68K_group_name(csh handle, unsigned int id)
561
73.2k
{
562
73.2k
#ifndef CAPSTONE_DIET
563
73.2k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
564
#else
565
  return NULL;
566
#endif
567
73.2k
}
568
569
#ifndef CAPSTONE_DIET
570
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
571
         uint8_t *regs_read_count, cs_regs regs_write,
572
         uint8_t *regs_write_count)
573
0
{
574
0
  uint8_t read_count, write_count;
575
576
0
  read_count = insn->detail->regs_read_count;
577
0
  write_count = insn->detail->regs_write_count;
578
579
  // implicit registers
580
0
  memcpy(regs_read, insn->detail->regs_read,
581
0
         read_count * sizeof(insn->detail->regs_read[0]));
582
0
  memcpy(regs_write, insn->detail->regs_write,
583
0
         write_count * sizeof(insn->detail->regs_write[0]));
584
585
0
  *regs_read_count = read_count;
586
0
  *regs_write_count = write_count;
587
0
}
588
#endif