Coverage Report

Created: 2026-02-26 07:11

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> // DEBUG
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include "M68KInstPrinter.h"
9
10
#include "M68KDisassembler.h"
11
12
#include "../../cs_priv.h"
13
#include "../../Mapping.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
34
static const char *const s_instruction_names[] = {
35
  "invalid",  "abcd", "add",      "adda", "addi",      "addq",
36
  "addx",     "and",  "andi",     "asl",  "asr",       "bhs",
37
  "blo",      "bhi",  "bls",      "bcc",  "bcs",       "bne",
38
  "beq",      "bvc",  "bvs",      "bpl",  "bmi",       "bge",
39
  "blt",      "bgt",  "ble",      "bra",  "bsr",       "bchg",
40
  "bclr",     "bset", "btst",     "bfchg",  "bfclr",     "bfexts",
41
  "bfextu",   "bfffo",  "bfins",    "bfset",  "bftst",     "bkpt",
42
  "callm",    "cas",  "cas2",     "chk",  "chk2",      "clr",
43
  "cmp",      "cmpa", "cmpi",     "cmpm", "cmp2",      "cinvl",
44
  "cinvp",    "cinva",  "cpushl",   "cpushp", "cpusha",    "dbt",
45
  "dbf",      "dbhi", "dbls",     "dbcc", "dbcs",      "dbne",
46
  "dbeq",     "dbvc", "dbvs",     "dbpl", "dbmi",      "dbge",
47
  "dblt",     "dbgt", "dble",     "dbra", "divs",      "divsl",
48
  "divu",     "divul",  "eor",      "eori", "exg",       "ext",
49
  "extb",     "fabs", "fsabs",    "fdabs",  "facos",     "fadd",
50
  "fsadd",    "fdadd",  "fasin",    "fatan",  "fatanh",    "fbf",
51
  "fbeq",     "fbogt",  "fboge",    "fbolt",  "fbole",     "fbogl",
52
  "fbor",     "fbun", "fbueq",    "fbugt",  "fbuge",     "fbult",
53
  "fbule",    "fbne", "fbt",      "fbsf", "fbseq",     "fbgt",
54
  "fbge",     "fblt", "fble",     "fbgl", "fbgle",     "fbngle",
55
  "fbngl",    "fbnle",  "fbnlt",    "fbnge",  "fbngt",     "fbsne",
56
  "fbst",     "fcmp", "fcos",     "fcosh",  "fdbf",      "fdbeq",
57
  "fdbogt",   "fdboge", "fdbolt",   "fdbole", "fdbogl",    "fdbor",
58
  "fdbun",    "fdbueq", "fdbugt",   "fdbuge", "fdbult",    "fdbule",
59
  "fdbne",    "fdbt", "fdbsf",    "fdbseq", "fdbgt",     "fdbge",
60
  "fdblt",    "fdble",  "fdbgl",    "fdbgle", "fdbngle",   "fdbngl",
61
  "fdbnle",   "fdbnlt", "fdbnge",   "fdbngt", "fdbsne",    "fdbst",
62
  "fdiv",     "fsdiv",  "fddiv",    "fetox",  "fetoxm1",   "fgetexp",
63
  "fgetman",  "fint", "fintrz",   "flog10", "flog2",     "flogn",
64
  "flognp1",  "fmod", "fmove",    "fsmove", "fdmove",    "fmovecr",
65
  "fmovem",   "fmul", "fsmul",    "fdmul",  "fneg",      "fsneg",
66
  "fdneg",    "fnop", "frem",     "frestore", "fsave",     "fscale",
67
  "fsgldiv",  "fsglmul",  "fsin",     "fsincos",  "fsinh",     "fsqrt",
68
  "fssqrt",   "fdsqrt", "fsf",      "fseq", "fsogt",     "fsoge",
69
  "fsolt",    "fsole",  "fsogl",    "fsor", "fsun",      "fsueq",
70
  "fsugt",    "fsuge",  "fsult",    "fsule",  "fsne",      "fst",
71
  "fssf",     "fsseq",  "fsgt",     "fsge", "fslt",      "fsle",
72
  "fsgl",     "fsgle",  "fsngle",   "fsngl",  "fsnle",     "fsnlt",
73
  "fsnge",    "fsngt",  "fssne",    "fsst", "fsub",      "fssub",
74
  "fdsub",    "ftan", "ftanh",    "ftentox",  "ftrapf",    "ftrapeq",
75
  "ftrapogt", "ftrapoge", "ftrapolt", "ftrapole", "ftrapogl",  "ftrapor",
76
  "ftrapun",  "ftrapueq", "ftrapugt", "ftrapuge", "ftrapult",  "ftrapule",
77
  "ftrapne",  "ftrapt", "ftrapsf",  "ftrapseq", "ftrapgt",   "ftrapge",
78
  "ftraplt",  "ftraple",  "ftrapgl",  "ftrapgle", "ftrapngle", "ftrapngl",
79
  "ftrapnle", "ftrapnlt", "ftrapnge", "ftrapngt", "ftrapsne",  "ftrapst",
80
  "ftst",     "ftwotox",  "halt",     "illegal",  "jmp",       "jsr",
81
  "lea",      "link", "lpstop",   "lsl",  "lsr",       "move",
82
  "movea",    "movec",  "movem",    "movep",  "moveq",     "moves",
83
  "move16",   "muls", "mulu",     "nbcd", "neg",       "negx",
84
  "nop",      "not",  "or",     "ori",  "pack",      "pea",
85
  "pflush",   "pflusha",  "pflushan", "pflushn",  "ploadr",    "ploadw",
86
  "plpar",    "plpaw",  "pmove",    "pmovefd",  "ptestr",    "ptestw",
87
  "pulse",    "rems", "remu",     "reset",  "rol",       "ror",
88
  "roxl",     "roxr", "rtd",      "rte",  "rtm",       "rtr",
89
  "rts",      "sbcd", "st",     "sf", "shi",       "sls",
90
  "scc",      "shs",  "scs",      "slo",  "sne",       "seq",
91
  "svc",      "svs",  "spl",      "smi",  "sge",       "slt",
92
  "sgt",      "sle",  "stop",     "sub",  "suba",      "subi",
93
  "subq",     "subx", "swap",     "tas",  "trap",      "trapv",
94
  "trapt",    "trapf",  "traphi",   "trapls", "trapcc",    "traphs",
95
  "trapcs",   "traplo", "trapne",   "trapeq", "trapvc",    "trapvs",
96
  "trappl",   "trapmi", "trapge",   "traplt", "trapgt",    "traple",
97
  "tst",      "unlk", "unpk",
98
};
99
#endif
100
101
#ifndef CAPSTONE_DIET
102
static const char *getRegName(m68k_reg reg)
103
29.5k
{
104
29.5k
  return s_reg_names[(int)reg];
105
29.5k
}
106
107
static void printRegbitsRange(char *buffer, size_t buf_len, uint32_t data,
108
            const char *prefix)
