Coverage Report

Created: 2026-01-10 06:34

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
44.3k
{
104
44.3k
  return s_reg_names[(int)reg];
105
44.3k
}
106
107
static void printRegbitsRange(char *buffer, size_t buf_len, uint32_t data,
108
            const char *prefix)
109
24.4k
{
110
24.4k
  unsigned int first = 0;
111
24.4k
  unsigned int run_length = 0;
112
24.4k
  int i;
113
114
200k
  for (i = 0; i < 8; ++i) {
115
176k
    if (data & (1 << i)) {
116
29.6k
      first = i;
117
29.6k
      run_length = 0;
118
119
49.0k
      while (i < 7 && (data & (1 << (i + 1)))) {
120
19.3k
        i++;
121
19.3k
        run_length++;
122
19.3k
      }
123
124
29.6k
      if (buffer[0] != 0)
125
21.4k
        strncat(buffer, "/", buf_len - 1);
126
127
29.6k
      snprintf(buffer + strlen(buffer), buf_len, "%s%d",
128
29.6k
         prefix, first);
129
29.6k
      if (run_length > 0)
130
9.92k
        snprintf(buffer + strlen(buffer), buf_len,
131
9.92k
           "-%s%d", prefix, first + run_length);
132
29.6k
    }
133
176k
  }
134
24.4k
}
135
136
static void registerBits(SStream *O, const cs_m68k_op *op)
137
9.48k
{
138
9.48k
  char buffer[128];
139
9.48k
  unsigned int data = op->register_bits;
140
141
9.48k
  buffer[0] = 0;
142
143
9.48k
  if (!data) {
144
1.33k
    SStream_concat(O, "%s", "#$0");
145
1.33k
    return;
146
1.33k
  }
147
148
8.14k
  printRegbitsRange(buffer, sizeof(buffer), data & 0xff, "d");
149
8.14k
  printRegbitsRange(buffer, sizeof(buffer), (data >> 8) & 0xff, "a");
150
8.14k
  printRegbitsRange(buffer, sizeof(buffer), (data >> 16) & 0xff, "fp");
151
152
8.14k
  SStream_concat(O, "%s", buffer);
153
8.14k
}
154
155
static void registerPair(SStream *O, const cs_m68k_op *op)
156
4.23k
{
157
4.23k
  SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
158
4.23k
           s_reg_names[op->reg_pair.reg_1]);
159
4.23k
}
160
161
static void printAddressingMode(SStream *O, unsigned int pc,
162
        const cs_m68k *inst, const cs_m68k_op *op)