109
14.9k
{
110
14.9k
  unsigned int first = 0;
111
14.9k
  unsigned int run_length = 0;
112
14.9k
  int i;
113
114
121k
  for (i = 0; i < 8; ++i) {
115
106k
    if (data & (1 << i)) {
116
17.9k
      first = i;
117
17.9k
      run_length = 0;
118
119
30.5k
      while (i < 7 && (data & (1 << (i + 1)))) {
120
12.5k
        i++;
121
12.5k
        run_length++;
122
12.5k
      }
123
124
17.9k
      if (buffer[0] != 0)
125
13.0k
        strncat(buffer, "/", buf_len - 1);
126
127
17.9k
      snprintf(buffer + strlen(buffer), buf_len, "%s%" PRId32,
128
17.9k
         prefix, first);
129
17.9k
      if (run_length > 0)
130
6.71k
        snprintf(buffer + strlen(buffer), buf_len,
131
6.71k
           "-%s%" PRId32, prefix,
132
6.71k
           first + run_length);
133
17.9k
    }
134
106k
  }
135
14.9k
}
136
137
static void registerBits(SStream *O, const cs_m68k_op *op)
138
5.28k
{
139
5.28k
  char buffer[128];
140
5.28k
  unsigned int data = op->register_bits;
141
142
5.28k
  buffer[0] = 0;
143
144
5.28k
  if (!data) {
145
307
    SStream_concat(O, "%s", "#$0");
146
307
    return;
147
307
  }
148
149
4.98k
  printRegbitsRange(buffer, sizeof(buffer), data & 0xff, "d");
150
4.98k
  printRegbitsRange(buffer, sizeof(buffer), (data >> 8) & 0xff, "a");
151
4.98k
  printRegbitsRange(buffer, sizeof(buffer), (data >> 16) & 0xff, "fp");
152
153
4.98k
  SStream_concat(O, "%s", buffer);
154
4.98k
}
155
156
static void registerPair(SStream *O, const cs_m68k_op *op)
157
1.28k
{
158
1.28k
  SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
159
1.28k
           s_reg_names[op->reg_pair.reg_1]);
160
1.28k
}
161
162
static void printAddressingMode(SStream *O, unsigned int pc,
163
        const cs_m68k *inst, const cs_m68k_op *op)
164
450k
{
165
450k
  switch (op->address_mode) {
166
47.1k
  case M68K_AM_NONE:
167
47.1k
    switch (op->type) {
168
5.28k
    case M68K_OP_REG_BITS:
169
5.28k
      registerBits(O, op);
170
5.28k
      break;
171
1.28k
    case M68K_OP_REG_PAIR:
172
1.28k
      registerPair(O, op);
173
1.28k
      break;
174
39.8k
    case M68K_OP_REG:
175
39.8k
      SStream_concat(O, "%s", s_reg_names[op->reg]);
176
39.8k
      break;
177
655
    default:
178
655
      break;
179
47.1k
    }
180
47.1k
    break;
181
182
145k
  case M68K_AM_REG_DIRECT_DATA:
183
145k
    SStream_concat(O, "d%" PRId32, (op->reg - M68K_REG_D0));
184
145k
    break;
185
22.1k
  case M68K_AM_REG_DIRECT_ADDR:
186
22.1k
    SStream_concat(O, "a%" PRId32, (op->reg - M68K_REG_A0));
187
22.1k
    break;
188
27.9k
  case M68K_AM_REGI_ADDR:
189
27.9k
    SStream_concat(O, "(a%" PRId32 ")", (op->reg - M68K_REG_A0));
190
27.9k
    break;
191
25.6k
  case M68K_AM_REGI_ADDR_POST_INC:
192
25.6k
    SStream_concat(O, "(a%" PRId32 ")+", (op->reg - M68K_REG_A0));
193
25.6k
    break;
194
41.9k
  case M68K_AM_REGI_ADDR_PRE_DEC:
195
41.9k
    SStream_concat(O, "-(a%" PRId32 ")", (op->reg - M68K_REG_A0));
196
41.9k
    break;
197
20.5k
  case M68K_AM_REGI_ADDR_DISP:
198
20.5k
    SStream_concat(O, "%s$%" PRIx16 "(a%" PRId32 ")",
199
20.5k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
200
20.5k
             (op->mem.base_reg - M68K_REG_A0));
201
20.5k
    break;
202
3.16k
  case M68K_AM_PCI_DISP:
203
3.16k
    SStream_concat(O, "$%" PRIx32 "(pc)", pc + 2 + op->mem.disp);
204
3.16k
    break;
205
3.42k
  case M68K_AM_ABSOLUTE_DATA_SHORT:
206
3.42k
    SStream_concat(O, "$%" PRIx32 ".w", op->imm);
207
3.42k
    break;
208
1.94k
  case M68K_AM_ABSOLUTE_DATA_LONG:
209
1.94k
    SStream_concat(O, "$%" PRIx64 ".l", op->imm);
210
1.94k
    break;
211
65.6k
  case M68K_AM_IMMEDIATE:
212
65.6k
    if (inst->op_size.type == M68K_SIZE_TYPE_FPU) {
213
#if defined(_KERNEL_MODE)
214
      // Issue #681: Windows kernel does not support formatting float point
215
      SStream_concat(O, "#<float_point_unsupported>");
216
      break;
217
#else
218
324
      if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
219
55
        SStream_concat(O, "#%f", op->simm);
220
269
      else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
221
269
        SStream_concat(O, "#%f", op->dimm);
222
0
      else
223
0
        SStream_concat(O, "#<unsupported>");
224
324
      break;
225
324
#endif
226
324
    }
227
65.3k
    SStream_concat(O, "#$%" PRIx64, op->imm);
228
65.3k
    break;
229
1.83k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
230
1.83k
    SStream_concat(O, "$%" PRIx32 "(pc,%s%s.%c)",
231
1.83k
             pc + 2 + op->mem.disp, s_spacing,
232
1.83k
             getRegName(op->mem.index_reg),
233
1.83k
             op->mem.index_size ? 'l' : 'w');
234
1.83k
    break;
235
8.61k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
236
8.61k
    SStream_concat(O, "%s$%" PRIx16 "(%s,%s%s.%c)",
237
8.61k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
238
8.61k
             getRegName(op->mem.base_reg), s_spacing,
239
8.61k
             getRegName(op->mem.index_reg),
240
8.61k
             op->mem.index_size ? 'l' : 'w');
241
8.61k
    break;
242
349
  case M68K_AM_PCI_INDEX_BASE_DISP:
243
4.81k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
244
245
4.81k
    if (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP) {
246
349
      SStream_concat(O, "$%" PRIx32,
247
349
               pc + 2 + op->mem.in_disp);
248
4.46k
    } else if (op->mem.in_disp != 0) {
249
1.37k
      SStream_concat(O, "%s$%" PRIx32,
250
1.37k
               op->mem.in_disp >= 0 ? "" : "-",
251
1.37k
               abs(op->mem.in_disp));
252
1.37k
    }
253
254
4.81k
    SStream_concat0(O, "(");
255
256
4.81k
    if (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP) {
257
349
      SStream_concat0(O, "pc");
258
4.46k
    } else if (op->mem.base_reg != M68K_REG_INVALID) {
259
3.13k
      SStream_concat(O, "a%" PRId32,
260
3.13k
               op->mem.base_reg - M68K_REG_A0);
261
3.13k
    }
262
263
4.81k
    if ((op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP ||
264
4.46k
         op->mem.base_reg != M68K_REG_INVALID) &&
265
3.48k
        op->mem.index_reg != M68K_REG_INVALID)
266
2.46k
      SStream_concat(O, ",%s", s_spacing);
267
268
4.81k
    if (op->mem.index_reg != M68K_REG_INVALID) {
269
3.38k
      SStream_concat(O, "%s.%c",
270
3.38k
               getRegName(op->mem.index_reg),
271
3.38k
               op->mem.index_size ? 'l' : 'w');
272
3.38k
      if (op->mem.scale > 0)
273
2.14k
        SStream_concat(O, "%s*%s%" PRId8, s_spacing,
274
2.14k
                 s_spacing, op->mem.scale);
275
3.38k
    }
276
277
4.81k
    SStream_concat0(O, ")");
278
4.81k
    break;
279
    // It's ok to just use PCMI here as is as we set base_reg to PC in the disassembler. While this is not strictly correct it makes the code
280
    // easier and that is what actually happens when the code is executed anyway.
281
282
600
  case M68K_AM_PC_MEMI_POST_INDEX:
283
1.02k
  case M68K_AM_PC_MEMI_PRE_INDEX:
284
3.63k
  case M68K_AM_MEMI_PRE_INDEX:
285
6.05k
  case M68K_AM_MEMI_POST_INDEX:
286
6.05k
    SStream_concat0(O, "([");
287
288
6.05k
    if (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
289
5.45k
        op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX) {
290
1.02k
      SStream_concat(O, "$%" PRIx32,
291
1.02k
               pc + 2 + op->mem.in_disp);
292
5.03k
    } else if (op->mem.in_disp != 0) {
293
2.80k
      SStream_concat(O, "%s$%" PRIx32,
294
2.80k
               op->mem.in_disp >= 0 ? "" : "-",
295
2.80k
               abs(op->mem.in_disp));
296
2.80k
    }
297
298
6.05k
    if (op->mem.base_reg != M68K_REG_INVALID) {
299
3.99k
      if (op->mem.in_disp != 0)
300
1.99k
        SStream_concat(O, ",%s%s", s_spacing,
301
1.99k
                 getRegName(op->mem.base_reg));
302
2.00k
      else
303
2.00k
        SStream_concat(O, "%s",
304
2.00k
                 getRegName(op->mem.base_reg));
305
3.99k
    }
306
307
6.05k
    if (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
308
3.63k
        op->address_mode == M68K_AM_PC_MEMI_POST_INDEX)
309
3.01k
      SStream_concat0(O, "]");
310
311
6.05k
    if (op->mem.index_reg != M68K_REG_INVALID)
312
3.05k
      SStream_concat(O, ",%s%s.%c", s_spacing,
313
3.05k
               getRegName(op->mem.index_reg),
314
3.05k
               op->mem.index_size ? 'l' : 'w');
315
316
6.05k
    if (op->mem.scale > 0)
317
2.13k
      SStream_concat(O, "%s*%s%" PRId8, s_spacing, s_spacing,
318
2.13k
               op->mem.scale);
319
320
6.05k
    if (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
321
3.43k
        op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX)
322
3.03k
      SStream_concat0(O, "]");
323
324
6.05k
    if (op->mem.out_disp != 0) {
325
2.36k
      SStream_concat(O, ",%s%s$%" PRIx32, s_spacing,
326
2.36k
               op->mem.out_disp >= 0 ? "" : "-",
327
2.36k
               abs(op->mem.out_disp));
328
2.36k
    }
329
330
6.05k
    SStream_concat0(O, ")");
331
6.05k
    break;
332
24.3k
  case M68K_AM_BRANCH_DISPLACEMENT:
333
24.3k
    SStream_concat(O, "$%" PRIx32, pc + 2 + op->br_disp.disp);
334
24.3k
  default:
335
24.3k
    break;
336
450k
  }
337
338
450k
  if (op->mem.bitfield)
339
2.68k
    SStream_concat(O, "{%" PRId8 ":%" PRId8 "}", op->mem.offset,
340
2.68k
             op->mem.width);
341
450k
}
342
#endif
343
344
#define m68k_sizeof_array(array) (int)(sizeof(array) / sizeof(array[0]))
345
880k
#define m68k_min(a, b) (a < b) ? a : b
346
347
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
348
293k
{
349
293k
#ifndef CAPSTONE_DIET
350
293k
  m68k_info *info = (m68k_info *)PrinterInfo;
351
293k
  cs_m68k *ext = &info->extension;
352
293k
  cs_detail *detail = NULL;
353
293k
  int i = 0;
354
355
293k
  detail = MI->flat_insn->detail;
356
293k
  if (detail) {
357
293k
    int regs_read_count =
358
293k
      m68k_min(m68k_sizeof_array(detail->regs_read),
359
293k
         info->regs_read_count);
360
293k
    int regs_write_count =
361
293k
      m68k_min(m68k_sizeof_array(detail->regs_write),
362
293k
         info->regs_write_count);
363
293k
    int groups_count = m68k_min(m68k_sizeof_array(detail->groups),
364
293k
              info->groups_count);
365
366
293k
    memcpy(&detail->m68k, ext, sizeof(cs_m68k));
367
368
293k
    memcpy(&detail->regs_read, &info->regs_read,
369
293k
           regs_read_count * sizeof(info->regs_read[0]));
370
293k
    detail->regs_read_count = regs_read_count;
371
372
293k
    memcpy(&detail->regs_write, &info->regs_write,
373
293k
           regs_write_count * sizeof(info->regs_write[0]));
374
293k
    detail->regs_write_count = regs_write_count;
375
376
293k
    memcpy(&detail->groups, &info->groups, groups_count);
377
293k
    detail->groups_count = groups_count;
378
293k
  }
379
380
293k
  if (MI->Opcode == M68K_INS_INVALID) {
381
42.8k
    if (ext->op_count)
382
42.8k
      SStream_concat(O, "dc.w $%" PRIx32,
383
42.8k
               ext->operands[0].imm);
384
0
    else
385
0
      SStream_concat(O, "dc.w $<unknown>");
386
42.8k
    return;
387
42.8k
  }
388
389
250k
  SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
390
391
250k
  switch (ext->op_size.type) {
392
0
  case M68K_SIZE_TYPE_INVALID:
393
0
    break;
394
395
247k
  case M68K_SIZE_TYPE_CPU:
396
247k
    switch (ext->op_size.cpu_size) {
397
78.8k
    case M68K_CPU_SIZE_BYTE:
398
78.8k
      SStream_concat0(O, ".b");
399
78.8k
      break;
400
63.7k
    case M68K_CPU_SIZE_WORD:
401
63.7k
      SStream_concat0(O, ".w");
402
63.7k
      break;
403
67.3k
    case M68K_CPU_SIZE_LONG:
404
67.3k
      SStream_concat0(O, ".l");
405
67.3k
      break;
406
37.7k
    case M68K_CPU_SIZE_NONE:
407
37.7k
      break;
408
247k
    }
409
247k
    break;
410
411
247k
  case M68K_SIZE_TYPE_FPU:
412
3.10k
    switch (ext->op_size.fpu_size) {
413
1.13k
    case M68K_FPU_SIZE_SINGLE:
414
1.13k
      SStream_concat0(O, ".s");
415
1.13k
      break;
416
1.05k
    case M68K_FPU_SIZE_DOUBLE:
417
1.05k
      SStream_concat0(O, ".d");
418
1.05k
      break;
419
926
    case M68K_FPU_SIZE_EXTENDED:
420
926
      SStream_concat0(O, ".x");
421
926
      break;
422
0
    case M68K_FPU_SIZE_NONE:
423
0
      break;
424
3.10k
    }
425
3.10k
    break;
426
250k
  }
427
428
250k
  SStream_concat0(O, " ");
429
430
  // this one is a bit spacial so we do special things
431
432
250k
  if (MI->Opcode == M68K_INS_CAS2) {
433
494
    int reg_value_0, reg_value_1;
434
494
    printAddressingMode(O, info->pc, ext, &ext->operands[0]);
435
494
    SStream_concat0(O, ",");
436
494
    printAddressingMode(O, info->pc, ext, &ext->operands[1]);
437
494
    SStream_concat0(O, ",");
438
494
    reg_value_0 = ext->operands[2].register_bits >> 4;
439
494
    reg_value_1 = ext->operands[2].register_bits & 0xf;
440
494
    SStream_concat(O, "(%s):(%s)",
441
494
             s_reg_names[M68K_REG_D0 + reg_value_0],
442
494
             s_reg_names[M68K_REG_D0 + reg_value_1]);
443
494
    return;
444
494
  }
445
446
699k
  for (i = 0; i < ext->op_count; ++i) {
447
449k
    printAddressingMode(O, info->pc, ext, &ext->operands[i]);
448
449k
    if ((i + 1) != ext->op_count)
449
200k
      SStream_concat(O, ",%s", s_spacing);
450
449k
  }
451
250k
#endif
452
250k
}
453
454
const char *M68K_reg_name(csh handle, unsigned int reg)
455
362k
{
456
#ifdef CAPSTONE_DIET
457
  return NULL;
458
#else
459
362k
  if (reg >= ARR_SIZE(s_reg_names)) {
460
0
    return NULL;
461
0
  }
462
362k
  return s_reg_names[(int)reg];
463
362k
#endif
464
362k
}
465
466
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
467
293k
{
468
293k
  insn->id = id; // These id's matches for 68k
469
293k
}
470
471
const char *M68K_insn_name(csh handle, unsigned int id)
472
293k
{
473
#ifdef CAPSTONE_DIET
474
  return NULL;
475
#else
476
293k
  return s_instruction_names[id];
477
293k
#endif
478
293k
}
479
480
#ifndef CAPSTONE_DIET
481
static const name_map group_name_maps[] = {
482
  { M68K_GRP_INVALID, NULL },
483
  { M68K_GRP_JUMP, "jump" },
484
  { M68K_GRP_RET, "ret" },
485
  { M68K_GRP_IRET, "iret" },
486
  { M68K_GRP_BRANCH_RELATIVE, "branch_relative" },
487
};
488
#endif
489
490
const char *M68K_group_name(csh handle, unsigned int id)
491
53.8k
{
492
53.8k
#ifndef CAPSTONE_DIET
493
53.8k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
494
#else
495
  return NULL;
496
#endif
497
53.8k
}
498
499
#ifndef CAPSTONE_DIET
500
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
501
         uint8_t *regs_read_count, cs_regs regs_write,
502
         uint8_t *regs_write_count)
503
0
{
504
0
  uint8_t read_count, write_count;
505
506
0
  read_count = insn->detail->regs_read_count;
507
0
  write_count = insn->detail->regs_write_count;
508
509
  // implicit registers
510
0
  memcpy(regs_read, insn->detail->regs_read,
511
0
         read_count * sizeof(insn->detail->regs_read[0]));
512
0
  memcpy(regs_write, insn->detail->regs_write,
513
0
         write_count * sizeof(insn->detail->regs_write[0]));
514
515
0
  *regs_read_count = read_count;
516
0
  *regs_write_count = write_count;
517
0
}
518
#endif