163
362k
{
164
362k
  switch (op->address_mode) {
165
39.8k
  case M68K_AM_NONE:
166
39.8k
    switch (op->type) {
167
5.02k
    case M68K_OP_REG_BITS:
168
5.02k
      registerBits(O, op);
169
5.02k
      break;
170
3.28k
    case M68K_OP_REG_PAIR:
171
3.28k
      registerPair(O, op);
172
3.28k
      break;
173
30.9k
    case M68K_OP_REG:
174
30.9k
      SStream_concat(O, "%s", s_reg_names[op->reg]);
175
30.9k
      break;
176
632
    default:
177
632
      break;
178
39.8k
    }
179
39.8k
    break;
180
181
119k
  case M68K_AM_REG_DIRECT_DATA:
182
119k
    SStream_concat(O, "d%d", (op->reg - M68K_REG_D0));
183
119k
    break;
184
17.8k
  case M68K_AM_REG_DIRECT_ADDR:
185
17.8k
    SStream_concat(O, "a%d", (op->reg - M68K_REG_A0));
186
17.8k
    break;
187
21.1k
  case M68K_AM_REGI_ADDR:
188
21.1k
    SStream_concat(O, "(a%d)", (op->reg - M68K_REG_A0));
189
21.1k
    break;
190
22.1k
  case M68K_AM_REGI_ADDR_POST_INC:
191
22.1k
    SStream_concat(O, "(a%d)+", (op->reg - M68K_REG_A0));
192
22.1k
    break;
193
39.6k
  case M68K_AM_REGI_ADDR_PRE_DEC:
194
39.6k
    SStream_concat(O, "-(a%d)", (op->reg - M68K_REG_A0));
195
39.6k
    break;
196
14.1k
  case M68K_AM_REGI_ADDR_DISP:
197
14.1k
    SStream_concat(O, "%s$%x(a%d)", op->mem.disp < 0 ? "-" : "",
198
14.1k
             abs(op->mem.disp),
199
14.1k
             (op->mem.base_reg - M68K_REG_A0));
200
14.1k
    break;
201
2.18k
  case M68K_AM_PCI_DISP:
202
2.18k
    SStream_concat(O, "$%x(pc)", pc + 2 + op->mem.disp);
203
2.18k
    break;
204
2.07k
  case M68K_AM_ABSOLUTE_DATA_SHORT:
205
2.07k
    SStream_concat(O, "$%x.w", op->imm);
206
2.07k
    break;
207
1.87k
  case M68K_AM_ABSOLUTE_DATA_LONG:
208
1.87k
    SStream_concat(O, "$%x.l", op->imm);
209
1.87k
    break;
210
48.7k
  case M68K_AM_IMMEDIATE:
211
48.7k
    if (inst->op_size.type == M68K_SIZE_TYPE_FPU) {
212
#if defined(_KERNEL_MODE)
213
      // Issue #681: Windows kernel does not support formatting float point
214
      SStream_concat(O, "#<float_point_unsupported>");
215
      break;
216
#else
217
285
      if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
218
216
        SStream_concat(O, "#%f", op->simm);
219
69
      else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
220
69
        SStream_concat(O, "#%f", op->dimm);
221
0
      else
222
0
        SStream_concat(O, "#<unsupported>");
223
285
      break;
224
285
#endif
225
285
    }
226
48.4k
    SStream_concat(O, "#$%x", op->imm);
227
48.4k
    break;
228
816
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
229
816
    SStream_concat(O, "$%x(pc,%s%s.%c)", pc + 2 + op->mem.disp,
230
816
             s_spacing, getRegName(op->mem.index_reg),
231
816
             op->mem.index_size ? 'l' : 'w');
232
816
    break;
233
7.36k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
234
7.36k
    SStream_concat(O, "%s$%x(%s,%s%s.%c)",
235
7.36k
             op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
236
7.36k
             getRegName(op->mem.base_reg), s_spacing,
237
7.36k
             getRegName(op->mem.index_reg),
238
7.36k
             op->mem.index_size ? 'l' : 'w');
239
7.36k
    break;
240
367
  case M68K_AM_PCI_INDEX_BASE_DISP:
241
3.27k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
242
243
3.27k
    if (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP) {
244
367
      SStream_concat(O, "$%x", pc + 2 + op->mem.in_disp);
245
2.91k
    } else if (op->mem.in_disp != 0) {
246
1.19k
      SStream_concat(O, "%s$%x",
247
1.19k
               op->mem.in_disp >= 0 ? "" : "-",
248
1.19k
               abs(op->mem.in_disp));
249
1.19k
    }
250
251
3.27k
    SStream_concat0(O, "(");
252
253
3.27k
    if (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP) {
254
367
      SStream_concat0(O, "pc");
255
2.91k
    } else if (op->mem.base_reg != M68K_REG_INVALID) {
256
1.89k
      SStream_concat(O, "a%d",
257
1.89k
               op->mem.base_reg - M68K_REG_A0);
258
1.89k
    }
259
260
3.27k
    if ((op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP ||
261
2.91k
         op->mem.base_reg != M68K_REG_INVALID) &&
262
2.26k
        op->mem.index_reg != M68K_REG_INVALID)
263
1.74k
      SStream_concat(O, ",%s", s_spacing);
264
265
3.27k
    if (op->mem.index_reg != M68K_REG_INVALID) {
266
2.43k
      SStream_concat(O, "%s.%c",
267
2.43k
               getRegName(op->mem.index_reg),
268
2.43k
               op->mem.index_size ? 'l' : 'w');
269
2.43k
      if (op->mem.scale > 0)
270
1.76k
        SStream_concat(O, "%s*%s%d", s_spacing,
271
1.76k
                 s_spacing, op->mem.scale);
272
2.43k
    }
273
274
3.27k
    SStream_concat0(O, ")");
275
3.27k
    break;
276
    // 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
277
    // easier and that is what actually happens when the code is executed anyway.
278
279
196
  case M68K_AM_PC_MEMI_POST_INDEX:
280
940
  case M68K_AM_PC_MEMI_PRE_INDEX:
281
2.97k
  case M68K_AM_MEMI_PRE_INDEX:
282
4.84k
  case M68K_AM_MEMI_POST_INDEX:
283
4.84k
    SStream_concat0(O, "([");
284
285
4.84k
    if (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
286
4.65k
        op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX) {
287
940
      SStream_concat(O, "$%x", pc + 2 + op->mem.in_disp);
288
3.90k
    } else if (op->mem.in_disp != 0) {
289
2.48k
      SStream_concat(O, "%s$%x",
290
2.48k
               op->mem.in_disp >= 0 ? "" : "-",
291
2.48k
               abs(op->mem.in_disp));
292
2.48k
    }
293
294
4.84k
    if (op->mem.base_reg != M68K_REG_INVALID) {
295
2.40k
      if (op->mem.in_disp != 0)
296
1.39k
        SStream_concat(O, ",%s%s", s_spacing,
297
1.39k
                 getRegName(op->mem.base_reg));
298
1.00k
      else
299
1.00k
        SStream_concat(O, "%s",
300
1.00k
                 getRegName(op->mem.base_reg));
301
2.40k
    }
302
303
4.84k
    if (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
304
2.97k
        op->address_mode == M68K_AM_PC_MEMI_POST_INDEX)
305
2.06k
      SStream_concat0(O, "]");
306
307
4.84k
    if (op->mem.index_reg != M68K_REG_INVALID)
308
3.05k
      SStream_concat(O, ",%s%s.%c", s_spacing,
309
3.05k
               getRegName(op->mem.index_reg),
310
3.05k
               op->mem.index_size ? 'l' : 'w');
311
312
4.84k
    if (op->mem.scale > 0)
313
2.48k
      SStream_concat(O, "%s*%s%d", s_spacing, s_spacing,
314
2.48k
               op->mem.scale);
315
316
4.84k
    if (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
317
2.81k
        op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX)
318
2.78k
      SStream_concat0(O, "]");
319
320
4.84k
    if (op->mem.out_disp != 0) {
321
1.37k
      SStream_concat(O, ",%s%s$%x", s_spacing,
322
1.37k
               op->mem.out_disp >= 0 ? "" : "-",
323
1.37k
               abs(op->mem.out_disp));
324
1.37k
    }
325
326
4.84k
    SStream_concat0(O, ")");
327
4.84k
    break;
328
17.4k
  case M68K_AM_BRANCH_DISPLACEMENT:
329
17.4k
    SStream_concat(O, "$%x", pc + 2 + op->br_disp.disp);
330
17.4k
  default:
331
17.4k
    break;
332
362k
  }
333
334
362k
  if (op->mem.bitfield)
335
1.85k
    SStream_concat(O, "{%d:%d}", op->mem.offset, op->mem.width);
336
362k
}
337
#endif
338
339
#define m68k_sizeof_array(array) (int)(sizeof(array) / sizeof(array[0]))
340
1.29M
#define m68k_min(a, b) (a < b) ? a : b
341
342
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
343
433k
{
344
433k
#ifndef CAPSTONE_DIET
345
433k
  m68k_info *info = (m68k_info *)PrinterInfo;
346
433k
  cs_m68k *ext = &info->extension;
347
433k
  cs_detail *detail = NULL;
348
433k
  int i = 0;
349
350
433k
  detail = MI->flat_insn->detail;
351
433k
  if (detail) {
352
433k
    int regs_read_count =
353
433k
      m68k_min(m68k_sizeof_array(detail->regs_read),
354
433k
         info->regs_read_count);
355
433k
    int regs_write_count =
356
433k
      m68k_min(m68k_sizeof_array(detail->regs_write),
357
433k
         info->regs_write_count);
358
433k
    int groups_count = m68k_min(m68k_sizeof_array(detail->groups),
359
433k
              info->groups_count);
360
361
433k
    memcpy(&detail->m68k, ext, sizeof(cs_m68k));
362
363
433k
    memcpy(&detail->regs_read, &info->regs_read,
364
433k
           regs_read_count * sizeof(info->regs_read[0]));
365
433k
    detail->regs_read_count = regs_read_count;
366
367
433k
    memcpy(&detail->regs_write, &info->regs_write,
368
433k
           regs_write_count * sizeof(info->regs_write[0]));
369
433k
    detail->regs_write_count = regs_write_count;
370
371
433k
    memcpy(&detail->groups, &info->groups, groups_count);
372
433k
    detail->groups_count = groups_count;
373
433k
  }
374
375
433k
  if (MI->Opcode == M68K_INS_INVALID) {
376
63.4k
    if (ext->op_count)
377
63.4k
      SStream_concat(O, "dc.w $%x", ext->operands[0].imm);
378
0
    else
379
0
      SStream_concat(O, "dc.w $<unknown>");
380
63.4k
    return;
381
63.4k
  }
382
383
369k
  SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
384
385
369k
  switch (ext->op_size.type) {
386
0
  case M68K_SIZE_TYPE_INVALID:
387
0
    break;
388
389
366k
  case M68K_SIZE_TYPE_CPU:
390
366k
    switch (ext->op_size.cpu_size) {
391
113k
    case M68K_CPU_SIZE_BYTE:
392
113k
      SStream_concat0(O, ".b");
393
113k
      break;
394
97.8k
    case M68K_CPU_SIZE_WORD:
395
97.8k
      SStream_concat0(O, ".w");
396
97.8k
      break;
397
101k
    case M68K_CPU_SIZE_LONG:
398
101k
      SStream_concat0(O, ".l");
399
101k
      break;
400
53.2k
    case M68K_CPU_SIZE_NONE:
401
53.2k
      break;
402
366k
    }
403
366k
    break;
404
405
366k
  case M68K_SIZE_TYPE_FPU:
406
3.41k
    switch (ext->op_size.fpu_size) {
407
907
    case M68K_FPU_SIZE_SINGLE:
408
907
      SStream_concat0(O, ".s");
409
907
      break;
410
1.35k
    case M68K_FPU_SIZE_DOUBLE:
411
1.35k
      SStream_concat0(O, ".d");
412
1.35k
      break;
413
1.15k
    case M68K_FPU_SIZE_EXTENDED:
414
1.15k
      SStream_concat0(O, ".x");
415
1.15k
      break;
416
0
    case M68K_FPU_SIZE_NONE:
417
0
      break;
418
3.41k
    }
419
3.41k
    break;
420
369k
  }
421
422
369k
  SStream_concat0(O, " ");
423
424
  // this one is a bit spacial so we do special things
425
426
369k
  if (MI->Opcode == M68K_INS_CAS2) {
427
1.85k
    int reg_value_0, reg_value_1;
428
1.85k
    printAddressingMode(O, info->pc, ext, &ext->operands[0]);
429
1.85k
    SStream_concat0(O, ",");
430
1.85k
    printAddressingMode(O, info->pc, ext, &ext->operands[1]);
431
1.85k
    SStream_concat0(O, ",");
432
1.85k
    reg_value_0 = ext->operands[2].register_bits >> 4;
433
1.85k
    reg_value_1 = ext->operands[2].register_bits & 0xf;
434
1.85k
    SStream_concat(O, "(%s):(%s)",
435
1.85k
             s_reg_names[M68K_REG_D0 + reg_value_0],
436
1.85k
             s_reg_names[M68K_REG_D0 + reg_value_1]);
437
1.85k
    return;
438
1.85k
  }
439
440
1.02M
  for (i = 0; i < ext->op_count; ++i) {
441
658k
    printAddressingMode(O, info->pc, ext, &ext->operands[i]);
442
658k
    if ((i + 1) != ext->op_count)
443
292k
      SStream_concat(O, ",%s", s_spacing);
444
658k
  }
445
367k
#endif
446
367k
}
447
448
const char *M68K_reg_name(csh handle, unsigned int reg)
449
551k
{
450
#ifdef CAPSTONE_DIET
451
  return NULL;
452
#else
453
551k
  if (reg >= ARR_SIZE(s_reg_names)) {
454
0
    return NULL;
455
0
  }
456
551k
  return s_reg_names[(int)reg];
457
551k
#endif
458
551k
}
459
460
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
461
433k
{
462
433k
  insn->id = id; // These id's matches for 68k
463
433k
}
464
465
const char *M68K_insn_name(csh handle, unsigned int id)
466
433k
{
467
#ifdef CAPSTONE_DIET
468
  return NULL;
469
#else
470
433k
  return s_instruction_names[id];
471
433k
#endif
472
433k
}
473
474
#ifndef CAPSTONE_DIET
475
static const name_map group_name_maps[] = {
476
  { M68K_GRP_INVALID, NULL },
477
  { M68K_GRP_JUMP, "jump" },
478
  { M68K_GRP_RET, "ret" },
479
  { M68K_GRP_IRET, "iret" },
480
  { M68K_GRP_BRANCH_RELATIVE, "branch_relative" },
481
};
482
#endif
483
484
const char *M68K_group_name(csh handle, unsigned int id)
485
75.4k
{
486
75.4k
#ifndef CAPSTONE_DIET
487
75.4k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
488
#else
489
  return NULL;
490
#endif
491
75.4k
}
492
493
#ifndef CAPSTONE_DIET
494
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
495
         uint8_t *regs_read_count, cs_regs regs_write,
496
         uint8_t *regs_write_count)
497
0
{
498
0
  uint8_t read_count, write_count;
499
500
0
  read_count = insn->detail->regs_read_count;
501
0
  write_count = insn->detail->regs_write_count;
502
503
  // implicit registers
504
0
  memcpy(regs_read, insn->detail->regs_read,
505
0
         read_count * sizeof(insn->detail->regs_read[0]));
506
0
  memcpy(regs_write, insn->detail->regs_write,
507
0
         write_count * sizeof(insn->detail->regs_write[0]));
508
509
0
  *regs_read_count = read_count;
510
0
  *regs_write_count = write_count;
511
0
}
512
#endif