Coverage Report

Created: 2025-11-24 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/M68K/M68KDisassembler.c
Line
Count
Source
1
/* ======================================================================== */
2
/* ========================= LICENSING & COPYRIGHT ======================== */
3
/* ======================================================================== */
4
/*
5
 *                                  MUSASHI
6
 *                                Version 3.4
7
 *
8
 * A portable Motorola M680x0 processor emulation engine.
9
 * Copyright 1998-2001 Karl Stenerud.  All rights reserved.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 */
29
30
/* The code below is based on MUSASHI but has been heavily modified for Capstone by
31
 * Daniel Collin <daniel@collin.com> 2015-2019 */
32
33
/* ======================================================================== */
34
/* ================================ INCLUDES ============================== */
35
/* ======================================================================== */
36
37
#include <stdlib.h>
38
#include <stdio.h>
39
#include <string.h>
40
41
#include "../../cs_priv.h"
42
#include "../../utils.h"
43
44
#include "../../MCInst.h"
45
#include "../../MCInstrDesc.h"
46
#include "../../MCRegisterInfo.h"
47
#include "M68KInstPrinter.h"
48
#include "M68KDisassembler.h"
49
50
/* ======================================================================== */
51
/* ============================ GENERAL DEFINES =========================== */
52
/* ======================================================================== */
53
54
/* Bit Isolation Functions */
55
90
#define BIT_0(A)  ((A) & 0x00000001)
56
#define BIT_1(A)  ((A) & 0x00000002)
57
#define BIT_2(A)  ((A) & 0x00000004)
58
0
#define BIT_3(A)  ((A) & 0x00000008)
59
#define BIT_4(A)  ((A) & 0x00000010)
60
226
#define BIT_5(A)  ((A) & 0x00000020)
61
646
#define BIT_6(A)  ((A) & 0x00000040)
62
646
#define BIT_7(A)  ((A) & 0x00000080)
63
1.27k
#define BIT_8(A)  ((A) & 0x00000100)
64
#define BIT_9(A)  ((A) & 0x00000200)
65
169
#define BIT_A(A)  ((A) & 0x00000400)
66
1.94k
#define BIT_B(A)  ((A) & 0x00000800)
67
#define BIT_C(A)  ((A) & 0x00001000)
68
#define BIT_D(A)  ((A) & 0x00002000)
69
#define BIT_E(A)  ((A) & 0x00004000)
70
1.52k
#define BIT_F(A)  ((A) & 0x00008000)
71
#define BIT_10(A) ((A) & 0x00010000)
72
#define BIT_11(A) ((A) & 0x00020000)
73
#define BIT_12(A) ((A) & 0x00040000)
74
#define BIT_13(A) ((A) & 0x00080000)
75
#define BIT_14(A) ((A) & 0x00100000)
76
#define BIT_15(A) ((A) & 0x00200000)
77
#define BIT_16(A) ((A) & 0x00400000)
78
#define BIT_17(A) ((A) & 0x00800000)
79
#define BIT_18(A) ((A) & 0x01000000)
80
#define BIT_19(A) ((A) & 0x02000000)
81
#define BIT_1A(A) ((A) & 0x04000000)
82
#define BIT_1B(A) ((A) & 0x08000000)
83
#define BIT_1C(A) ((A) & 0x10000000)
84
#define BIT_1D(A) ((A) & 0x20000000)
85
#define BIT_1E(A) ((A) & 0x40000000)
86
16
#define BIT_1F(A) ((A) & 0x80000000)
87
88
/* These are the CPU types understood by this disassembler */
89
6.23k
#define TYPE_68000 1
90
0
#define TYPE_68010 2
91
0
#define TYPE_68020 4
92
0
#define TYPE_68030 8
93
15.5k
#define TYPE_68040 16
94
95
#define M68000_ONLY   TYPE_68000
96
97
#define M68010_ONLY   TYPE_68010
98
#define M68010_LESS   (TYPE_68000 | TYPE_68010)
99
#define M68010_PLUS   (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040)
100
101
#define M68020_ONLY   TYPE_68020
102
#define M68020_LESS   (TYPE_68010 | TYPE_68020)
103
#define M68020_PLUS   (TYPE_68020 | TYPE_68030 | TYPE_68040)
104
105
#define M68030_ONLY   TYPE_68030
106
#define M68030_LESS   (TYPE_68010 | TYPE_68020 | TYPE_68030)
107
#define M68030_PLUS   (TYPE_68030 | TYPE_68040)
108
109
#define M68040_PLUS   TYPE_68040
110
111
enum {
112
  M68K_CPU_TYPE_INVALID,
113
  M68K_CPU_TYPE_68000,
114
  M68K_CPU_TYPE_68010,
115
  M68K_CPU_TYPE_68EC020,
116
  M68K_CPU_TYPE_68020,
117
  M68K_CPU_TYPE_68030,  /* Supported by disassembler ONLY */
118
  M68K_CPU_TYPE_68040   /* Supported by disassembler ONLY */
119
};
120
121
/* Extension word formats */
122
633
#define EXT_8BIT_DISPLACEMENT(A)          ((A)&0xff)
123
1.27k
#define EXT_FULL(A)                       BIT_8(A)
124
#define EXT_EFFECTIVE_ZERO(A)             (((A)&0xe4) == 0xc4 || ((A)&0xe2) == 0xc0)
125
646
#define EXT_BASE_REGISTER_PRESENT(A)      (!BIT_7(A))
126
646
#define EXT_INDEX_REGISTER_PRESENT(A)     (!BIT_6(A))
127
1.15k
#define EXT_INDEX_REGISTER(A)             (((A)>>12)&7)
128
#define EXT_INDEX_PRE_POST(A)             (EXT_INDEX_PRESENT(A) && (A)&3)
129
#define EXT_INDEX_PRE(A)                  (EXT_INDEX_PRESENT(A) && ((A)&7) < 4 && ((A)&7) != 0)
130
#define EXT_INDEX_POST(A)                 (EXT_INDEX_PRESENT(A) && ((A)&7) > 4)
131
1.86k
#define EXT_INDEX_SCALE(A)                (((A)>>9)&3)
132
1.15k
#define EXT_INDEX_LONG(A)                 BIT_B(A)
133
1.15k
#define EXT_INDEX_AR(A)                   BIT_F(A)
134
646
#define EXT_BASE_DISPLACEMENT_PRESENT(A)  (((A)&0x30) > 0x10)
135
#define EXT_BASE_DISPLACEMENT_WORD(A)     (((A)&0x30) == 0x20)
136
190
#define EXT_BASE_DISPLACEMENT_LONG(A)     (((A)&0x30) == 0x30)
137
646
#define EXT_OUTER_DISPLACEMENT_PRESENT(A) (((A)&3) > 1 && ((A)&0x47) < 0x44)
138
#define EXT_OUTER_DISPLACEMENT_WORD(A)    (((A)&3) == 2 && ((A)&0x47) < 0x44)
139
200
#define EXT_OUTER_DISPLACEMENT_LONG(A)    (((A)&3) == 3 && ((A)&0x47) < 0x44)
140
141
#define IS_BITSET(val,b) ((val) & (1 << (b)))
142
1.85k
#define BITFIELD_MASK(sb,eb)  (((1 << ((sb) + 1))-1) & (~((1 << (eb))-1)))
143
1.85k
#define BITFIELD(val,sb,eb) ((BITFIELD_MASK(sb,eb) & (val)) >> (eb))
144
145
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146
147
static unsigned int m68k_read_disassembler_16(const m68k_info *info, const uint64_t addr)
148
52.5k
{
149
52.5k
  const uint16_t v0 = info->code[addr + 0];
150
52.5k
  const uint16_t v1 = info->code[addr + 1];
151
52.5k
  return (v0 << 8) | v1;
152
52.5k
}
153
154
static unsigned int m68k_read_disassembler_32(const m68k_info *info, const uint64_t addr)
155
22.3k
{
156
22.3k
  const uint32_t v0 = info->code[addr + 0];
157
22.3k
  const uint32_t v1 = info->code[addr + 1];
158
22.3k
  const uint32_t v2 = info->code[addr + 2];
159
22.3k
  const uint32_t v3 = info->code[addr + 3];
160
22.3k
  return (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
161
22.3k
}
162
163
static uint64_t m68k_read_disassembler_64(const m68k_info *info, const uint64_t addr)
164
18
{
165
18
  const uint64_t v0 = info->code[addr + 0];
166
18
  const uint64_t v1 = info->code[addr + 1];
167
18
  const uint64_t v2 = info->code[addr + 2];
168
18
  const uint64_t v3 = info->code[addr + 3];
169
18
  const uint64_t v4 = info->code[addr + 4];
170
18
  const uint64_t v5 = info->code[addr + 5];
171
18
  const uint64_t v6 = info->code[addr + 6];
172
18
  const uint64_t v7 = info->code[addr + 7];
173
18
  return (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) | (v5 << 16) | (v6 << 8) | v7;
174
18
}
175
176
static unsigned int m68k_read_safe_16(const m68k_info *info, const uint64_t address)
177
52.6k
{
178
52.6k
  const uint64_t addr = (address - info->baseAddress) & info->address_mask;
179
52.6k
  if (info->code_len < addr + 2) {
180
106
    return 0xaaaa;
181
106
  }
182
52.5k
  return m68k_read_disassembler_16(info, addr);
183
52.6k
}
184
185
static unsigned int m68k_read_safe_32(const m68k_info *info, const uint64_t address)
186
22.6k
{
187
22.6k
  const uint64_t addr = (address - info->baseAddress) & info->address_mask;
188
22.6k
  if (info->code_len < addr + 4) {
189
320
    return 0xaaaaaaaa;
190
320
  }
191
22.3k
  return m68k_read_disassembler_32(info, addr);
192
22.6k
}
193
194
static uint64_t m68k_read_safe_64(const m68k_info *info, const uint64_t address)
195
18
{
196
18
  const uint64_t addr = (address - info->baseAddress) & info->address_mask;
197
18
  if (info->code_len < addr + 8) {
198
0
    return 0xaaaaaaaaaaaaaaaaLL;
199
0
  }
200
18
  return m68k_read_disassembler_64(info, addr);
201
18
}
202
203
/* ======================================================================== */
204
/* =============================== PROTOTYPES ============================= */
205
/* ======================================================================== */
206
207
/* make signed integers 100% portably */
208
static int make_int_8(int value);
209
static int make_int_16(int value);
210
211
/* Stuff to build the opcode handler jump table */
212
static void d68000_invalid(m68k_info *info);
213
static int instruction_is_valid(m68k_info *info, const unsigned int word_check);
214
215
typedef struct {
216
  void (*instruction)(m68k_info *info);   /* handler function */
217
  uint16_t word2_mask;                  /* mask the 2nd word */
218
  uint16_t word2_match;                 /* what to match after masking */
219
} instruction_struct;
220
221
/* ======================================================================== */
222
/* ================================= DATA ================================= */
223
/* ======================================================================== */
224
225
static const instruction_struct g_instruction_table[0x10000];
226
227
/* used by ops like asr, ror, addq, etc */
228
static const uint32_t g_3bit_qdata_table[8] = {8, 1, 2, 3, 4, 5, 6, 7};
229
230
static const uint32_t g_5bit_data_table[32] = {
231
  32,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
232
  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
233
};
234
235
static const m68k_insn s_branch_lut[] = {
236
  M68K_INS_INVALID, M68K_INS_INVALID, M68K_INS_BHI, M68K_INS_BLS,
237
  M68K_INS_BCC, M68K_INS_BCS, M68K_INS_BNE, M68K_INS_BEQ,
238
  M68K_INS_BVC, M68K_INS_BVS, M68K_INS_BPL, M68K_INS_BMI,
239
  M68K_INS_BGE, M68K_INS_BLT, M68K_INS_BGT, M68K_INS_BLE,
240
};
241
242
static const m68k_insn s_dbcc_lut[] = {
243
  M68K_INS_DBT, M68K_INS_DBF, M68K_INS_DBHI, M68K_INS_DBLS,
244
  M68K_INS_DBCC, M68K_INS_DBCS, M68K_INS_DBNE, M68K_INS_DBEQ,
245
  M68K_INS_DBVC, M68K_INS_DBVS, M68K_INS_DBPL, M68K_INS_DBMI,
246
  M68K_INS_DBGE, M68K_INS_DBLT, M68K_INS_DBGT, M68K_INS_DBLE,
247
};
248
249
static const m68k_insn s_scc_lut[] = {
250
  M68K_INS_ST, M68K_INS_SF, M68K_INS_SHI, M68K_INS_SLS,
251
  M68K_INS_SCC, M68K_INS_SCS, M68K_INS_SNE, M68K_INS_SEQ,
252
  M68K_INS_SVC, M68K_INS_SVS, M68K_INS_SPL, M68K_INS_SMI,
253
  M68K_INS_SGE, M68K_INS_SLT, M68K_INS_SGT, M68K_INS_SLE,
254
};
255
256
static const m68k_insn s_trap_lut[] = {
257
  M68K_INS_TRAPT, M68K_INS_TRAPF, M68K_INS_TRAPHI, M68K_INS_TRAPLS,
258
  M68K_INS_TRAPCC, M68K_INS_TRAPCS, M68K_INS_TRAPNE, M68K_INS_TRAPEQ,
259
  M68K_INS_TRAPVC, M68K_INS_TRAPVS, M68K_INS_TRAPPL, M68K_INS_TRAPMI,
260
  M68K_INS_TRAPGE, M68K_INS_TRAPLT, M68K_INS_TRAPGT, M68K_INS_TRAPLE,
261
};
262
263
/* ======================================================================== */
264
/* =========================== UTILITY FUNCTIONS ========================== */
265
/* ======================================================================== */
266
267
#define LIMIT_CPU_TYPES(info, ALLOWED_CPU_TYPES)  \
268
5.50k
  do {           \
269
5.50k
    if (!(info->type & ALLOWED_CPU_TYPES)) { \
270
940
      d68000_invalid(info);   \
271
940
      return;       \
272
940
    }          \
273
5.50k
  } while (0)
274
275
1.46k
static unsigned int peek_imm_8(const m68k_info *info)  { return (m68k_read_safe_16((info), (info)->pc)&0xff); }
276
51.1k
static unsigned int peek_imm_16(const m68k_info *info) { return m68k_read_safe_16((info), (info)->pc); }
277
22.6k
static unsigned int peek_imm_32(const m68k_info *info) { return m68k_read_safe_32((info), (info)->pc); }
278
18
static unsigned long long peek_imm_64(const m68k_info *info) { return m68k_read_safe_64((info), (info)->pc); }
279
280
1.46k
static unsigned int read_imm_8(m68k_info *info)  { const unsigned int value = peek_imm_8(info);  (info)->pc+=2; return value; }
281
29.4k
static unsigned int read_imm_16(m68k_info *info) { const unsigned int value = peek_imm_16(info); (info)->pc+=2; return value; }
282
852
static unsigned int read_imm_32(m68k_info *info) { const unsigned int value = peek_imm_32(info); (info)->pc+=4; return value; }
283
18
static unsigned long long read_imm_64(m68k_info *info) { const unsigned long long value = peek_imm_64(info); (info)->pc+=8; return value; }
284
285
/* Fake a split interface */
286
#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0)
287
#define get_ea_mode_str_16(instruction) get_ea_mode_str(instruction, 1)
288
#define get_ea_mode_str_32(instruction) get_ea_mode_str(instruction, 2)
289
290
#define get_imm_str_s8() get_imm_str_s(0)
291
#define get_imm_str_s16() get_imm_str_s(1)
292
#define get_imm_str_s32() get_imm_str_s(2)
293
294
#define get_imm_str_u8() get_imm_str_u(0)
295
#define get_imm_str_u16() get_imm_str_u(1)
296
#define get_imm_str_u32() get_imm_str_u(2)
297
298
299
/* 100% portable signed int generators */
300
static int make_int_8(int value)
301
1.07k
{
302
1.07k
  return (value & 0x80) ? value | ~0xff : value & 0xff;
303
1.07k
}
304
305
static int make_int_16(int value)
306
434
{
307
434
  return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
308
434
}
309
310
static void get_with_index_address_mode(m68k_info *info, cs_m68k_op* op, uint32_t instruction, uint32_t size, bool is_pc)
311
1.27k
{
312
1.27k
  uint32_t extension = read_imm_16(info);
313
314
1.27k
  op->address_mode = M68K_AM_AREGI_INDEX_BASE_DISP;
315
316
1.27k
  if (EXT_FULL(extension)) {
317
646
    uint32_t preindex;
318
646
    uint32_t postindex;
319
320
646
    op->mem.base_reg = M68K_REG_INVALID;
321
646
    op->mem.index_reg = M68K_REG_INVALID;
322
323
    /* Not sure how to deal with this?
324
       if (EXT_EFFECTIVE_ZERO(extension)) {
325
       strcpy(mode, "0");
326
       break;
327
       }
328
     */
329
330
646
    op->mem.in_disp = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32(info) : read_imm_16(info)) : 0;
331
646
    op->mem.out_disp = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32(info) : read_imm_16(info)) : 0;
332
333
646
    if (EXT_BASE_REGISTER_PRESENT(extension)) {
334
470
      if (is_pc) {
335
164
        op->mem.base_reg = M68K_REG_PC;
336
306
      } else {
337
306
        op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
338
306
      }
339
470
    }
340
341
646
    if (EXT_INDEX_REGISTER_PRESENT(extension)) {
342
518
      if (EXT_INDEX_AR(extension)) {
343
53
        op->mem.index_reg = M68K_REG_A0 + EXT_INDEX_REGISTER(extension);
344
465
      } else {
345
465
        op->mem.index_reg = M68K_REG_D0 + EXT_INDEX_REGISTER(extension);
346
465
      }
347
348
518
      op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
349
350
518
      if (EXT_INDEX_SCALE(extension)) {
351
333
        op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
352
333
      }
353
518
    }
354
355
646
    preindex = (extension & 7) > 0 && (extension & 7) < 4;
356
646
    postindex = (extension & 7) > 4;
357
358
646
    if (preindex) {
359
301
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_PRE_INDEX : M68K_AM_MEMI_PRE_INDEX;
360
345
    } else if (postindex) {
361
78
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_POST_INDEX : M68K_AM_MEMI_POST_INDEX;
362
78
    }
363
364
646
    return;
365
646
  }
366
367
633
  op->mem.index_reg = (EXT_INDEX_AR(extension) ? M68K_REG_A0 : M68K_REG_D0) + EXT_INDEX_REGISTER(extension);
368
633
  op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
369
370
633
  if (EXT_8BIT_DISPLACEMENT(extension) == 0) {
371
115
    if (is_pc) {
372
0
      op->mem.base_reg = M68K_REG_PC;
373
0
      op->address_mode = M68K_AM_PCI_INDEX_BASE_DISP;
374
115
    } else {
375
115
      op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
376
115
    }
377
518
  } else {
378
518
    if (is_pc) {
379
52
      op->mem.base_reg = M68K_REG_PC;
380
52
      op->address_mode = M68K_AM_PCI_INDEX_8_BIT_DISP;
381
466
    } else {
382
466
      op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
383
466
      op->address_mode = M68K_AM_AREGI_INDEX_8_BIT_DISP;
384
466
    }
385
386
518
    op->mem.disp = (int8_t)(extension & 0xff);
387
518
  }
388
389
633
  if (EXT_INDEX_SCALE(extension)) {
390
383
    op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
391
383
  }
392
633
}
393
394
/* Make string of effective address mode */
395
static void get_ea_mode_op(m68k_info *info, cs_m68k_op* op, uint32_t instruction, uint32_t size)
396
14.2k
{
397
  // default to memory
398
399
14.2k
  op->type = M68K_OP_MEM;
400
401
14.2k
  switch (instruction & 0x3f) {
402
3.95k
    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
403
      /* data register direct */
404
3.95k
      op->address_mode = M68K_AM_REG_DIRECT_DATA;
405
3.95k
      op->reg = M68K_REG_D0 + (instruction & 7);
406
3.95k
      op->type = M68K_OP_REG;
407
3.95k
      break;
408
409
811
    case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
410
      /* address register direct */
411
811
      op->address_mode = M68K_AM_REG_DIRECT_ADDR;
412
811
      op->reg = M68K_REG_A0 + (instruction & 7);
413
811
      op->type = M68K_OP_REG;
414
811
      break;
415
416
2.12k
    case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
417
      /* address register indirect */
418
2.12k
      op->address_mode = M68K_AM_REGI_ADDR;
419
2.12k
      op->reg = M68K_REG_A0 + (instruction & 7);
420
2.12k
      break;
421
422
1.29k
    case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
423
      /* address register indirect with postincrement */
424
1.29k
      op->address_mode = M68K_AM_REGI_ADDR_POST_INC;
425
1.29k
      op->reg = M68K_REG_A0 + (instruction & 7);
426
1.29k
      break;
427
428
3.05k
    case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
429
      /* address register indirect with predecrement */
430
3.05k
      op->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
431
3.05k
      op->reg = M68K_REG_A0 + (instruction & 7);
432
3.05k
      break;
433
434
773
    case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
435
      /* address register indirect with displacement*/
436
773
      op->address_mode = M68K_AM_REGI_ADDR_DISP;
437
773
      op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
438
773
      op->mem.disp = (int16_t)read_imm_16(info);
439
773
      break;
440
441
949
    case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
442
      /* address register indirect with index */
443
949
      get_with_index_address_mode(info, op, instruction, size, false);
444
949
      break;
445
446
81
    case 0x38:
447
      /* absolute short address */
448
81
      op->address_mode = M68K_AM_ABSOLUTE_DATA_SHORT;
449
81
      op->imm = read_imm_16(info);
450
81
      break;
451
452
46
    case 0x39:
453
      /* absolute long address */
454
46
      op->address_mode = M68K_AM_ABSOLUTE_DATA_LONG;
455
46
      op->imm = read_imm_32(info);
456
46
      break;
457
458
407
    case 0x3a:
459
      /* program counter with displacement */
460
407
      op->address_mode = M68K_AM_PCI_DISP;
461
407
      op->mem.disp = (int16_t)read_imm_16(info);
462
407
      break;
463
464
330
    case 0x3b:
465
      /* program counter with index */
466
330
      get_with_index_address_mode(info, op, instruction, size, true);
467
330
      break;
468
469
458
    case 0x3c:
470
458
      op->address_mode = M68K_AM_IMMEDIATE;
471
458
      op->type = M68K_OP_IMM;
472
473
458
      if (size == 1)
474
6
        op->imm = read_imm_8(info) & 0xff;
475
452
      else if (size == 2)
476
426
        op->imm = read_imm_16(info) & 0xffff;
477
26
      else if (size == 4)
478
8
        op->imm = read_imm_32(info);
479
18
      else
480
18
        op->imm = read_imm_64(info);
481
482
458
      break;
483
484
6
    default:
485
6
      break;
486
14.2k
  }
487
14.2k
}
488
489
static void set_insn_group(m68k_info *info, m68k_group_type group)
490
4.24k
{
491
4.24k
  info->groups[info->groups_count++] = (uint8_t)group;
492
4.24k
}
493
494
static cs_m68k* build_init_op(m68k_info *info, int opcode, int count, int size)
495
20.0k
{
496
20.0k
  cs_m68k* ext;
497
498
20.0k
  MCInst_setOpcode(info->inst, opcode);
499
500
20.0k
  ext = &info->extension;
501
502
20.0k
  ext->op_count = (uint8_t)count;
503
20.0k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
504
20.0k
  ext->op_size.cpu_size = size;
505
506
20.0k
  return ext;
507
20.0k
}
508
509
static void build_re_gen_1(m68k_info *info, bool isDreg, int opcode, uint8_t size)
510
1.52k
{
511
1.52k
  cs_m68k_op* op0;
512
1.52k
  cs_m68k_op* op1;
513
1.52k
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
514
515
1.52k
  op0 = &ext->operands[0];
516
1.52k
  op1 = &ext->operands[1];
517
518
1.52k
  if (isDreg) {
519
1.52k
    op0->address_mode = M68K_AM_REG_DIRECT_DATA;
520
1.52k
    op0->reg = M68K_REG_D0 + ((info->ir >> 9 ) & 7);
521
1.52k
  } else {
522
0
    op0->address_mode = M68K_AM_REG_DIRECT_ADDR;
523
0
    op0->reg = M68K_REG_A0 + ((info->ir >> 9 ) & 7);
524
0
  }
525
526
1.52k
  get_ea_mode_op(info, op1, info->ir, size);
527
1.52k
}
528
529
static void build_re_1(m68k_info *info, int opcode, uint8_t size)
530
1.52k
{
531
1.52k
  build_re_gen_1(info, true, opcode, size);
532
1.52k
}
533
534
static void build_er_gen_1(m68k_info *info, bool isDreg, int opcode, uint8_t size)
535
1.41k
{
536
1.41k
  cs_m68k_op* op0;
537
1.41k
  cs_m68k_op* op1;
538
1.41k
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
539
540
1.41k
  op0 = &ext->operands[0];
541
1.41k
  op1 = &ext->operands[1];
542
543
1.41k
  get_ea_mode_op(info, op0, info->ir, size);
544
545
1.41k
  if (isDreg) {
546
1.41k
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
547
1.41k
    op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
548
1.41k
  } else {
549
0
    op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
550
0
    op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
551
0
  }
552
1.41k
}
553
554
static void build_rr(m68k_info *info, int opcode, uint8_t size, int imm)
555
677
{
556
677
  cs_m68k_op* op0;
557
677
  cs_m68k_op* op1;
558
677
  cs_m68k_op* op2;
559
677
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
560
561
677
  op0 = &ext->operands[0];
562
677
  op1 = &ext->operands[1];
563
677
  op2 = &ext->operands[2];
564
565
677
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
566
677
  op0->reg = M68K_REG_D0 + (info->ir & 7);
567
568
677
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
569
677
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
570
571
677
  if (imm > 0) {
572
41
    ext->op_count = 3;
573
41
    op2->type = M68K_OP_IMM;
574
41
    op2->address_mode = M68K_AM_IMMEDIATE;
575
41
    op2->imm = imm;
576
41
  }
577
677
}
578
579
static void build_r(m68k_info *info, int opcode, uint8_t size)
580
691
{
581
691
  cs_m68k_op* op0;
582
691
  cs_m68k_op* op1;
583
691
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
584
585
691
  op0 = &ext->operands[0];
586
691
  op1 = &ext->operands[1];
587
588
691
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
589
691
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
590
591
691
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
592
691
  op1->reg = M68K_REG_D0 + (info->ir & 7);
593
691
}
594
595
static void build_imm_ea(m68k_info *info, int opcode, uint8_t size, int imm)
596
2.14k
{
597
2.14k
  cs_m68k_op* op0;
598
2.14k
  cs_m68k_op* op1;
599
2.14k
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
600
601
2.14k
  op0 = &ext->operands[0];
602
2.14k
  op1 = &ext->operands[1];
603
604
2.14k
  op0->type = M68K_OP_IMM;
605
2.14k
  op0->address_mode = M68K_AM_IMMEDIATE;
606
2.14k
  op0->imm = imm;
607
608
2.14k
  get_ea_mode_op(info, op1, info->ir, size);
609
2.14k
}
610
611
static void build_3bit_d(m68k_info *info, int opcode, int size)
612
815
{
613
815
  cs_m68k_op* op0;
614
815
  cs_m68k_op* op1;
615
815
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
616
617
815
  op0 = &ext->operands[0];
618
815
  op1 = &ext->operands[1];
619
620
815
  op0->type = M68K_OP_IMM;
621
815
  op0->address_mode = M68K_AM_IMMEDIATE;
622
815
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
623
624
815
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
625
815
  op1->reg = M68K_REG_D0 + (info->ir & 7);
626
815
}
627
628
static void build_3bit_ea(m68k_info *info, int opcode, int size)
629
617
{
630
617
  cs_m68k_op* op0;
631
617
  cs_m68k_op* op1;
632
617
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
633
634
617
  op0 = &ext->operands[0];
635
617
  op1 = &ext->operands[1];
636
637
617
  op0->type = M68K_OP_IMM;
638
617
  op0->address_mode = M68K_AM_IMMEDIATE;
639
617
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
640
641
617
  get_ea_mode_op(info, op1, info->ir, size);
642
617
}
643
644
static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm)
645
332
{
646
332
  cs_m68k_op* op0;
647
332
  cs_m68k_op* op1;
648
332
  cs_m68k_op* op2;
649
332
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
650
651
332
  op0 = &ext->operands[0];
652
332
  op1 = &ext->operands[1];
653
332
  op2 = &ext->operands[2];
654
655
332
  op0->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
656
332
  op0->reg = M68K_REG_A0 + (info->ir & 7);
657
658
332
  op1->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
659
332
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
660
661
332
  if (imm > 0) {
662
132
    ext->op_count = 3;
663
132
    op2->type = M68K_OP_IMM;
664
132
    op2->address_mode = M68K_AM_IMMEDIATE;
665
132
    op2->imm = imm;
666
132
  }
667
332
}
668
669
static void build_ea(m68k_info *info, int opcode, uint8_t size)
670
1.49k
{
671
1.49k
  cs_m68k* ext = build_init_op(info, opcode, 1, size);
672
1.49k
  get_ea_mode_op(info, &ext->operands[0], info->ir, size);
673
1.49k
}
674
675
static void build_ea_a(m68k_info *info, int opcode, uint8_t size)
676
982
{
677
982
  cs_m68k_op* op0;
678
982
  cs_m68k_op* op1;
679
982
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
680
681
982
  op0 = &ext->operands[0];
682
982
  op1 = &ext->operands[1];
683
684
982
  get_ea_mode_op(info, op0, info->ir, size);
685
686
982
  op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
687
982
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
688
982
}
689
690
static void build_ea_ea(m68k_info *info, int opcode, int size)
691
1.82k
{
692
1.82k
  cs_m68k_op* op0;
693
1.82k
  cs_m68k_op* op1;
694
1.82k
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
695
696
1.82k
  op0 = &ext->operands[0];
697
1.82k
  op1 = &ext->operands[1];
698
699
1.82k
  get_ea_mode_op(info, op0, info->ir, size);
700
1.82k
  get_ea_mode_op(info, op1, (((info->ir>>9) & 7) | ((info->ir>>3) & 0x38)), size);
701
1.82k
}
702
703
static void build_pi_pi(m68k_info *info, int opcode, int size)
704
8
{
705
8
  cs_m68k_op* op0;
706
8
  cs_m68k_op* op1;
707
8
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
708
709
8
  op0 = &ext->operands[0];
710
8
  op1 = &ext->operands[1];
711
712
8
  op0->address_mode = M68K_AM_REGI_ADDR_POST_INC;
713
8
  op0->reg = M68K_REG_A0 + (info->ir & 7);
714
715
8
  op1->address_mode = M68K_AM_REGI_ADDR_POST_INC;
716
8
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
717
8
}
718
719
static void build_imm_special_reg(m68k_info *info, int opcode, int imm, int size, m68k_reg reg)
720
6
{
721
6
  cs_m68k_op* op0;
722
6
  cs_m68k_op* op1;
723
6
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
724
725
6
  op0 = &ext->operands[0];
726
6
  op1 = &ext->operands[1];
727
728
6
  op0->type = M68K_OP_IMM;
729
6
  op0->address_mode = M68K_AM_IMMEDIATE;
730
6
  op0->imm = imm;
731
732
6
  op1->address_mode = M68K_AM_NONE;
733
6
  op1->reg = reg;
734
6
}
735
736
static void build_relative_branch(m68k_info *info, int opcode, int size, int displacement)
737
1.13k
{
738
1.13k
  cs_m68k_op* op;
739
1.13k
  cs_m68k* ext = build_init_op(info, opcode, 1, size);
740
741
1.13k
  op = &ext->operands[0];
742
743
1.13k
  op->type = M68K_OP_BR_DISP;
744
1.13k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
745
1.13k
  op->br_disp.disp = displacement;
746
1.13k
  op->br_disp.disp_size = size;
747
748
1.13k
  set_insn_group(info, M68K_GRP_JUMP);
749
1.13k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
750
1.13k
}
751
752
static void build_absolute_jump_with_immediate(m68k_info *info, int opcode, int size, int immediate)
753
990
{
754
990
  cs_m68k_op* op;
755
990
  cs_m68k* ext = build_init_op(info, opcode, 1, size);
756
757
990
  op = &ext->operands[0];
758
759
990
  op->type = M68K_OP_IMM;
760
990
  op->address_mode = M68K_AM_IMMEDIATE;
761
990
  op->imm = immediate;
762
763
990
  set_insn_group(info, M68K_GRP_JUMP);
764
990
}
765
766
static void build_bcc(m68k_info *info, int size, int displacement)
767
865
{
768
865
  build_relative_branch(info, s_branch_lut[(info->ir >> 8) & 0xf], size, displacement);
769
865
}
770
771
static void build_trap(m68k_info *info, int size, int immediate)
772
51
{
773
51
  build_absolute_jump_with_immediate(info, s_trap_lut[(info->ir >> 8) & 0xf], size, immediate);
774
51
}
775
776
static void build_dbxx(m68k_info *info, int opcode, int size, int displacement)
777
33
{
778
33
  cs_m68k_op* op0;
779
33
  cs_m68k_op* op1;
780
33
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
781
782
33
  op0 = &ext->operands[0];
783
33
  op1 = &ext->operands[1];
784
785
33
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
786
33
  op0->reg = M68K_REG_D0 + (info->ir & 7);
787
788
33
  op1->type = M68K_OP_BR_DISP;
789
33
  op1->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
790
33
  op1->br_disp.disp = displacement;
791
33
  op1->br_disp.disp_size = M68K_OP_BR_DISP_SIZE_LONG;
792
793
33
  set_insn_group(info, M68K_GRP_JUMP);
794
33
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
795
33
}
796
797
static void build_dbcc(m68k_info *info, int size, int displacement)
798
11
{
799
11
  build_dbxx(info, s_dbcc_lut[(info->ir >> 8) & 0xf], size, displacement);
800
11
}
801
802
static void build_d_d_ea(m68k_info *info, int opcode, int size)
803
22
{
804
22
  cs_m68k_op* op0;
805
22
  cs_m68k_op* op1;
806
22
  cs_m68k_op* op2;
807
22
  uint32_t extension = read_imm_16(info);
808
22
  cs_m68k* ext = build_init_op(info, opcode, 3, size);
809
810
22
  op0 = &ext->operands[0];
811
22
  op1 = &ext->operands[1];
812
22
  op2 = &ext->operands[2];
813
814
22
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
815
22
  op0->reg = M68K_REG_D0 + (extension & 7);
816
817
22
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
818
22
  op1->reg = M68K_REG_D0 + ((extension >> 6) & 7);
819
820
22
  get_ea_mode_op(info, op2, info->ir, size);
821
22
}
822
823
static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg)
824
226
{
825
226
  uint8_t offset;
826
226
  uint8_t width;
827
226
  cs_m68k_op* op_ea;
828
226
  cs_m68k_op* op1;
829
226
  cs_m68k* ext = build_init_op(info, opcode, 1, 0);
830
226
  uint32_t extension = read_imm_16(info);
831
832
226
  op_ea = &ext->operands[0];
833
226
  op1 = &ext->operands[1];
834
835
226
  if (BIT_B(extension))
836
110
    offset = (extension >> 6) & 7;
837
116
  else
838
116
    offset = (extension >> 6) & 31;
839
840
226
  if (BIT_5(extension))
841
136
    width = extension & 7;
842
90
  else
843
90
    width = (uint8_t)g_5bit_data_table[extension & 31];
844
845
226
  if (has_d_arg) {
846
127
    ext->op_count = 2;
847
127
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
848
127
    op1->reg = M68K_REG_D0 + ((extension >> 12) & 7);
849
127
  }
850
851
226
  get_ea_mode_op(info, op_ea, info->ir, 1);
852
853
226
  op_ea->mem.bitfield = 1;
854
226
  op_ea->mem.width = width;
855
226
  op_ea->mem.offset = offset;
856
226
}
857
858
static void build_d(m68k_info *info, int opcode, int size)
859
201
{
860
201
  cs_m68k* ext = build_init_op(info, opcode, 1, size);
861
201
  cs_m68k_op* op;
862
863
201
  op = &ext->operands[0];
864
865
201
  op->address_mode = M68K_AM_REG_DIRECT_DATA;
866
201
  op->reg = M68K_REG_D0 + (info->ir & 7);
867
201
}
868
869
static uint16_t reverse_bits(uint32_t v)
870
40
{
871
40
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
872
40
  uint32_t s = 16 - 1; // extra shift needed at end
873
874
609
  for (v >>= 1; v; v >>= 1) {
875
569
    r <<= 1;
876
569
    r |= v & 1;
877
569
    s--;
878
569
  }
879
880
40
  return r <<= s; // shift when v's highest bits are zero
881
40
}
882
883
static uint8_t reverse_bits_8(uint32_t v)
884
46
{
885
46
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
886
46
  uint32_t s = 8 - 1; // extra shift needed at end
887
888
276
  for (v >>= 1; v; v >>= 1) {
889
230
    r <<= 1;
890
230
    r |= v & 1;
891
230
    s--;
892
230
  }
893
894
46
  return r <<= s; // shift when v's highest bits are zero
895
46
}
896
897
898
static void build_movem_re(m68k_info *info, int opcode, int size)
899
169
{
900
169
  cs_m68k_op* op0;
901
169
  cs_m68k_op* op1;
902
169
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
903
904
169
  op0 = &ext->operands[0];
905
169
  op1 = &ext->operands[1];
906
907
169
  op0->type = M68K_OP_REG_BITS;
908
169
  op0->register_bits = read_imm_16(info);
909
910
169
  get_ea_mode_op(info, op1, info->ir, size);
911
912
169
  if (op1->address_mode == M68K_AM_REGI_ADDR_PRE_DEC)
913
40
    op0->register_bits = reverse_bits(op0->register_bits);
914
169
}
915
916
static void build_movem_er(m68k_info *info, int opcode, int size)
917
107
{
918
107
  cs_m68k_op* op0;
919
107
  cs_m68k_op* op1;
920
107
  cs_m68k* ext = build_init_op(info, opcode, 2, size);
921
922
107
  op0 = &ext->operands[0];
923
107
  op1 = &ext->operands[1];
924
925
107
  op1->type = M68K_OP_REG_BITS;
926
107
  op1->register_bits = read_imm_16(info);
927
928
107
  get_ea_mode_op(info, op0, info->ir, size);
929
107
}
930
931
static void build_imm(m68k_info *info, int opcode, int data)
932
1.73k
{
933
1.73k
  cs_m68k_op* op;
934
1.73k
  cs_m68k* ext = build_init_op(info, opcode, 1, 0);
935
936
1.73k
  MCInst_setOpcode(info->inst, opcode);
937
938
1.73k
  op = &ext->operands[0];
939
940
1.73k
  op->type = M68K_OP_IMM;
941
1.73k
  op->address_mode = M68K_AM_IMMEDIATE;
942
1.73k
  op->imm = data;
943
1.73k
}
944
945
static void build_illegal(m68k_info *info, int data)
946
16
{
947
16
  build_imm(info, M68K_INS_ILLEGAL, data);
948
16
}
949
950
static void build_invalid(m68k_info *info, int data)
951
1.72k
{
952
1.72k
  build_imm(info, M68K_INS_INVALID, data);
953
1.72k
}
954
955
static void build_cas2(m68k_info *info, int size)
956
20
{
957
20
  uint32_t word3;
958
20
  uint32_t extension;
959
20
  cs_m68k_op* op0;
960
20
  cs_m68k_op* op1;
961
20
  cs_m68k_op* op2;
962
20
  cs_m68k* ext = build_init_op(info, M68K_INS_CAS2, 3, size);
963
20
  int reg_0, reg_1;
964
965
  /* cas2 is the only 3 words instruction, word2 and word3 have the same motif bits to check */
966
20
  word3 = peek_imm_32(info) & 0xffff;
967
20
  if (!instruction_is_valid(info, word3))
968
4
    return;
969
970
16
  op0 = &ext->operands[0];
971
16
  op1 = &ext->operands[1];
972
16
  op2 = &ext->operands[2];
973
974
16
  extension = read_imm_32(info);
975
976
16
  op0->address_mode = M68K_AM_NONE;
977
16
  op0->type = M68K_OP_REG_PAIR;
978
16
  op0->reg_pair.reg_0 = ((extension >> 16) & 7) + M68K_REG_D0;
979
16
  op0->reg_pair.reg_1 = (extension & 7) + M68K_REG_D0;
980
981
16
  op1->address_mode = M68K_AM_NONE;
982
16
  op1->type = M68K_OP_REG_PAIR;
983
16
  op1->reg_pair.reg_0 = ((extension >> 22) & 7) + M68K_REG_D0;
984
16
  op1->reg_pair.reg_1 = ((extension >> 6) & 7) + M68K_REG_D0;
985
986
16
  reg_0 = (extension >> 28) & 7;
987
16
  reg_1 = (extension >> 12) & 7;
988
989
16
  op2->address_mode = M68K_AM_NONE;
990
16
  op2->type = M68K_OP_REG_PAIR;
991
16
  op2->reg_pair.reg_0 = reg_0 + (BIT_1F(extension) ? 8 : 0) + M68K_REG_D0;
992
16
  op2->reg_pair.reg_1 = reg_1 + (BIT_F(extension) ? 8 : 0) + M68K_REG_D0;
993
16
}
994
995
static void build_chk2_cmp2(m68k_info *info, int size)
996
236
{
997
236
  cs_m68k_op* op0;
998
236
  cs_m68k_op* op1;
999
236
  cs_m68k* ext = build_init_op(info, M68K_INS_CHK2, 2, size);
1000
1001
236
  uint32_t extension = read_imm_16(info);
1002
1003
236
  if (BIT_B(extension))
1004
67
    MCInst_setOpcode(info->inst, M68K_INS_CHK2);
1005
169
  else
1006
169
    MCInst_setOpcode(info->inst, M68K_INS_CMP2);
1007
1008
236
  op0 = &ext->operands[0];
1009
236
  op1 = &ext->operands[1];
1010
1011
236
  get_ea_mode_op(info, op0, info->ir, size);
1012
1013
236
  op1->address_mode = M68K_AM_NONE;
1014
236
  op1->type = M68K_OP_REG;
1015
236
  op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
1016
236
}
1017
1018
static void build_move16(m68k_info *info, int data[2], int modes[2])
1019
14
{
1020
14
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE16, 2, 0);
1021
14
  int i;
1022
1023
42
  for (i = 0; i < 2; ++i) {
1024
28
    cs_m68k_op* op = &ext->operands[i];
1025
28
    const int d = data[i];
1026
28
    const int m = modes[i];
1027
1028
28
    op->type = M68K_OP_MEM;
1029
1030
28
    if (m == M68K_AM_REGI_ADDR_POST_INC || m == M68K_AM_REG_DIRECT_ADDR) {
1031
15
      op->address_mode = m;
1032
15
      op->reg = M68K_REG_A0 + d;
1033
15
    } else {
1034
13
      op->address_mode = m;
1035
13
      op->imm = d;
1036
13
    }
1037
28
  }
1038
14
}
1039
1040
static void build_link(m68k_info *info, int disp, int size)
1041
1
{
1042
1
  cs_m68k_op* op0;
1043
1
  cs_m68k_op* op1;
1044
1
  cs_m68k* ext = build_init_op(info, M68K_INS_LINK, 2, size);
1045
1046
1
  op0 = &ext->operands[0];
1047
1
  op1 = &ext->operands[1];
1048
1049
1
  op0->address_mode = M68K_AM_NONE;
1050
1
  op0->reg = M68K_REG_A0 + (info->ir & 7);
1051
1052
1
  op1->address_mode = M68K_AM_IMMEDIATE;
1053
1
  op1->type = M68K_OP_IMM;
1054
1
  op1->imm = disp;
1055
1
}
1056
1057
static void build_cpush_cinv(m68k_info *info, int op_offset)
1058
25
{
1059
25
  cs_m68k_op* op0;
1060
25
  cs_m68k_op* op1;
1061
25
  cs_m68k* ext = build_init_op(info, M68K_INS_INVALID, 2, 0);
1062
1063
25
  switch ((info->ir >> 3) & 3) { // scope
1064
    // Invalid
1065
9
    case 0:
1066
9
      d68000_invalid(info);
1067
9
      return;
1068
      // Line
1069
1
    case 1:
1070
1
      MCInst_setOpcode(info->inst, op_offset + 0);
1071
1
      break;
1072
      // Page
1073
10
    case 2:
1074
10
      MCInst_setOpcode(info->inst, op_offset + 1);
1075
10
      break;
1076
      // All
1077
5
    case 3:
1078
5
      ext->op_count = 1;
1079
5
      MCInst_setOpcode(info->inst, op_offset + 2);
1080
5
      break;
1081
25
  }
1082
1083
16
  op0 = &ext->operands[0];
1084
16
  op1 = &ext->operands[1];
1085
1086
16
  op0->address_mode = M68K_AM_IMMEDIATE;
1087
16
  op0->type = M68K_OP_IMM;
1088
16
  op0->imm = (info->ir >> 6) & 3;
1089
1090
16
  op1->type = M68K_OP_MEM;
1091
16
  op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
1092
16
  op1->imm = M68K_REG_A0 + (info->ir & 7);
1093
16
}
1094
1095
static void build_movep_re(m68k_info *info, int size)
1096
14
{
1097
14
  cs_m68k_op* op0;
1098
14
  cs_m68k_op* op1;
1099
14
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1100
1101
14
  op0 = &ext->operands[0];
1102
14
  op1 = &ext->operands[1];
1103
1104
14
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1105
1106
14
  op1->address_mode = M68K_AM_REGI_ADDR_DISP;
1107
14
  op1->type = M68K_OP_MEM;
1108
14
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1109
14
  op1->mem.disp = (int16_t)read_imm_16(info);
1110
14
}
1111
1112
static void build_movep_er(m68k_info *info, int size)
1113
250
{
1114
250
  cs_m68k_op* op0;
1115
250
  cs_m68k_op* op1;
1116
250
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1117
1118
250
  op0 = &ext->operands[0];
1119
250
  op1 = &ext->operands[1];
1120
1121
250
  op0->address_mode = M68K_AM_REGI_ADDR_DISP;
1122
250
  op0->type = M68K_OP_MEM;
1123
250
  op0->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1124
250
  op0->mem.disp = (int16_t)read_imm_16(info);
1125
1126
250
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1127
250
}
1128
1129
static void build_moves(m68k_info *info, int size)
1130
30
{
1131
30
  cs_m68k_op* op0;
1132
30
  cs_m68k_op* op1;
1133
30
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVES, 2, size);
1134
30
  uint32_t extension = read_imm_16(info);
1135
1136
30
  op0 = &ext->operands[0];
1137
30
  op1 = &ext->operands[1];
1138
1139
30
  if (BIT_B(extension)) {
1140
5
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
1141
5
    get_ea_mode_op(info, op1, info->ir, size);
1142
25
  } else {
1143
25
    get_ea_mode_op(info, op0, info->ir, size);
1144
25
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
1145
25
  }
1146
30
}
1147
1148
static void build_er_1(m68k_info *info, int opcode, uint8_t size)
1149
1.41k
{
1150
1.41k
  build_er_gen_1(info, true, opcode, size);
1151
1.41k
}
1152
1153
/* ======================================================================== */
1154
/* ========================= INSTRUCTION HANDLERS ========================= */
1155
/* ======================================================================== */
1156
/* Instruction handler function names follow this convention:
1157
 *
1158
 * d68000_NAME_EXTENSIONS(void)
1159
 * where NAME is the name of the opcode it handles and EXTENSIONS are any
1160
 * extensions for special instances of that opcode.
1161
 *
1162
 * Examples:
1163
 *   d68000_add_er_8(): add opcode, from effective address to register,
1164
 *                      size = byte
1165
 *
1166
 *   d68000_asr_s_8(): arithmetic shift right, static count, size = byte
1167
 *
1168
 *
1169
 * Common extensions:
1170
 * 8   : size = byte
1171
 * 16  : size = word
1172
 * 32  : size = long
1173
 * rr  : register to register
1174
 * mm  : memory to memory
1175
 * r   : register
1176
 * s   : static
1177
 * er  : effective address -> register
1178
 * re  : register -> effective address
1179
 * ea  : using effective address mode of operation
1180
 * d   : data register direct
1181
 * a   : address register direct
1182
 * ai  : address register indirect
1183
 * pi  : address register indirect with postincrement
1184
 * pd  : address register indirect with predecrement
1185
 * di  : address register indirect with displacement
1186
 * ix  : address register indirect with index
1187
 * aw  : absolute word
1188
 * al  : absolute long
1189
 */
1190
1191
1192
static void d68000_invalid(m68k_info *info)
1193
1.00k
{
1194
1.00k
  build_invalid(info, info->ir);
1195
1.00k
}
1196
1197
static void d68000_illegal(m68k_info *info)
1198
16
{
1199
16
  build_illegal(info, info->ir);
1200
16
}
1201
1202
static void d68000_1010(m68k_info *info)
1203
288
{
1204
288
  build_invalid(info, info->ir);
1205
288
}
1206
1207
static void d68000_1111(m68k_info *info)
1208
433
{
1209
433
  build_invalid(info, info->ir);
1210
433
}
1211
1212
static void d68000_abcd_rr(m68k_info *info)
1213
161
{
1214
161
  build_rr(info, M68K_INS_ABCD, 1, 0);
1215
161
}
1216
1217
static void d68000_abcd_mm(m68k_info *info)
1218
0
{
1219
0
  build_mm(info, M68K_INS_ABCD, 1, 0);
1220
0
}
1221
1222
static void d68000_add_er_8(m68k_info *info)
1223
15
{
1224
15
  build_er_1(info, M68K_INS_ADD, 1);
1225
15
}
1226
1227
static void d68000_add_er_16(m68k_info *info)
1228
18
{
1229
18
  build_er_1(info, M68K_INS_ADD, 2);
1230
18
}
1231
1232
static void d68000_add_er_32(m68k_info *info)
1233
79
{
1234
79
  build_er_1(info, M68K_INS_ADD, 4);
1235
79
}
1236
1237
static void d68000_add_re_8(m68k_info *info)
1238
42
{
1239
42
  build_re_1(info, M68K_INS_ADD, 1);
1240
42
}
1241
1242
static void d68000_add_re_16(m68k_info *info)
1243
8
{
1244
8
  build_re_1(info, M68K_INS_ADD, 2);
1245
8
}
1246
1247
static void d68000_add_re_32(m68k_info *info)
1248
16
{
1249
16
  build_re_1(info, M68K_INS_ADD, 4);
1250
16
}
1251
1252
static void d68000_adda_16(m68k_info *info)
1253
217
{
1254
217
  build_ea_a(info, M68K_INS_ADDA, 2);
1255
217
}
1256
1257
static void d68000_adda_32(m68k_info *info)
1258
181
{
1259
181
  build_ea_a(info, M68K_INS_ADDA, 4);
1260
181
}
1261
1262
static void d68000_addi_8(m68k_info *info)
1263
145
{
1264
145
  build_imm_ea(info, M68K_INS_ADDI, 1, read_imm_8(info));
1265
145
}
1266
1267
static void d68000_addi_16(m68k_info *info)
1268
22
{
1269
22
  build_imm_ea(info, M68K_INS_ADDI, 2, read_imm_16(info));
1270
22
}
1271
1272
static void d68000_addi_32(m68k_info *info)
1273
6
{
1274
6
  build_imm_ea(info, M68K_INS_ADDI, 4, read_imm_32(info));
1275
6
}
1276
1277
static void d68000_addq_8(m68k_info *info)
1278
87
{
1279
87
  build_3bit_ea(info, M68K_INS_ADDQ, 1);
1280
87
}
1281
1282
static void d68000_addq_16(m68k_info *info)
1283
188
{
1284
188
  build_3bit_ea(info, M68K_INS_ADDQ, 2);
1285
188
}
1286
1287
static void d68000_addq_32(m68k_info *info)
1288
200
{
1289
200
  build_3bit_ea(info, M68K_INS_ADDQ, 4);
1290
200
}
1291
1292
static void d68000_addx_rr_8(m68k_info *info)
1293
19
{
1294
19
  build_rr(info, M68K_INS_ADDX, 1, 0);
1295
19
}
1296
1297
static void d68000_addx_rr_16(m68k_info *info)
1298
56
{
1299
56
  build_rr(info, M68K_INS_ADDX, 2, 0);
1300
56
}
1301
1302
static void d68000_addx_rr_32(m68k_info *info)
1303
142
{
1304
142
  build_rr(info, M68K_INS_ADDX, 4, 0);
1305
142
}
1306
1307
static void d68000_addx_mm_8(m68k_info *info)
1308
20
{
1309
20
  build_mm(info, M68K_INS_ADDX, 1, 0);
1310
20
}
1311
1312
static void d68000_addx_mm_16(m68k_info *info)
1313
0
{
1314
0
  build_mm(info, M68K_INS_ADDX, 2, 0);
1315
0
}
1316
1317
static void d68000_addx_mm_32(m68k_info *info)
1318
1
{
1319
1
  build_mm(info, M68K_INS_ADDX, 4, 0);
1320
1
}
1321
1322
static void d68000_and_er_8(m68k_info *info)
1323
28
{
1324
28
  build_er_1(info, M68K_INS_AND, 1);
1325
28
}
1326
1327
static void d68000_and_er_16(m68k_info *info)
1328
12
{
1329
12
  build_er_1(info, M68K_INS_AND, 2);
1330
12
}
1331
1332
static void d68000_and_er_32(m68k_info *info)
1333
27
{
1334
27
  build_er_1(info, M68K_INS_AND, 4);
1335
27
}
1336
1337
static void d68000_and_re_8(m68k_info *info)
1338
3
{
1339
3
  build_re_1(info, M68K_INS_AND, 1);
1340
3
}
1341
1342
static void d68000_and_re_16(m68k_info *info)
1343
145
{
1344
145
  build_re_1(info, M68K_INS_AND, 2);
1345
145
}
1346
1347
static void d68000_and_re_32(m68k_info *info)
1348
11
{
1349
11
  build_re_1(info, M68K_INS_AND, 4);
1350
11
}
1351
1352
static void d68000_andi_8(m68k_info *info)
1353
43
{
1354
43
  build_imm_ea(info, M68K_INS_ANDI, 1, read_imm_8(info));
1355
43
}
1356
1357
static void d68000_andi_16(m68k_info *info)
1358
12
{
1359
12
  build_imm_ea(info, M68K_INS_ANDI, 2, read_imm_16(info));
1360
12
}
1361
1362
static void d68000_andi_32(m68k_info *info)
1363
69
{
1364
69
  build_imm_ea(info, M68K_INS_ANDI, 4, read_imm_32(info));
1365
69
}
1366
1367
static void d68000_andi_to_ccr(m68k_info *info)
1368
0
{
1369
0
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_8(info), 1, M68K_REG_CCR);
1370
0
}
1371
1372
static void d68000_andi_to_sr(m68k_info *info)
1373
0
{
1374
0
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_16(info), 2, M68K_REG_SR);
1375
0
}
1376
1377
static void d68000_asr_s_8(m68k_info *info)
1378
65
{
1379
65
  build_3bit_d(info, M68K_INS_ASR, 1);
1380
65
}
1381
1382
static void d68000_asr_s_16(m68k_info *info)
1383
4
{
1384
4
  build_3bit_d(info, M68K_INS_ASR, 2);
1385
4
}
1386
1387
static void d68000_asr_s_32(m68k_info *info)
1388
171
{
1389
171
  build_3bit_d(info, M68K_INS_ASR, 4);
1390
171
}
1391
1392
static void d68000_asr_r_8(m68k_info *info)
1393
5
{
1394
5
  build_r(info, M68K_INS_ASR, 1);
1395
5
}
1396
1397
static void d68000_asr_r_16(m68k_info *info)
1398
21
{
1399
21
  build_r(info, M68K_INS_ASR, 2);
1400
21
}
1401
1402
static void d68000_asr_r_32(m68k_info *info)
1403
0
{
1404
0
  build_r(info, M68K_INS_ASR, 4);
1405
0
}
1406
1407
static void d68000_asr_ea(m68k_info *info)
1408
6
{
1409
6
  build_ea(info, M68K_INS_ASR, 2);
1410
6
}
1411
1412
static void d68000_asl_s_8(m68k_info *info)
1413
131
{
1414
131
  build_3bit_d(info, M68K_INS_ASL, 1);
1415
131
}
1416
1417
static void d68000_asl_s_16(m68k_info *info)
1418
0
{
1419
0
  build_3bit_d(info, M68K_INS_ASL, 2);
1420
0
}
1421
1422
static void d68000_asl_s_32(m68k_info *info)
1423
14
{
1424
14
  build_3bit_d(info, M68K_INS_ASL, 4);
1425
14
}
1426
1427
static void d68000_asl_r_8(m68k_info *info)
1428
2
{
1429
2
  build_r(info, M68K_INS_ASL, 1);
1430
2
}
1431
1432
static void d68000_asl_r_16(m68k_info *info)
1433
20
{
1434
20
  build_r(info, M68K_INS_ASL, 2);
1435
20
}
1436
1437
static void d68000_asl_r_32(m68k_info *info)
1438
0
{
1439
0
  build_r(info, M68K_INS_ASL, 4);
1440
0
}
1441
1442
static void d68000_asl_ea(m68k_info *info)
1443
128
{
1444
128
  build_ea(info, M68K_INS_ASL, 2);
1445
128
}
1446
1447
static void d68000_bcc_8(m68k_info *info)
1448
850
{
1449
850
  build_bcc(info, 1, make_int_8(info->ir));
1450
850
}
1451
1452
static void d68000_bcc_16(m68k_info *info)
1453
13
{
1454
13
  build_bcc(info, 2, make_int_16(read_imm_16(info)));
1455
13
}
1456
1457
static void d68020_bcc_32(m68k_info *info)
1458
25
{
1459
25
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1460
2
  build_bcc(info, 4, read_imm_32(info));
1461
2
}
1462
1463
static void d68000_bchg_r(m68k_info *info)
1464
92
{
1465
92
  build_re_1(info, M68K_INS_BCHG, 1);
1466
92
}
1467
1468
static void d68000_bchg_s(m68k_info *info)
1469
34
{
1470
34
  build_imm_ea(info, M68K_INS_BCHG, 1, read_imm_8(info));
1471
34
}
1472
1473
static void d68000_bclr_r(m68k_info *info)
1474
66
{
1475
66
  build_re_1(info, M68K_INS_BCLR, 1);
1476
66
}
1477
1478
static void d68000_bclr_s(m68k_info *info)
1479
139
{
1480
139
  build_imm_ea(info, M68K_INS_BCLR, 1, read_imm_8(info));
1481
139
}
1482
1483
static void d68010_bkpt(m68k_info *info)
1484
9
{
1485
9
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1486
1
  build_absolute_jump_with_immediate(info, M68K_INS_BKPT, 0, info->ir & 7);
1487
1
}
1488
1489
static void d68020_bfchg(m68k_info *info)
1490
41
{
1491
41
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1492
41
  build_bitfield_ins(info, M68K_INS_BFCHG, false);
1493
41
}
1494
1495
1496
static void d68020_bfclr(m68k_info *info)
1497
8
{
1498
8
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1499
8
  build_bitfield_ins(info, M68K_INS_BFCLR, false);
1500
8
}
1501
1502
static void d68020_bfexts(m68k_info *info)
1503
10
{
1504
10
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1505
6
  build_bitfield_ins(info, M68K_INS_BFEXTS, true);
1506
6
}
1507
1508
static void d68020_bfextu(m68k_info *info)
1509
91
{
1510
91
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1511
91
  build_bitfield_ins(info, M68K_INS_BFEXTU, true);
1512
91
}
1513
1514
static void d68020_bfffo(m68k_info *info)
1515
10
{
1516
10
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1517
8
  build_bitfield_ins(info, M68K_INS_BFFFO, true);
1518
8
}
1519
1520
static void d68020_bfins(m68k_info *info)
1521
42
{
1522
42
  cs_m68k* ext = &info->extension;
1523
42
  cs_m68k_op temp;
1524
1525
42
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1526
22
  build_bitfield_ins(info, M68K_INS_BFINS, true);
1527
1528
  // a bit hacky but we need to flip the args on only this instruction
1529
1530
22
  temp = ext->operands[0];
1531
22
  ext->operands[0] = ext->operands[1];
1532
22
  ext->operands[1] = temp;
1533
22
}
1534
1535
static void d68020_bfset(m68k_info *info)
1536
37
{
1537
37
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1538
35
  build_bitfield_ins(info, M68K_INS_BFSET, false);
1539
35
}
1540
1541
static void d68020_bftst(m68k_info *info)
1542
15
{
1543
15
  build_bitfield_ins(info, M68K_INS_BFTST, false);
1544
15
}
1545
1546
static void d68000_bra_8(m68k_info *info)
1547
209
{
1548
209
  build_relative_branch(info, M68K_INS_BRA, 1, make_int_8(info->ir));
1549
209
}
1550
1551
static void d68000_bra_16(m68k_info *info)
1552
9
{
1553
9
  build_relative_branch(info, M68K_INS_BRA, 2, make_int_16(read_imm_16(info)));
1554
9
}
1555
1556
static void d68020_bra_32(m68k_info *info)
1557
6
{
1558
6
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1559
3
  build_relative_branch(info, M68K_INS_BRA, 4, read_imm_32(info));
1560
3
}
1561
1562
static void d68000_bset_r(m68k_info *info)
1563
166
{
1564
166
  build_re_1(info, M68K_INS_BSET, 1);
1565
166
}
1566
1567
static void d68000_bset_s(m68k_info *info)
1568
32
{
1569
32
  build_imm_ea(info, M68K_INS_BSET, 1, read_imm_8(info));
1570
32
}
1571
1572
static void d68000_bsr_8(m68k_info *info)
1573
20
{
1574
20
  build_relative_branch(info, M68K_INS_BSR, 1, make_int_8(info->ir));
1575
20
}
1576
1577
static void d68000_bsr_16(m68k_info *info)
1578
16
{
1579
16
  build_relative_branch(info, M68K_INS_BSR, 2, make_int_16(read_imm_16(info)));
1580
16
}
1581
1582
static void d68020_bsr_32(m68k_info *info)
1583
13
{
1584
13
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1585
13
  build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info));
1586
13
}
1587
1588
static void d68000_btst_r(m68k_info *info)
1589
438
{
1590
438
  build_re_1(info, M68K_INS_BTST, 4);
1591
438
}
1592
1593
static void d68000_btst_s(m68k_info *info)
1594
18
{
1595
18
  build_imm_ea(info, M68K_INS_BTST, 1, read_imm_8(info));
1596
18
}
1597
1598
static void d68020_callm(m68k_info *info)
1599
0
{
1600
0
  LIMIT_CPU_TYPES(info, M68020_ONLY);
1601
0
  build_imm_ea(info, M68K_INS_CALLM, 0, read_imm_8(info));
1602
0
}
1603
1604
static void d68020_cas_8(m68k_info *info)
1605
13
{
1606
13
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1607
5
  build_d_d_ea(info, M68K_INS_CAS, 1);
1608
5
}
1609
1610
static void d68020_cas_16(m68k_info *info)
1611
16
{
1612
16
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1613
16
  build_d_d_ea(info, M68K_INS_CAS, 2);
1614
16
}
1615
1616
static void d68020_cas_32(m68k_info *info)
1617
4
{
1618
4
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1619
1
  build_d_d_ea(info, M68K_INS_CAS, 4);
1620
1
}
1621
1622
static void d68020_cas2_16(m68k_info *info)
1623
12
{
1624
12
  build_cas2(info, 2);
1625
12
}
1626
1627
static void d68020_cas2_32(m68k_info *info)
1628
8
{
1629
8
  build_cas2(info, 4);
1630
8
}
1631
1632
static void d68000_chk_16(m68k_info *info)
1633
45
{
1634
45
  build_er_1(info, M68K_INS_CHK, 2);
1635
45
}
1636
1637
static void d68020_chk_32(m68k_info *info)
1638
15
{
1639
15
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1640
7
  build_er_1(info, M68K_INS_CHK, 4);
1641
7
}
1642
1643
static void d68020_chk2_cmp2_8(m68k_info *info)
1644
93
{
1645
93
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1646
90
  build_chk2_cmp2(info, 1);
1647
90
}
1648
1649
static void d68020_chk2_cmp2_16(m68k_info *info)
1650
19
{
1651
19
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1652
16
  build_chk2_cmp2(info, 2);
1653
16
}
1654
1655
static void d68020_chk2_cmp2_32(m68k_info *info)
1656
149
{
1657
149
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1658
130
  build_chk2_cmp2(info, 4);
1659
130
}
1660
1661
static void d68040_cinv(m68k_info *info)
1662
16
{
1663
16
  LIMIT_CPU_TYPES(info, M68040_PLUS);
1664
12
  build_cpush_cinv(info, M68K_INS_CINVL);
1665
12
}
1666
1667
static void d68000_clr_8(m68k_info *info)
1668
6
{
1669
6
  build_ea(info, M68K_INS_CLR, 1);
1670
6
}
1671
1672
static void d68000_clr_16(m68k_info *info)
1673
7
{
1674
7
  build_ea(info, M68K_INS_CLR, 2);
1675
7
}
1676
1677
static void d68000_clr_32(m68k_info *info)
1678
0
{
1679
0
  build_ea(info, M68K_INS_CLR, 4);
1680
0
}
1681
1682
static void d68000_cmp_8(m68k_info *info)
1683
7
{
1684
7
  build_er_1(info, M68K_INS_CMP, 1);
1685
7
}
1686
1687
static void d68000_cmp_16(m68k_info *info)
1688
41
{
1689
41
  build_er_1(info, M68K_INS_CMP, 2);
1690
41
}
1691
1692
static void d68000_cmp_32(m68k_info *info)
1693
164
{
1694
164
  build_er_1(info, M68K_INS_CMP, 4);
1695
164
}
1696
1697
static void d68000_cmpa_16(m68k_info *info)
1698
11
{
1699
11
  build_ea_a(info, M68K_INS_CMPA, 2);
1700
11
}
1701
1702
static void d68000_cmpa_32(m68k_info *info)
1703
91
{
1704
91
  build_ea_a(info, M68K_INS_CMPA, 4);
1705
91
}
1706
1707
static void d68000_cmpi_8(m68k_info *info)
1708
22
{
1709
22
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
1710
22
}
1711
1712
static void d68020_cmpi_pcdi_8(m68k_info *info)
1713
47
{
1714
47
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1715
43
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
1716
43
}
1717
1718
static void d68020_cmpi_pcix_8(m68k_info *info)
1719
55
{
1720
55
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1721
11
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
1722
11
}
1723
1724
static void d68000_cmpi_16(m68k_info *info)
1725
30
{
1726
30
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
1727
30
}
1728
1729
static void d68020_cmpi_pcdi_16(m68k_info *info)
1730
171
{
1731
171
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1732
139
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
1733
139
}
1734
1735
static void d68020_cmpi_pcix_16(m68k_info *info)
1736
2
{
1737
2
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1738
2
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
1739
2
}
1740
1741
static void d68000_cmpi_32(m68k_info *info)
1742
134
{
1743
134
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
1744
134
}
1745
1746
static void d68020_cmpi_pcdi_32(m68k_info *info)
1747
38
{
1748
38
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1749
35
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
1750
35
}
1751
1752
static void d68020_cmpi_pcix_32(m68k_info *info)
1753
20
{
1754
20
  LIMIT_CPU_TYPES(info, M68010_PLUS);
1755
16
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
1756
16
}
1757
1758
static void d68000_cmpm_8(m68k_info *info)
1759
2
{
1760
2
  build_pi_pi(info, M68K_INS_CMPM, 1);
1761
2
}
1762
1763
static void d68000_cmpm_16(m68k_info *info)
1764
6
{
1765
6
  build_pi_pi(info, M68K_INS_CMPM, 2);
1766
6
}
1767
1768
static void d68000_cmpm_32(m68k_info *info)
1769
0
{
1770
0
  build_pi_pi(info, M68K_INS_CMPM, 4);
1771
0
}
1772
1773
static void make_cpbcc_operand(cs_m68k_op* op, int size, int displacement)
1774
426
{
1775
426
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
1776
426
  op->type = M68K_OP_BR_DISP;
1777
426
  op->br_disp.disp = displacement;
1778
426
  op->br_disp.disp_size = size;
1779
426
}
1780
1781
static void d68020_cpbcc_16(m68k_info *info)
1782
230
{
1783
230
  cs_m68k_op* op0;
1784
230
  cs_m68k* ext;
1785
230
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1786
1787
  // FNOP is a special case of FBF
1788
207
  if (info->ir == 0xf280 && peek_imm_16(info) == 0) {
1789
6
    MCInst_setOpcode(info->inst, M68K_INS_FNOP);
1790
6
    info->pc += 2;
1791
6
    return;
1792
6
  }
1793
1794
  // these are all in row with the extension so just doing a add here is fine
1795
201
  info->inst->Opcode += (info->ir & 0x2f);
1796
1797
201
  ext = build_init_op(info, M68K_INS_FBF, 1, 2);
1798
201
  op0 = &ext->operands[0];
1799
1800
201
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_WORD, make_int_16(read_imm_16(info)));
1801
1802
201
  set_insn_group(info, M68K_GRP_JUMP);
1803
201
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
1804
201
}
1805
1806
static void d68020_cpbcc_32(m68k_info *info)
1807
125
{
1808
125
  cs_m68k* ext;
1809
125
  cs_m68k_op* op0;
1810
1811
125
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1812
1813
  // these are all in row with the extension so just doing a add here is fine
1814
63
  info->inst->Opcode += (info->ir & 0x2f);
1815
1816
63
  ext = build_init_op(info, M68K_INS_FBF, 1, 4);
1817
63
  op0 = &ext->operands[0];
1818
1819
63
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_LONG, read_imm_32(info));
1820
1821
63
  set_insn_group(info, M68K_GRP_JUMP);
1822
63
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
1823
63
}
1824
1825
static void d68020_cpdbcc(m68k_info *info)
1826
331
{
1827
331
  cs_m68k* ext;
1828
331
  cs_m68k_op* op0;
1829
331
  cs_m68k_op* op1;
1830
331
  uint32_t ext1, ext2;
1831
1832
331
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1833
1834
162
  ext1 = read_imm_16(info);
1835
162
  ext2 = read_imm_16(info);
1836
1837
  // these are all in row with the extension so just doing a add here is fine
1838
162
  info->inst->Opcode += (ext1 & 0x2f);
1839
1840
162
  ext = build_init_op(info, M68K_INS_FDBF, 2, 0);
1841
162
  op0 = &ext->operands[0];
1842
162
  op1 = &ext->operands[1];
1843
1844
162
  op0->reg = M68K_REG_D0 + (info->ir & 7);
1845
1846
162
  make_cpbcc_operand(op1, M68K_OP_BR_DISP_SIZE_WORD, make_int_16(ext2) + 2);
1847
1848
162
  set_insn_group(info, M68K_GRP_JUMP);
1849
162
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
1850
162
}
1851
1852
static void fmove_fpcr(m68k_info *info, uint32_t extension)
1853
64
{
1854
64
  cs_m68k_op* special;
1855
64
  cs_m68k_op* op_ea;
1856
1857
64
  int regsel = (extension >> 10) & 0x7;
1858
64
  int dir = (extension >> 13) & 0x1;
1859
1860
64
  cs_m68k* ext = build_init_op(info, M68K_INS_FMOVE, 2, 4);
1861
1862
64
  special = &ext->operands[0];
1863
64
  op_ea = &ext->operands[1];
1864
1865
64
  if (!dir) {
1866
44
    cs_m68k_op* t = special;
1867
44
    special = op_ea;
1868
44
    op_ea = t;
1869
44
  }
1870
1871
64
  get_ea_mode_op(info, op_ea, info->ir, 4);
1872
1873
64
  if (regsel & 4)
1874
39
    special->reg = M68K_REG_FPCR;
1875
25
  else if (regsel & 2)
1876
4
    special->reg = M68K_REG_FPSR;
1877
21
  else if (regsel & 1)
1878
0
    special->reg = M68K_REG_FPIAR;
1879
64
}
1880
1881
static void fmovem(m68k_info *info, uint32_t extension)
1882
152
{
1883
152
  cs_m68k_op* op_reglist;
1884
152
  cs_m68k_op* op_ea;
1885
152
  int dir = (extension >> 13) & 0x1;
1886
152
  int mode = (extension >> 11) & 0x3;
1887
152
  uint32_t reglist = extension & 0xff;
1888
152
  cs_m68k* ext = build_init_op(info, M68K_INS_FMOVEM, 2, 0);
1889
1890
152
  op_reglist = &ext->operands[0];
1891
152
  op_ea = &ext->operands[1];
1892
1893
  // flip args around
1894
1895
152
  if (!dir) {
1896
11
    cs_m68k_op* t = op_reglist;
1897
11
    op_reglist = op_ea;
1898
11
    op_ea = t;
1899
11
  }
1900
1901
152
  get_ea_mode_op(info, op_ea, info->ir, 0);
1902
1903
152
  switch (mode) {
1904
71
    case 1 : // Dynamic list in dn register
1905
71
      op_reglist->reg = M68K_REG_D0 + ((reglist >> 4) & 7);
1906
71
      break;
1907
1908
3
    case 0 :
1909
3
      op_reglist->address_mode = M68K_AM_NONE;
1910
3
      op_reglist->type = M68K_OP_REG_BITS;
1911
3
      op_reglist->register_bits = reglist << 16;
1912
3
      break;
1913
1914
46
    case 2 : // Static list
1915
46
      op_reglist->address_mode = M68K_AM_NONE;
1916
46
      op_reglist->type = M68K_OP_REG_BITS;
1917
46
      op_reglist->register_bits = ((uint32_t)reverse_bits_8(reglist)) << 16;
1918
46
      break;
1919
152
  }
1920
152
}
1921
1922
static void d68020_cpgen(m68k_info *info)
1923
1.77k
{
1924
1.77k
  cs_m68k *ext;
1925
1.77k
  cs_m68k_op* op0;
1926
1.77k
  cs_m68k_op* op1;
1927
1.77k
  bool supports_single_op;
1928
1.77k
  uint32_t next;
1929
1.77k
  int rm, src, dst, opmode;
1930
1931
1932
1.77k
  LIMIT_CPU_TYPES(info, M68020_PLUS);
1933
1934
1.76k
  supports_single_op = true;
1935
1936
1.76k
  next = read_imm_16(info);
1937
1938
1.76k
  rm = (next >> 14) & 0x1;
1939
1.76k
  src = (next >> 10) & 0x7;
1940
1.76k
  dst = (next >> 7) & 0x7;
1941
1.76k
  opmode = next & 0x3f;
1942
1943
  // special handling for fmovecr
1944
1945
1.76k
  if (BITFIELD(info->ir, 5, 0) == 0 && BITFIELD(next, 15, 10) == 0x17) {
1946
8
    cs_m68k_op* op0;
1947
8
    cs_m68k_op* op1;
1948
8
    cs_m68k* ext = build_init_op(info, M68K_INS_FMOVECR, 2, 0);
1949
1950
8
    op0 = &ext->operands[0];
1951
8
    op1 = &ext->operands[1];
1952
1953
8
    op0->address_mode = M68K_AM_IMMEDIATE;
1954
8
    op0->type = M68K_OP_IMM;
1955
8
    op0->imm = next & 0x3f;
1956
1957
8
    op1->reg = M68K_REG_FP0 + ((next >> 7) & 7);
1958
1959
8
    return;
1960
8
  }
1961
1962
  // deal with extended move stuff
1963
1964
1.75k
  switch ((next >> 13) & 0x7) {
1965
    // fmovem fpcr
1966
44
    case 0x4: // FMOVEM ea, FPCR
1967
64
    case 0x5: // FMOVEM FPCR, ea
1968
64
      fmove_fpcr(info, next);
1969
64
      return;
1970
1971
    // fmovem list
1972
11
    case 0x6:
1973
152
    case 0x7:
1974
152
      fmovem(info, next);
1975
152
      return;
1976
1.75k
  }
1977
1978
  // See comment bellow on why this is being done
1979
1980
1.53k
  if ((next >> 6) & 1)
1981
716
    opmode &= ~4;
1982
1983
  // special handling of some instructions here
1984
1985
1.53k
  switch (opmode) {
1986
17
    case 0x00: MCInst_setOpcode(info->inst, M68K_INS_FMOVE); supports_single_op = false; break;
1987
27
    case 0x01: MCInst_setOpcode(info->inst, M68K_INS_FINT); break;
1988
5
    case 0x02: MCInst_setOpcode(info->inst, M68K_INS_FSINH); break;
1989
0
    case 0x03: MCInst_setOpcode(info->inst, M68K_INS_FINTRZ); break;
1990
0
    case 0x04: MCInst_setOpcode(info->inst, M68K_INS_FSQRT); break;
1991
3
    case 0x06: MCInst_setOpcode(info->inst, M68K_INS_FLOGNP1); break;
1992
5
    case 0x08: MCInst_setOpcode(info->inst, M68K_INS_FETOXM1); break;
1993
1
    case 0x09: MCInst_setOpcode(info->inst, M68K_INS_FATANH); break;
1994
142
    case 0x0a: MCInst_setOpcode(info->inst, M68K_INS_FATAN); break;
1995
18
    case 0x0c: MCInst_setOpcode(info->inst, M68K_INS_FASIN); break;
1996
128
    case 0x0d: MCInst_setOpcode(info->inst, M68K_INS_FATANH); break;
1997
128
    case 0x0e: MCInst_setOpcode(info->inst, M68K_INS_FSIN); break;
1998
33
    case 0x0f: MCInst_setOpcode(info->inst, M68K_INS_FTAN); break;
1999
3
    case 0x10: MCInst_setOpcode(info->inst, M68K_INS_FETOX); break;
2000
9
    case 0x11: MCInst_setOpcode(info->inst, M68K_INS_FTWOTOX); break;
2001
1
    case 0x12: MCInst_setOpcode(info->inst, M68K_INS_FTENTOX); break;
2002
3
    case 0x14: MCInst_setOpcode(info->inst, M68K_INS_FLOGN); break;
2003
8
    case 0x15: MCInst_setOpcode(info->inst, M68K_INS_FLOG10); break;
2004
5
    case 0x16: MCInst_setOpcode(info->inst, M68K_INS_FLOG2); break;
2005
1
    case 0x18: MCInst_setOpcode(info->inst, M68K_INS_FABS); break;
2006
4
    case 0x19: MCInst_setOpcode(info->inst, M68K_INS_FCOSH); break;
2007
18
    case 0x1a: MCInst_setOpcode(info->inst, M68K_INS_FNEG); break;
2008
2
    case 0x1c: MCInst_setOpcode(info->inst, M68K_INS_FACOS); break;
2009
33
    case 0x1d: MCInst_setOpcode(info->inst, M68K_INS_FCOS); break;
2010
0
    case 0x1e: MCInst_setOpcode(info->inst, M68K_INS_FGETEXP); break;
2011
40
    case 0x1f: MCInst_setOpcode(info->inst, M68K_INS_FGETMAN); break;
2012
6
    case 0x20: MCInst_setOpcode(info->inst, M68K_INS_FDIV); supports_single_op = false; break;
2013
164
    case 0x21: MCInst_setOpcode(info->inst, M68K_INS_FMOD); supports_single_op = false; break;
2014
7
    case 0x22: MCInst_setOpcode(info->inst, M68K_INS_FADD); supports_single_op = false; break;
2015
321
    case 0x23: MCInst_setOpcode(info->inst, M68K_INS_FMUL); supports_single_op = false; break;
2016
8
    case 0x24: MCInst_setOpcode(info->inst, M68K_INS_FSGLDIV); supports_single_op = false; break;
2017
10
    case 0x25: MCInst_setOpcode(info->inst, M68K_INS_FREM); break;
2018
153
    case 0x26: MCInst_setOpcode(info->inst, M68K_INS_FSCALE); break;
2019
24
    case 0x27: MCInst_setOpcode(info->inst, M68K_INS_FSGLMUL); break;
2020
135
    case 0x28: MCInst_setOpcode(info->inst, M68K_INS_FSUB); supports_single_op = false; break;
2021
29
    case 0x38: MCInst_setOpcode(info->inst, M68K_INS_FCMP); supports_single_op = false; break;
2022
7
    case 0x3a: MCInst_setOpcode(info->inst, M68K_INS_FTST); break;
2023
41
    default:
2024
41
      break;
2025
1.53k
  }
2026
2027
  // Some trickery here! It's not documented but if bit 6 is set this is a s/d opcode and then
2028
  // if bit 2 is set it's a d. As we already have set our opcode in the code above we can just
2029
  // offset it as the following 2 op codes (if s/d is supported) will always be directly after it
2030
2031
1.53k
  if ((next >> 6) & 1) {
2032
716
    if ((next >> 2) & 1)
2033
355
      info->inst->Opcode += 2;
2034
361
    else
2035
361
      info->inst->Opcode += 1;
2036
716
  }
2037
2038
1.53k
  ext = &info->extension;
2039
2040
1.53k
  ext->op_count = 2;
2041
1.53k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
2042
1.53k
  ext->op_size.cpu_size = 0;
2043
2044
  // Special case - adjust direction of fmove
2045
1.53k
  if ((opmode == 0x00) && ((next >> 13) & 0x1) != 0) {
2046
4
    op0 = &ext->operands[1];
2047
4
    op1 = &ext->operands[0];
2048
1.53k
  } else {
2049
1.53k
    op0 = &ext->operands[0];
2050
1.53k
    op1 = &ext->operands[1];
2051
1.53k
  }
2052
2053
1.53k
  if (rm == 0 && supports_single_op && src == dst) {
2054
65
    ext->op_count = 1;
2055
65
    op0->reg = M68K_REG_FP0 + dst;
2056
65
    return;
2057
65
  }
2058
2059
1.47k
  if (rm == 1) {
2060
847
    switch (src) {
2061
20
      case 0x00 :
2062
20
        ext->op_size.cpu_size = M68K_CPU_SIZE_LONG;
2063
20
        get_ea_mode_op(info, op0, info->ir, 4);
2064
20
        break;
2065
2066
225
      case 0x06 :
2067
225
        ext->op_size.cpu_size = M68K_CPU_SIZE_BYTE;
2068
225
        get_ea_mode_op(info, op0, info->ir, 1);
2069
225
        break;
2070
2071
436
      case 0x04 :
2072
436
        ext->op_size.cpu_size = M68K_CPU_SIZE_WORD;
2073
436
        get_ea_mode_op(info, op0, info->ir, 2);
2074
436
        break;
2075
2076
7
      case 0x01 :
2077
7
        ext->op_size.type = M68K_SIZE_TYPE_FPU;
2078
7
        ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE;
2079
7
        get_ea_mode_op(info, op0, info->ir, 4);
2080
7
        op0->type = M68K_OP_FP_SINGLE;
2081
7
        break;
2082
2083
10
      case 0x05:
2084
10
        ext->op_size.type = M68K_SIZE_TYPE_FPU;
2085
10
        ext->op_size.fpu_size = M68K_FPU_SIZE_DOUBLE;
2086
10
        get_ea_mode_op(info, op0, info->ir, 8);
2087
10
        op0->type = M68K_OP_FP_DOUBLE;
2088
10
        break;
2089
2090
149
      default :
2091
149
        ext->op_size.type = M68K_SIZE_TYPE_FPU;
2092
149
        ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
2093
149
        break;
2094
847
    }
2095
847
  } else {
2096
627
    op0->reg = M68K_REG_FP0 + src;
2097
627
  }
2098
2099
1.47k
  op1->reg = M68K_REG_FP0 + dst;
2100
1.47k
}
2101
2102
static void d68020_cprestore(m68k_info *info)
2103
91
{
2104
91
  cs_m68k* ext;
2105
91
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2106
2107
87
  ext = build_init_op(info, M68K_INS_FRESTORE, 1, 0);
2108
87
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
2109
87
}
2110
2111
static void d68020_cpsave(m68k_info *info)
2112
74
{
2113
74
  cs_m68k* ext;
2114
2115
74
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2116
2117
72
  ext = build_init_op(info, M68K_INS_FSAVE, 1, 0);
2118
72
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
2119
72
}
2120
2121
static void d68020_cpscc(m68k_info *info)
2122
84
{
2123
84
  cs_m68k* ext;
2124
2125
84
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2126
42
  ext = build_init_op(info, M68K_INS_FSF, 1, 1);
2127
2128
  // these are all in row with the extension so just doing a add here is fine
2129
42
  info->inst->Opcode += (read_imm_16(info) & 0x2f);
2130
2131
42
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
2132
42
}
2133
2134
static void d68020_cptrapcc_0(m68k_info *info)
2135
129
{
2136
129
  uint32_t extension1;
2137
129
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2138
2139
129
  extension1 = read_imm_16(info);
2140
2141
129
  build_init_op(info, M68K_INS_FTRAPF, 0, 0);
2142
2143
  // these are all in row with the extension so just doing a add here is fine
2144
129
  info->inst->Opcode += (extension1 & 0x2f);
2145
129
}
2146
2147
static void d68020_cptrapcc_16(m68k_info *info)
2148
2
{
2149
2
  uint32_t extension1, extension2;
2150
2
  cs_m68k_op* op0;
2151
2
  cs_m68k* ext;
2152
2153
2
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2154
2155
0
  extension1 = read_imm_16(info);
2156
0
  extension2 = read_imm_16(info);
2157
2158
0
  ext = build_init_op(info, M68K_INS_FTRAPF, 1, 2);
2159
2160
  // these are all in row with the extension so just doing a add here is fine
2161
0
  info->inst->Opcode += (extension1 & 0x2f);
2162
2163
0
  op0 = &ext->operands[0];
2164
2165
0
  op0->address_mode = M68K_AM_IMMEDIATE;
2166
0
  op0->type = M68K_OP_IMM;
2167
0
  op0->imm = extension2;
2168
0
}
2169
2170
static void d68020_cptrapcc_32(m68k_info *info)
2171
36
{
2172
36
  uint32_t extension1, extension2;
2173
36
  cs_m68k* ext;
2174
36
  cs_m68k_op* op0;
2175
2176
36
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2177
2178
3
  extension1 = read_imm_16(info);
2179
3
  extension2 = read_imm_32(info);
2180
2181
3
  ext = build_init_op(info, M68K_INS_FTRAPF, 1, 2);
2182
2183
  // these are all in row with the extension so just doing a add here is fine
2184
3
  info->inst->Opcode += (extension1 & 0x2f);
2185
2186
3
  op0 = &ext->operands[0];
2187
2188
3
  op0->address_mode = M68K_AM_IMMEDIATE;
2189
3
  op0->type = M68K_OP_IMM;
2190
3
  op0->imm = extension2;
2191
3
}
2192
2193
static void d68040_cpush(m68k_info *info)
2194
13
{
2195
13
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2196
13
  build_cpush_cinv(info, M68K_INS_CPUSHL);
2197
13
}
2198
2199
static void d68000_dbra(m68k_info *info)
2200
22
{
2201
22
  build_dbxx(info, M68K_INS_DBRA, 0, make_int_16(read_imm_16(info)));
2202
22
}
2203
2204
static void d68000_dbcc(m68k_info *info)
2205
11
{
2206
11
  build_dbcc(info, 0, make_int_16(read_imm_16(info)));
2207
11
}
2208
2209
static void d68000_divs(m68k_info *info)
2210
187
{
2211
187
  build_er_1(info, M68K_INS_DIVS, 2);
2212
187
}
2213
2214
static void d68000_divu(m68k_info *info)
2215
21
{
2216
21
  build_er_1(info, M68K_INS_DIVU, 2);
2217
21
}
2218
2219
static void d68020_divl(m68k_info *info)
2220
173
{
2221
173
  uint32_t extension, insn_signed;
2222
173
  cs_m68k* ext;
2223
173
  cs_m68k_op* op0;
2224
173
  cs_m68k_op* op1;
2225
173
  uint32_t reg_0, reg_1;
2226
2227
173
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2228
2229
173
  extension = read_imm_16(info);
2230
173
  insn_signed = 0;
2231
2232
173
  if (BIT_B((extension)))
2233
4
    insn_signed = 1;
2234
2235
173
  ext = build_init_op(info, insn_signed ? M68K_INS_DIVS : M68K_INS_DIVU, 2, 4);
2236
2237
173
  op0 = &ext->operands[0];
2238
173
  op1 = &ext->operands[1];
2239
2240
173
  get_ea_mode_op(info, op0, info->ir, 4);
2241
2242
173
  reg_0 = extension & 7;
2243
173
  reg_1 = (extension >> 12) & 7;
2244
2245
173
  op1->address_mode = M68K_AM_NONE;
2246
173
  op1->type = M68K_OP_REG_PAIR;
2247
173
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
2248
173
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
2249
2250
173
  if ((reg_0 == reg_1) || !BIT_A(extension)) {
2251
169
    op1->type = M68K_OP_REG;
2252
169
    op1->reg = M68K_REG_D0 + reg_1;
2253
169
  }
2254
173
}
2255
2256
static void d68000_eor_8(m68k_info *info)
2257
35
{
2258
35
  build_re_1(info, M68K_INS_EOR, 1);
2259
35
}
2260
2261
static void d68000_eor_16(m68k_info *info)
2262
16
{
2263
16
  build_re_1(info, M68K_INS_EOR, 2);
2264
16
}
2265
2266
static void d68000_eor_32(m68k_info *info)
2267
24
{
2268
24
  build_re_1(info, M68K_INS_EOR, 4);
2269
24
}
2270
2271
static void d68000_eori_8(m68k_info *info)
2272
3
{
2273
3
  build_imm_ea(info, M68K_INS_EORI, 1, read_imm_8(info));
2274
3
}
2275
2276
static void d68000_eori_16(m68k_info *info)
2277
35
{
2278
35
  build_imm_ea(info, M68K_INS_EORI, 2, read_imm_16(info));
2279
35
}
2280
2281
static void d68000_eori_32(m68k_info *info)
2282
18
{
2283
18
  build_imm_ea(info, M68K_INS_EORI, 4, read_imm_32(info));
2284
18
}
2285
2286
static void d68000_eori_to_ccr(m68k_info *info)
2287
0
{
2288
0
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_8(info), 1, M68K_REG_CCR);
2289
0
}
2290
2291
static void d68000_eori_to_sr(m68k_info *info)
2292
0
{
2293
0
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_16(info), 2, M68K_REG_SR);
2294
0
}
2295
2296
static void d68000_exg_dd(m68k_info *info)
2297
128
{
2298
128
  build_r(info, M68K_INS_EXG, 4);
2299
128
}
2300
2301
static void d68000_exg_aa(m68k_info *info)
2302
16
{
2303
16
  cs_m68k_op* op0;
2304
16
  cs_m68k_op* op1;
2305
16
  cs_m68k* ext = build_init_op(info, M68K_INS_EXG, 2, 4);
2306
2307
16
  op0 = &ext->operands[0];
2308
16
  op1 = &ext->operands[1];
2309
2310
16
  op0->address_mode = M68K_AM_NONE;
2311
16
  op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
2312
2313
16
  op1->address_mode = M68K_AM_NONE;
2314
16
  op1->reg = M68K_REG_A0 + (info->ir & 7);
2315
16
}
2316
2317
static void d68000_exg_da(m68k_info *info)
2318
32
{
2319
32
  cs_m68k_op* op0;
2320
32
  cs_m68k_op* op1;
2321
32
  cs_m68k* ext = build_init_op(info, M68K_INS_EXG, 2, 4);
2322
2323
32
  op0 = &ext->operands[0];
2324
32
  op1 = &ext->operands[1];
2325
2326
32
  op0->address_mode = M68K_AM_NONE;
2327
32
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
2328
2329
32
  op1->address_mode = M68K_AM_NONE;
2330
32
  op1->reg = M68K_REG_A0 + (info->ir & 7);
2331
32
}
2332
2333
static void d68000_ext_16(m68k_info *info)
2334
0
{
2335
0
  build_d(info, M68K_INS_EXT, 2);
2336
0
}
2337
2338
static void d68000_ext_32(m68k_info *info)
2339
20
{
2340
20
  build_d(info, M68K_INS_EXT, 4);
2341
20
}
2342
2343
static void d68020_extb_32(m68k_info *info)
2344
189
{
2345
189
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2346
179
  build_d(info, M68K_INS_EXTB, 4);
2347
179
}
2348
2349
static void d68000_jmp(m68k_info *info)
2350
18
{
2351
18
  cs_m68k* ext = build_init_op(info, M68K_INS_JMP, 1, 0);
2352
18
  set_insn_group(info, M68K_GRP_JUMP);
2353
18
  get_ea_mode_op(info, &ext->operands[0], info->ir, 4);
2354
18
}
2355
2356
static void d68000_jsr(m68k_info *info)
2357
1
{
2358
1
  cs_m68k* ext = build_init_op(info, M68K_INS_JSR, 1, 0);
2359
1
  set_insn_group(info, M68K_GRP_JUMP);
2360
1
  get_ea_mode_op(info, &ext->operands[0], info->ir, 4);
2361
1
}
2362
2363
static void d68000_lea(m68k_info *info)
2364
146
{
2365
146
  build_ea_a(info, M68K_INS_LEA, 4);
2366
146
}
2367
2368
static void d68000_link_16(m68k_info *info)
2369
1
{
2370
1
  build_link(info, read_imm_16(info), 2);
2371
1
}
2372
2373
static void d68020_link_32(m68k_info *info)
2374
36
{
2375
36
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2376
0
  build_link(info, read_imm_32(info), 4);
2377
0
}
2378
2379
static void d68000_lsr_s_8(m68k_info *info)
2380
58
{
2381
58
  build_3bit_d(info, M68K_INS_LSR, 1);
2382
58
}
2383
2384
static void d68000_lsr_s_16(m68k_info *info)
2385
2
{
2386
2
  build_3bit_d(info, M68K_INS_LSR, 2);
2387
2
}
2388
2389
static void d68000_lsr_s_32(m68k_info *info)
2390
28
{
2391
28
  build_3bit_d(info, M68K_INS_LSR, 4);
2392
28
}
2393
2394
static void d68000_lsr_r_8(m68k_info *info)
2395
12
{
2396
12
  build_r(info, M68K_INS_LSR, 1);
2397
12
}
2398
2399
static void d68000_lsr_r_16(m68k_info *info)
2400
32
{
2401
32
  build_r(info, M68K_INS_LSR, 2);
2402
32
}
2403
2404
static void d68000_lsr_r_32(m68k_info *info)
2405
2
{
2406
2
  build_r(info, M68K_INS_LSR, 4);
2407
2
}
2408
2409
static void d68000_lsr_ea(m68k_info *info)
2410
0
{
2411
0
  build_ea(info, M68K_INS_LSR, 2);
2412
0
}
2413
2414
static void d68000_lsl_s_8(m68k_info *info)
2415
9
{
2416
9
  build_3bit_d(info, M68K_INS_LSL, 1);
2417
9
}
2418
2419
static void d68000_lsl_s_16(m68k_info *info)
2420
3
{
2421
3
  build_3bit_d(info, M68K_INS_LSL, 2);
2422
3
}
2423
2424
static void d68000_lsl_s_32(m68k_info *info)
2425
32
{
2426
32
  build_3bit_d(info, M68K_INS_LSL, 4);
2427
32
}
2428
2429
static void d68000_lsl_r_8(m68k_info *info)
2430
208
{
2431
208
  build_r(info, M68K_INS_LSL, 1);
2432
208
}
2433
2434
static void d68000_lsl_r_16(m68k_info *info)
2435
18
{
2436
18
  build_r(info, M68K_INS_LSL, 2);
2437
18
}
2438
2439
static void d68000_lsl_r_32(m68k_info *info)
2440
21
{
2441
21
  build_r(info, M68K_INS_LSL, 4);
2442
21
}
2443
2444
static void d68000_lsl_ea(m68k_info *info)
2445
2
{
2446
2
  build_ea(info, M68K_INS_LSL, 2);
2447
2
}
2448
2449
static void d68000_move_8(m68k_info *info)
2450
328
{
2451
328
  build_ea_ea(info, M68K_INS_MOVE, 1);
2452
328
}
2453
2454
static void d68000_move_16(m68k_info *info)
2455
289
{
2456
289
  build_ea_ea(info, M68K_INS_MOVE, 2);
2457
289
}
2458
2459
static void d68000_move_32(m68k_info *info)
2460
1.20k
{
2461
1.20k
  build_ea_ea(info, M68K_INS_MOVE, 4);
2462
1.20k
}
2463
2464
static void d68000_movea_16(m68k_info *info)
2465
76
{
2466
76
  build_ea_a(info, M68K_INS_MOVEA, 2);
2467
76
}
2468
2469
static void d68000_movea_32(m68k_info *info)
2470
83
{
2471
83
  build_ea_a(info, M68K_INS_MOVEA, 4);
2472
83
}
2473
2474
static void d68000_move_to_ccr(m68k_info *info)
2475
4
{
2476
4
  cs_m68k_op* op0;
2477
4
  cs_m68k_op* op1;
2478
4
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
2479
2480
4
  op0 = &ext->operands[0];
2481
4
  op1 = &ext->operands[1];
2482
2483
4
  get_ea_mode_op(info, op0, info->ir, 1);
2484
2485
4
  op1->address_mode = M68K_AM_NONE;
2486
4
  op1->reg = M68K_REG_CCR;
2487
4
}
2488
2489
static void d68010_move_fr_ccr(m68k_info *info)
2490
34
{
2491
34
  cs_m68k_op* op0;
2492
34
  cs_m68k_op* op1;
2493
34
  cs_m68k* ext;
2494
2495
34
  LIMIT_CPU_TYPES(info, M68010_PLUS);
2496
2497
34
  ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
2498
2499
34
  op0 = &ext->operands[0];
2500
34
  op1 = &ext->operands[1];
2501
2502
34
  op0->address_mode = M68K_AM_NONE;
2503
34
  op0->reg = M68K_REG_CCR;
2504
2505
34
  get_ea_mode_op(info, op1, info->ir, 1);
2506
34
}
2507
2508
static void d68000_move_fr_sr(m68k_info *info)
2509
3
{
2510
3
  cs_m68k_op* op0;
2511
3
  cs_m68k_op* op1;
2512
3
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
2513
2514
3
  op0 = &ext->operands[0];
2515
3
  op1 = &ext->operands[1];
2516
2517
3
  op0->address_mode = M68K_AM_NONE;
2518
3
  op0->reg = M68K_REG_SR;
2519
2520
3
  get_ea_mode_op(info, op1, info->ir, 2);
2521
3
}
2522
2523
static void d68000_move_to_sr(m68k_info *info)
2524
4
{
2525
4
  cs_m68k_op* op0;
2526
4
  cs_m68k_op* op1;
2527
4
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
2528
2529
4
  op0 = &ext->operands[0];
2530
4
  op1 = &ext->operands[1];
2531
2532
4
  get_ea_mode_op(info, op0, info->ir, 2);
2533
2534
4
  op1->address_mode = M68K_AM_NONE;
2535
4
  op1->reg = M68K_REG_SR;
2536
4
}
2537
2538
static void d68000_move_fr_usp(m68k_info *info)
2539
2
{
2540
2
  cs_m68k_op* op0;
2541
2
  cs_m68k_op* op1;
2542
2
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
2543
2544
2
  op0 = &ext->operands[0];
2545
2
  op1 = &ext->operands[1];
2546
2547
2
  op0->address_mode = M68K_AM_NONE;
2548
2
  op0->reg = M68K_REG_USP;
2549
2550
2
  op1->address_mode = M68K_AM_NONE;
2551
2
  op1->reg = M68K_REG_A0 + (info->ir & 7);
2552
2
}
2553
2554
static void d68000_move_to_usp(m68k_info *info)
2555
24
{
2556
24
  cs_m68k_op* op0;
2557
24
  cs_m68k_op* op1;
2558
24
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
2559
2560
24
  op0 = &ext->operands[0];
2561
24
  op1 = &ext->operands[1];
2562
2563
24
  op0->address_mode = M68K_AM_NONE;
2564
24
  op0->reg = M68K_REG_A0 + (info->ir & 7);
2565
2566
24
  op1->address_mode = M68K_AM_NONE;
2567
24
  op1->reg = M68K_REG_USP;
2568
24
}
2569
2570
static void d68010_movec(m68k_info *info)
2571
90
{
2572
90
  uint32_t extension;
2573
90
  m68k_reg reg;
2574
90
  cs_m68k* ext;
2575
90
  cs_m68k_op* op0;
2576
90
  cs_m68k_op* op1;
2577
2578
2579
90
  LIMIT_CPU_TYPES(info, M68010_PLUS);
2580
2581
90
  extension = read_imm_16(info);
2582
90
  reg = M68K_REG_INVALID;
2583
2584
90
  ext = build_init_op(info, M68K_INS_MOVEC, 2, 0);
2585
2586
90
  op0 = &ext->operands[0];
2587
90
  op1 = &ext->operands[1];
2588
2589
90
  switch (extension & 0xfff) {
2590
0
    case 0x000: reg = M68K_REG_SFC; break;
2591
0
    case 0x001: reg = M68K_REG_DFC; break;
2592
0
    case 0x800: reg = M68K_REG_USP; break;
2593
2
    case 0x801: reg = M68K_REG_VBR; break;
2594
16
    case 0x002: reg = M68K_REG_CACR; break;
2595
2
    case 0x802: reg = M68K_REG_CAAR; break;
2596
0
    case 0x803: reg = M68K_REG_MSP; break;
2597
9
    case 0x804: reg = M68K_REG_ISP; break;
2598
0
    case 0x003: reg = M68K_REG_TC; break;
2599
20
    case 0x004: reg = M68K_REG_ITT0; break;
2600
9
    case 0x005: reg = M68K_REG_ITT1; break;
2601
16
    case 0x006: reg = M68K_REG_DTT0; break;
2602
0
    case 0x007: reg = M68K_REG_DTT1; break;
2603
1
    case 0x805: reg = M68K_REG_MMUSR; break;
2604
0
    case 0x806: reg = M68K_REG_URP; break;
2605
0
    case 0x807: reg = M68K_REG_SRP; break;
2606
90
  }
2607
2608
90
  if (BIT_0(info->ir)) {
2609
31
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
2610
31
    op1->reg = reg;
2611
59
  } else {
2612
59
    op0->reg = reg;
2613
59
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
2614
59
  }
2615
90
}
2616
2617
static void d68000_movem_pd_16(m68k_info *info)
2618
5
{
2619
5
  build_movem_re(info, M68K_INS_MOVEM, 2);
2620
5
}
2621
2622
static void d68000_movem_pd_32(m68k_info *info)
2623
35
{
2624
35
  build_movem_re(info, M68K_INS_MOVEM, 4);
2625
35
}
2626
2627
static void d68000_movem_er_16(m68k_info *info)
2628
42
{
2629
42
  build_movem_er(info, M68K_INS_MOVEM, 2);
2630
42
}
2631
2632
static void d68000_movem_er_32(m68k_info *info)
2633
65
{
2634
65
  build_movem_er(info, M68K_INS_MOVEM, 4);
2635
65
}
2636
2637
static void d68000_movem_re_16(m68k_info *info)
2638
109
{
2639
109
  build_movem_re(info, M68K_INS_MOVEM, 2);
2640
109
}
2641
2642
static void d68000_movem_re_32(m68k_info *info)
2643
20
{
2644
20
  build_movem_re(info, M68K_INS_MOVEM, 4);
2645
20
}
2646
2647
static void d68000_movep_re_16(m68k_info *info)
2648
6
{
2649
6
  build_movep_re(info, 2);
2650
6
}
2651
2652
static void d68000_movep_re_32(m68k_info *info)
2653
8
{
2654
8
  build_movep_re(info, 4);
2655
8
}
2656
2657
static void d68000_movep_er_16(m68k_info *info)
2658
104
{
2659
104
  build_movep_er(info, 2);
2660
104
}
2661
2662
static void d68000_movep_er_32(m68k_info *info)
2663
146
{
2664
146
  build_movep_er(info, 4);
2665
146
}
2666
2667
static void d68010_moves_8(m68k_info *info)
2668
8
{
2669
8
  LIMIT_CPU_TYPES(info, M68010_PLUS);
2670
4
  build_moves(info, 1);
2671
4
}
2672
2673
static void d68010_moves_16(m68k_info *info)
2674
24
{
2675
  //uint32_t extension;
2676
24
  LIMIT_CPU_TYPES(info, M68010_PLUS);
2677
8
  build_moves(info, 2);
2678
8
}
2679
2680
static void d68010_moves_32(m68k_info *info)
2681
27
{
2682
27
  LIMIT_CPU_TYPES(info, M68010_PLUS);
2683
18
  build_moves(info, 4);
2684
18
}
2685
2686
static void d68000_moveq(m68k_info *info)
2687
459
{
2688
459
  cs_m68k_op* op0;
2689
459
  cs_m68k_op* op1;
2690
2691
459
  cs_m68k* ext = build_init_op(info, M68K_INS_MOVEQ, 2, 0);
2692
2693
459
  op0 = &ext->operands[0];
2694
459
  op1 = &ext->operands[1];
2695
2696
459
  op0->type = M68K_OP_IMM;
2697
459
  op0->address_mode = M68K_AM_IMMEDIATE;
2698
459
  op0->imm = (info->ir & 0xff);
2699
2700
459
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
2701
459
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
2702
459
}
2703
2704
static void d68040_move16_pi_pi(m68k_info *info)
2705
5
{
2706
5
  int data[] = { info->ir & 7, (read_imm_16(info) >> 12) & 7 };
2707
5
  int modes[] = { M68K_AM_REGI_ADDR_POST_INC, M68K_AM_REGI_ADDR_POST_INC };
2708
2709
5
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2710
2711
1
  build_move16(info, data, modes);
2712
1
}
2713
2714
static void d68040_move16_pi_al(m68k_info *info)
2715
14
{
2716
14
  int data[] = { info->ir & 7, read_imm_32(info) };
2717
14
  int modes[] = { M68K_AM_REGI_ADDR_POST_INC, M68K_AM_ABSOLUTE_DATA_LONG };
2718
2719
14
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2720
2721
1
  build_move16(info, data, modes);
2722
1
}
2723
2724
static void d68040_move16_al_pi(m68k_info *info)
2725
3
{
2726
3
  int data[] = { read_imm_32(info), info->ir & 7 };
2727
3
  int modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REGI_ADDR_POST_INC };
2728
2729
3
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2730
2731
1
  build_move16(info, data, modes);
2732
1
}
2733
2734
static void d68040_move16_ai_al(m68k_info *info)
2735
12
{
2736
12
  int data[] = { info->ir & 7, read_imm_32(info) };
2737
12
  int modes[] = { M68K_AM_REG_DIRECT_ADDR, M68K_AM_ABSOLUTE_DATA_LONG };
2738
2739
12
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2740
2741
5
  build_move16(info, data, modes);
2742
5
}
2743
2744
static void d68040_move16_al_ai(m68k_info *info)
2745
6
{
2746
6
  int data[] = { read_imm_32(info), info->ir & 7 };
2747
6
  int modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REG_DIRECT_ADDR };
2748
2749
6
  LIMIT_CPU_TYPES(info, M68040_PLUS);
2750
2751
6
  build_move16(info, data, modes);
2752
6
}
2753
2754
static void d68000_muls(m68k_info *info)
2755
13
{
2756
13
  build_er_1(info, M68K_INS_MULS, 2);
2757
13
}
2758
2759
static void d68000_mulu(m68k_info *info)
2760
76
{
2761
76
  build_er_1(info, M68K_INS_MULU, 2);
2762
76
}
2763
2764
static void d68020_mull(m68k_info *info)
2765
125
{
2766
125
  uint32_t extension, insn_signed;
2767
125
  cs_m68k* ext;
2768
125
  cs_m68k_op* op0;
2769
125
  cs_m68k_op* op1;
2770
125
  uint32_t reg_0, reg_1;
2771
2772
125
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2773
2774
125
  extension = read_imm_16(info);
2775
125
  insn_signed = 0;
2776
2777
125
  if (BIT_B((extension)))
2778
4
    insn_signed = 1;
2779
2780
125
  ext = build_init_op(info, insn_signed ? M68K_INS_MULS : M68K_INS_MULU, 2, 4);
2781
2782
125
  op0 = &ext->operands[0];
2783
125
  op1 = &ext->operands[1];
2784
2785
125
  get_ea_mode_op(info, op0, info->ir, 4);
2786
2787
125
  reg_0 = extension & 7;
2788
125
  reg_1 = (extension >> 12) & 7;
2789
2790
125
  op1->address_mode = M68K_AM_NONE;
2791
125
  op1->type = M68K_OP_REG_PAIR;
2792
125
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
2793
125
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
2794
2795
125
  if (!BIT_A(extension)) {
2796
121
    op1->type = M68K_OP_REG;
2797
121
    op1->reg = M68K_REG_D0 + reg_1;
2798
121
  }
2799
125
}
2800
2801
static void d68000_nbcd(m68k_info *info)
2802
53
{
2803
53
  build_ea(info, M68K_INS_NBCD, 1);
2804
53
}
2805
2806
static void d68000_neg_8(m68k_info *info)
2807
2
{
2808
2
  build_ea(info, M68K_INS_NEG, 1);
2809
2
}
2810
2811
static void d68000_neg_16(m68k_info *info)
2812
15
{
2813
15
  build_ea(info, M68K_INS_NEG, 2);
2814
15
}
2815
2816
static void d68000_neg_32(m68k_info *info)
2817
156
{
2818
156
  build_ea(info, M68K_INS_NEG, 4);
2819
156
}
2820
2821
static void d68000_negx_8(m68k_info *info)
2822
16
{
2823
16
  build_ea(info, M68K_INS_NEGX, 1);
2824
16
}
2825
2826
static void d68000_negx_16(m68k_info *info)
2827
1
{
2828
1
  build_ea(info, M68K_INS_NEGX, 2);
2829
1
}
2830
2831
static void d68000_negx_32(m68k_info *info)
2832
187
{
2833
187
  build_ea(info, M68K_INS_NEGX, 4);
2834
187
}
2835
2836
static void d68000_nop(m68k_info *info)
2837
0
{
2838
0
  MCInst_setOpcode(info->inst, M68K_INS_NOP);
2839
0
}
2840
2841
static void d68000_not_8(m68k_info *info)
2842
139
{
2843
139
  build_ea(info, M68K_INS_NOT, 1);
2844
139
}
2845
2846
static void d68000_not_16(m68k_info *info)
2847
134
{
2848
134
  build_ea(info, M68K_INS_NOT, 2);
2849
134
}
2850
2851
static void d68000_not_32(m68k_info *info)
2852
5
{
2853
5
  build_ea(info, M68K_INS_NOT, 4);
2854
5
}
2855
2856
static void d68000_or_er_8(m68k_info *info)
2857
37
{
2858
37
  build_er_1(info, M68K_INS_OR, 1);
2859
37
}
2860
2861
static void d68000_or_er_16(m68k_info *info)
2862
41
{
2863
41
  build_er_1(info, M68K_INS_OR, 2);
2864
41
}
2865
2866
static void d68000_or_er_32(m68k_info *info)
2867
213
{
2868
213
  build_er_1(info, M68K_INS_OR, 4);
2869
213
}
2870
2871
static void d68000_or_re_8(m68k_info *info)
2872
24
{
2873
24
  build_re_1(info, M68K_INS_OR, 1);
2874
24
}
2875
2876
static void d68000_or_re_16(m68k_info *info)
2877
14
{
2878
14
  build_re_1(info, M68K_INS_OR, 2);
2879
14
}
2880
2881
static void d68000_or_re_32(m68k_info *info)
2882
150
{
2883
150
  build_re_1(info, M68K_INS_OR, 4);
2884
150
}
2885
2886
static void d68000_ori_8(m68k_info *info)
2887
820
{
2888
820
  build_imm_ea(info, M68K_INS_ORI, 1, read_imm_8(info));
2889
820
}
2890
2891
static void d68000_ori_16(m68k_info *info)
2892
91
{
2893
91
  build_imm_ea(info, M68K_INS_ORI, 2, read_imm_16(info));
2894
91
}
2895
2896
static void d68000_ori_32(m68k_info *info)
2897
52
{
2898
52
  build_imm_ea(info, M68K_INS_ORI, 4, read_imm_32(info));
2899
52
}
2900
2901
static void d68000_ori_to_ccr(m68k_info *info)
2902
0
{
2903
0
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_8(info), 1, M68K_REG_CCR);
2904
0
}
2905
2906
static void d68000_ori_to_sr(m68k_info *info)
2907
6
{
2908
6
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_16(info), 2, M68K_REG_SR);
2909
6
}
2910
2911
static void d68020_pack_rr(m68k_info *info)
2912
72
{
2913
72
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2914
72
  build_rr(info, M68K_INS_PACK, 0, read_imm_16(info));
2915
72
}
2916
2917
static void d68020_pack_mm(m68k_info *info)
2918
97
{
2919
97
  LIMIT_CPU_TYPES(info, M68020_PLUS);
2920
96
  build_mm(info, M68K_INS_PACK, 0, read_imm_16(info));
2921
96
}
2922
2923
static void d68000_pea(m68k_info *info)
2924
138
{
2925
138
  build_ea(info, M68K_INS_PEA, 4);
2926
138
}
2927
2928
static void d68000_reset(m68k_info *info)
2929
32
{
2930
32
  MCInst_setOpcode(info->inst, M68K_INS_RESET);
2931
32
}
2932
2933
static void d68000_ror_s_8(m68k_info *info)
2934
3
{
2935
3
  build_3bit_d(info, M68K_INS_ROR, 1);
2936
3
}
2937
2938
static void d68000_ror_s_16(m68k_info *info)
2939
5
{
2940
5
  build_3bit_d(info, M68K_INS_ROR, 2);
2941
5
}
2942
2943
static void d68000_ror_s_32(m68k_info *info)
2944
3
{
2945
3
  build_3bit_d(info, M68K_INS_ROR, 4);
2946
3
}
2947
2948
static void d68000_ror_r_8(m68k_info *info)
2949
32
{
2950
32
  build_r(info, M68K_INS_ROR, 1);
2951
32
}
2952
2953
static void d68000_ror_r_16(m68k_info *info)
2954
1
{
2955
1
  build_r(info, M68K_INS_ROR, 2);
2956
1
}
2957
2958
static void d68000_ror_r_32(m68k_info *info)
2959
0
{
2960
0
  build_r(info, M68K_INS_ROR, 4);
2961
0
}
2962
2963
static void d68000_ror_ea(m68k_info *info)
2964
10
{
2965
10
  build_ea(info, M68K_INS_ROR, 2);
2966
10
}
2967
2968
static void d68000_rol_s_8(m68k_info *info)
2969
46
{
2970
46
  build_3bit_d(info, M68K_INS_ROL, 1);
2971
46
}
2972
2973
static void d68000_rol_s_16(m68k_info *info)
2974
54
{
2975
54
  build_3bit_d(info, M68K_INS_ROL, 2);
2976
54
}
2977
2978
static void d68000_rol_s_32(m68k_info *info)
2979
3
{
2980
3
  build_3bit_d(info, M68K_INS_ROL, 4);
2981
3
}
2982
2983
static void d68000_rol_r_8(m68k_info *info)
2984
131
{
2985
131
  build_r(info, M68K_INS_ROL, 1);
2986
131
}
2987
2988
static void d68000_rol_r_16(m68k_info *info)
2989
0
{
2990
0
  build_r(info, M68K_INS_ROL, 2);
2991
0
}
2992
2993
static void d68000_rol_r_32(m68k_info *info)
2994
7
{
2995
7
  build_r(info, M68K_INS_ROL, 4);
2996
7
}
2997
2998
static void d68000_rol_ea(m68k_info *info)
2999
3
{
3000
3
  build_ea(info, M68K_INS_ROL, 2);
3001
3
}
3002
3003
static void d68000_roxr_s_8(m68k_info *info)
3004
18
{
3005
18
  build_3bit_d(info, M68K_INS_ROXR, 1);
3006
18
}
3007
3008
static void d68000_roxr_s_16(m68k_info *info)
3009
132
{
3010
132
  build_3bit_d(info, M68K_INS_ROXR, 2);
3011
132
}
3012
3013
static void d68000_roxr_s_32(m68k_info *info)
3014
6
{
3015
6
  build_3bit_d(info, M68K_INS_ROXR, 4);
3016
6
}
3017
3018
static void d68000_roxr_r_8(m68k_info *info)
3019
6
{
3020
6
  build_3bit_d(info, M68K_INS_ROXR, 4);
3021
6
}
3022
3023
static void d68000_roxr_r_16(m68k_info *info)
3024
0
{
3025
0
  build_r(info, M68K_INS_ROXR, 2);
3026
0
}
3027
3028
static void d68000_roxr_r_32(m68k_info *info)
3029
14
{
3030
14
  build_r(info, M68K_INS_ROXR, 4);
3031
14
}
3032
3033
static void d68000_roxr_ea(m68k_info *info)
3034
0
{
3035
0
  build_ea(info, M68K_INS_ROXR, 2);
3036
0
}
3037
3038
static void d68000_roxl_s_8(m68k_info *info)
3039
11
{
3040
11
  build_3bit_d(info, M68K_INS_ROXL, 1);
3041
11
}
3042
3043
static void d68000_roxl_s_16(m68k_info *info)
3044
8
{
3045
8
  build_3bit_d(info, M68K_INS_ROXL, 2);
3046
8
}
3047
3048
static void d68000_roxl_s_32(m68k_info *info)
3049
3
{
3050
3
  build_3bit_d(info, M68K_INS_ROXL, 4);
3051
3
}
3052
3053
static void d68000_roxl_r_8(m68k_info *info)
3054
1
{
3055
1
  build_r(info, M68K_INS_ROXL, 1);
3056
1
}
3057
3058
static void d68000_roxl_r_16(m68k_info *info)
3059
20
{
3060
20
  build_r(info, M68K_INS_ROXL, 2);
3061
20
}
3062
3063
static void d68000_roxl_r_32(m68k_info *info)
3064
16
{
3065
16
  build_r(info, M68K_INS_ROXL, 4);
3066
16
}
3067
3068
static void d68000_roxl_ea(m68k_info *info)
3069
0
{
3070
0
  build_ea(info, M68K_INS_ROXL, 2);
3071
0
}
3072
3073
static void d68010_rtd(m68k_info *info)
3074
5
{
3075
5
  set_insn_group(info, M68K_GRP_RET);
3076
5
  LIMIT_CPU_TYPES(info, M68010_PLUS);
3077
2
  build_absolute_jump_with_immediate(info, M68K_INS_RTD, 0, read_imm_16(info));
3078
2
}
3079
3080
static void d68000_rte(m68k_info *info)
3081
0
{
3082
0
  set_insn_group(info, M68K_GRP_IRET);
3083
0
  MCInst_setOpcode(info->inst, M68K_INS_RTE);
3084
0
}
3085
3086
static void d68020_rtm(m68k_info *info)
3087
7
{
3088
7
  cs_m68k* ext;
3089
7
  cs_m68k_op* op;
3090
3091
7
  set_insn_group(info, M68K_GRP_RET);
3092
3093
7
  LIMIT_CPU_TYPES(info, M68020_ONLY);
3094
3095
0
  build_absolute_jump_with_immediate(info, M68K_INS_RTM, 0, 0);
3096
3097
0
  ext = &info->extension;
3098
0
  op = &ext->operands[0];
3099
3100
0
  op->address_mode = M68K_AM_NONE;
3101
0
  op->type = M68K_OP_REG;
3102
3103
0
  if (BIT_3(info->ir)) {
3104
0
    op->reg = M68K_REG_A0 + (info->ir & 7);
3105
0
  } else {
3106
0
    op->reg = M68K_REG_D0 + (info->ir & 7);
3107
0
  }
3108
0
}
3109
3110
static void d68000_rtr(m68k_info *info)
3111
33
{
3112
33
  set_insn_group(info, M68K_GRP_RET);
3113
33
  MCInst_setOpcode(info->inst, M68K_INS_RTR);
3114
33
}
3115
3116
static void d68000_rts(m68k_info *info)
3117
0
{
3118
0
  set_insn_group(info, M68K_GRP_RET);
3119
0
  MCInst_setOpcode(info->inst, M68K_INS_RTS);
3120
0
}
3121
3122
static void d68000_sbcd_rr(m68k_info *info)
3123
30
{
3124
30
  build_rr(info, M68K_INS_SBCD, 1, 0);
3125
30
}
3126
3127
static void d68000_sbcd_mm(m68k_info *info)
3128
35
{
3129
35
  build_mm(info, M68K_INS_SBCD, 0, read_imm_16(info));
3130
35
}
3131
3132
static void d68000_scc(m68k_info *info)
3133
191
{
3134
191
  cs_m68k* ext = build_init_op(info, s_scc_lut[(info->ir >> 8) & 0xf], 1, 1);
3135
191
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
3136
191
}
3137
3138
static void d68000_stop(m68k_info *info)
3139
48
{
3140
48
  build_absolute_jump_with_immediate(info, M68K_INS_STOP, 0, read_imm_16(info));
3141
48
}
3142
3143
static void d68000_sub_er_8(m68k_info *info)
3144
237
{
3145
237
  build_er_1(info, M68K_INS_SUB, 1);
3146
237
}
3147
3148
static void d68000_sub_er_16(m68k_info *info)
3149
56
{
3150
56
  build_er_1(info, M68K_INS_SUB, 2);
3151
56
}
3152
3153
static void d68000_sub_er_32(m68k_info *info)
3154
94
{
3155
94
  build_er_1(info, M68K_INS_SUB, 4);
3156
94
}
3157
3158
static void d68000_sub_re_8(m68k_info *info)
3159
190
{
3160
190
  build_re_1(info, M68K_INS_SUB, 1);
3161
190
}
3162
3163
static void d68000_sub_re_16(m68k_info *info)
3164
23
{
3165
23
  build_re_1(info, M68K_INS_SUB, 2);
3166
23
}
3167
3168
static void d68000_sub_re_32(m68k_info *info)
3169
57
{
3170
57
  build_re_1(info, M68K_INS_SUB, 4);
3171
57
}
3172
3173
static void d68000_suba_16(m68k_info *info)
3174
169
{
3175
169
  build_ea_a(info, M68K_INS_SUBA, 2);
3176
169
}
3177
3178
static void d68000_suba_32(m68k_info *info)
3179
8
{
3180
8
  build_ea_a(info, M68K_INS_SUBA, 4);
3181
8
}
3182
3183
static void d68000_subi_8(m68k_info *info)
3184
153
{
3185
153
  build_imm_ea(info, M68K_INS_SUBI, 1, read_imm_8(info));
3186
153
}
3187
3188
static void d68000_subi_16(m68k_info *info)
3189
6
{
3190
6
  build_imm_ea(info, M68K_INS_SUBI, 2, read_imm_16(info));
3191
6
}
3192
3193
static void d68000_subi_32(m68k_info *info)
3194
11
{
3195
11
  build_imm_ea(info, M68K_INS_SUBI, 4, read_imm_32(info));
3196
11
}
3197
3198
static void d68000_subq_8(m68k_info *info)
3199
18
{
3200
18
  build_3bit_ea(info, M68K_INS_SUBQ, 1);
3201
18
}
3202
3203
static void d68000_subq_16(m68k_info *info)
3204
99
{
3205
99
  build_3bit_ea(info, M68K_INS_SUBQ, 2);
3206
99
}
3207
3208
static void d68000_subq_32(m68k_info *info)
3209
25
{
3210
25
  build_3bit_ea(info, M68K_INS_SUBQ, 4);
3211
25
}
3212
3213
static void d68000_subx_rr_8(m68k_info *info)
3214
137
{
3215
137
  build_rr(info, M68K_INS_SUBX, 1, 0);
3216
137
}
3217
3218
static void d68000_subx_rr_16(m68k_info *info)
3219
27
{
3220
27
  build_rr(info, M68K_INS_SUBX, 2, 0);
3221
27
}
3222
3223
static void d68000_subx_rr_32(m68k_info *info)
3224
14
{
3225
14
  build_rr(info, M68K_INS_SUBX, 4, 0);
3226
14
}
3227
3228
static void d68000_subx_mm_8(m68k_info *info)
3229
1
{
3230
1
  build_mm(info, M68K_INS_SUBX, 1, 0);
3231
1
}
3232
3233
static void d68000_subx_mm_16(m68k_info *info)
3234
30
{
3235
30
  build_mm(info, M68K_INS_SUBX, 2, 0);
3236
30
}
3237
3238
static void d68000_subx_mm_32(m68k_info *info)
3239
147
{
3240
147
  build_mm(info, M68K_INS_SUBX, 4, 0);
3241
147
}
3242
3243
static void d68000_swap(m68k_info *info)
3244
2
{
3245
2
  build_d(info, M68K_INS_SWAP, 0);
3246
2
}
3247
3248
static void d68000_tas(m68k_info *info)
3249
77
{
3250
77
  build_ea(info, M68K_INS_TAS, 1);
3251
77
}
3252
3253
static void d68000_trap(m68k_info *info)
3254
888
{
3255
888
  build_absolute_jump_with_immediate(info, M68K_INS_TRAP, 0, info->ir&0xf);
3256
888
}
3257
3258
static void d68020_trapcc_0(m68k_info *info)
3259
1
{
3260
1
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3261
0
  build_trap(info, 0, 0);
3262
3263
0
  info->extension.op_count = 0;
3264
0
}
3265
3266
static void d68020_trapcc_16(m68k_info *info)
3267
34
{
3268
34
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3269
18
  build_trap(info, 2, read_imm_16(info));
3270
18
}
3271
3272
static void d68020_trapcc_32(m68k_info *info)
3273
36
{
3274
36
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3275
33
  build_trap(info, 4, read_imm_32(info));
3276
33
}
3277
3278
static void d68000_trapv(m68k_info *info)
3279
128
{
3280
128
  MCInst_setOpcode(info->inst, M68K_INS_TRAPV);
3281
128
}
3282
3283
static void d68000_tst_8(m68k_info *info)
3284
11
{
3285
11
  build_ea(info, M68K_INS_TST, 1);
3286
11
}
3287
3288
static void d68020_tst_pcdi_8(m68k_info *info)
3289
53
{
3290
53
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3291
53
  build_ea(info, M68K_INS_TST, 1);
3292
53
}
3293
3294
static void d68020_tst_pcix_8(m68k_info *info)
3295
27
{
3296
27
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3297
26
  build_ea(info, M68K_INS_TST, 1);
3298
26
}
3299
3300
static void d68020_tst_i_8(m68k_info *info)
3301
0
{
3302
0
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3303
0
  build_ea(info, M68K_INS_TST, 1);
3304
0
}
3305
3306
static void d68000_tst_16(m68k_info *info)
3307
5
{
3308
5
  build_ea(info, M68K_INS_TST, 2);
3309
5
}
3310
3311
static void d68020_tst_a_16(m68k_info *info)
3312
18
{
3313
18
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3314
7
  build_ea(info, M68K_INS_TST, 2);
3315
7
}
3316
3317
static void d68020_tst_pcdi_16(m68k_info *info)
3318
33
{
3319
33
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3320
33
  build_ea(info, M68K_INS_TST, 2);
3321
33
}
3322
3323
static void d68020_tst_pcix_16(m68k_info *info)
3324
261
{
3325
261
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3326
133
  build_ea(info, M68K_INS_TST, 2);
3327
133
}
3328
3329
static void d68020_tst_i_16(m68k_info *info)
3330
6
{
3331
6
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3332
0
  build_ea(info, M68K_INS_TST, 2);
3333
0
}
3334
3335
static void d68000_tst_32(m68k_info *info)
3336
7
{
3337
7
  build_ea(info, M68K_INS_TST, 4);
3338
7
}
3339
3340
static void d68020_tst_a_32(m68k_info *info)
3341
128
{
3342
128
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3343
128
  build_ea(info, M68K_INS_TST, 4);
3344
128
}
3345
3346
static void d68020_tst_pcdi_32(m68k_info *info)
3347
17
{
3348
17
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3349
0
  build_ea(info, M68K_INS_TST, 4);
3350
0
}
3351
3352
static void d68020_tst_pcix_32(m68k_info *info)
3353
97
{
3354
97
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3355
8
  build_ea(info, M68K_INS_TST, 4);
3356
8
}
3357
3358
static void d68020_tst_i_32(m68k_info *info)
3359
0
{
3360
0
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3361
0
  build_ea(info, M68K_INS_TST, 4);
3362
0
}
3363
3364
static void d68000_unlk(m68k_info *info)
3365
141
{
3366
141
  cs_m68k_op* op;
3367
141
  cs_m68k* ext = build_init_op(info, M68K_INS_UNLK, 1, 0);
3368
3369
141
  op = &ext->operands[0];
3370
3371
141
  op->address_mode = M68K_AM_REG_DIRECT_ADDR;
3372
141
  op->reg = M68K_REG_A0 + (info->ir & 7);
3373
141
}
3374
3375
static void d68020_unpk_rr(m68k_info *info)
3376
28
{
3377
28
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3378
19
  build_rr(info, M68K_INS_UNPK, 0, read_imm_16(info));
3379
19
}
3380
3381
static void d68020_unpk_mm(m68k_info *info)
3382
4
{
3383
4
  LIMIT_CPU_TYPES(info, M68020_PLUS);
3384
2
  build_mm(info, M68K_INS_UNPK, 0, read_imm_16(info));
3385
2
}
3386
3387
/* This table is auto-generated. Look in contrib/m68k_instruction_tbl_gen for more info */
3388
#include "M68KInstructionTable.inc"
3389
3390
static int instruction_is_valid(m68k_info *info, const unsigned int word_check)
3391
21.7k
{
3392
21.7k
  const unsigned int instruction = info->ir;
3393
21.7k
  const instruction_struct *i = &g_instruction_table[instruction];
3394
3395
21.7k
  if ( (i->word2_mask && ((word_check & i->word2_mask) != i->word2_match)) ||
3396
21.7k
    (i->instruction == d68000_invalid) ) {
3397
51
    d68000_invalid(info);
3398
51
    return 0;
3399
51
  }
3400
3401
21.7k
  return 1;
3402
21.7k
}
3403
3404
static int exists_reg_list(uint16_t *regs, uint8_t count, m68k_reg reg)
3405
28.9k
{
3406
28.9k
  uint8_t i;
3407
3408
44.2k
  for (i = 0; i < count; ++i) {
3409
15.7k
    if (regs[i] == (uint16_t)reg)
3410
528
      return 1;
3411
15.7k
  }
3412
3413
28.4k
  return 0;
3414
28.9k
}
3415
3416
static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write)
3417
30.5k
{
3418
30.5k
  if (reg == M68K_REG_INVALID)
3419
1.55k
    return;
3420
3421
28.9k
  if (write)
3422
17.4k
  {
3423
17.4k
    if (exists_reg_list(info->regs_write, info->regs_write_count, reg))
3424
442
      return;
3425
3426
17.0k
    info->regs_write[info->regs_write_count] = (uint16_t)reg;
3427
17.0k
    info->regs_write_count++;
3428
17.0k
  }
3429
11.5k
  else
3430
11.5k
  {
3431
11.5k
    if (exists_reg_list(info->regs_read, info->regs_read_count, reg))
3432
86
      return;
3433
3434
11.4k
    info->regs_read[info->regs_read_count] = (uint16_t)reg;
3435
11.4k
    info->regs_read_count++;
3436
11.4k
  }
3437
28.9k
}
3438
3439
static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write)
3440
9.36k
{
3441
9.36k
  switch (op->address_mode) {
3442
22
    case M68K_AM_REG_DIRECT_ADDR:
3443
22
    case M68K_AM_REG_DIRECT_DATA:
3444
22
      add_reg_to_rw_list(info, op->reg, write);
3445
22
      break;
3446
3447
1.30k
    case M68K_AM_REGI_ADDR_POST_INC:
3448
4.35k
    case M68K_AM_REGI_ADDR_PRE_DEC:
3449
4.35k
      add_reg_to_rw_list(info, op->reg, 1);
3450
4.35k
      break;
3451
3452
2.11k
    case M68K_AM_REGI_ADDR:
3453
3.15k
    case M68K_AM_REGI_ADDR_DISP:
3454
3.15k
      add_reg_to_rw_list(info, op->reg, 0);
3455
3.15k
      break;
3456
3457
466
    case M68K_AM_AREGI_INDEX_8_BIT_DISP:
3458
848
    case M68K_AM_AREGI_INDEX_BASE_DISP:
3459
921
    case M68K_AM_MEMI_POST_INDEX:
3460
974
    case M68K_AM_MEMI_PRE_INDEX:
3461
1.02k
    case M68K_AM_PCI_INDEX_8_BIT_DISP:
3462
1.02k
    case M68K_AM_PCI_INDEX_BASE_DISP:
3463
1.27k
    case M68K_AM_PC_MEMI_PRE_INDEX:
3464
1.27k
    case M68K_AM_PC_MEMI_POST_INDEX:
3465
1.27k
      add_reg_to_rw_list(info, op->mem.index_reg, 0);
3466
1.27k
      add_reg_to_rw_list(info, op->mem.base_reg, 0);
3467
1.27k
      break;
3468
3469
    // no register(s) in the other addressing modes
3470
548
    default:
3471
548
      break;
3472
9.36k
  }
3473
9.36k
}
3474
3475
static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits, int write)
3476
975
{
3477
975
  int i;
3478
3479
8.77k
  for (i = 0; i < 8; ++i) {
3480
7.80k
    if (bits & (1 << i)) {
3481
2.56k
      add_reg_to_rw_list(info, reg_start + i, write);
3482
2.56k
    }
3483
7.80k
  }
3484
975
}
3485
3486
static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write)
3487
325
{
3488
325
  uint32_t bits = op->register_bits;
3489
325
  update_bits_range(info, M68K_REG_D0, bits & 0xff, write);
3490
325
  update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write);
3491
325
  update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write);
3492
325
}
3493
3494
static void update_op_reg_list(m68k_info *info, cs_m68k_op *op, int write)
3495
36.4k
{
3496
36.4k
  switch ((int)op->type) {
3497
17.7k
    case M68K_OP_REG:
3498
17.7k
      add_reg_to_rw_list(info, op->reg, write);
3499
17.7k
      break;
3500
3501
9.36k
    case M68K_OP_MEM:
3502
9.36k
      update_am_reg_list(info, op, write);
3503
9.36k
      break;
3504
3505
325
    case M68K_OP_REG_BITS:
3506
325
      update_reg_list_regbits(info, op, write);
3507
325
      break;
3508
3509
56
    case M68K_OP_REG_PAIR:
3510
56
      add_reg_to_rw_list(info, op->reg_pair.reg_0, write);
3511
56
      add_reg_to_rw_list(info, op->reg_pair.reg_1, write);
3512
56
      break;
3513
36.4k
  }
3514
36.4k
}
3515
3516
static void build_regs_read_write_counts(m68k_info *info)
3517
21.7k
{
3518
21.7k
  int i;
3519
3520
21.7k
  if (!info->extension.op_count)
3521
328
    return;
3522
3523
21.3k
  if (info->extension.op_count == 1) {
3524
6.50k
    update_op_reg_list(info, &info->extension.operands[0], 1);
3525
14.8k
  } else {
3526
    // first operand is always read
3527
14.8k
    update_op_reg_list(info, &info->extension.operands[0], 0);
3528
3529
    // remaning write
3530
29.9k
    for (i = 1; i < info->extension.op_count; ++i)
3531
15.1k
      update_op_reg_list(info, &info->extension.operands[i], 1);
3532
14.8k
  }
3533
21.3k
}
3534
3535
static void m68k_setup_internals(m68k_info* info, MCInst* inst, unsigned int pc, unsigned int cpu_type)
3536
21.7k
{
3537
21.7k
  info->inst = inst;
3538
21.7k
  info->pc = pc;
3539
21.7k
  info->ir = 0;
3540
21.7k
  info->type = cpu_type;
3541
21.7k
  info->address_mask = 0xffffffff;
3542
3543
21.7k
  switch(info->type) {
3544
6.23k
    case M68K_CPU_TYPE_68000:
3545
6.23k
      info->type = TYPE_68000;
3546
6.23k
      info->address_mask = 0x00ffffff;
3547
6.23k
      break;
3548
0
    case M68K_CPU_TYPE_68010:
3549
0
      info->type = TYPE_68010;
3550
0
      info->address_mask = 0x00ffffff;
3551
0
      break;
3552
0
    case M68K_CPU_TYPE_68EC020:
3553
0
      info->type = TYPE_68020;
3554
0
      info->address_mask = 0x00ffffff;
3555
0
      break;
3556
0
    case M68K_CPU_TYPE_68020:
3557
0
      info->type = TYPE_68020;
3558
0
      info->address_mask = 0xffffffff;
3559
0
      break;
3560
0
    case M68K_CPU_TYPE_68030:
3561
0
      info->type = TYPE_68030;
3562
0
      info->address_mask = 0xffffffff;
3563
0
      break;
3564
15.5k
    case M68K_CPU_TYPE_68040:
3565
15.5k
      info->type = TYPE_68040;
3566
15.5k
      info->address_mask = 0xffffffff;
3567
15.5k
      break;
3568
0
    default:
3569
0
      info->address_mask = 0;
3570
0
      return;
3571
21.7k
  }
3572
21.7k
}
3573
3574
/* ======================================================================== */
3575
/* ================================= API ================================== */
3576
/* ======================================================================== */
3577
3578
/* Disasemble one instruction at pc and store in str_buff */
3579
static unsigned int m68k_disassemble(m68k_info *info, uint64_t pc)
3580
21.7k
{
3581
21.7k
  MCInst *inst = info->inst;
3582
21.7k
  cs_m68k* ext = &info->extension;
3583
21.7k
  int i;
3584
21.7k
  unsigned int size;
3585
3586
21.7k
  inst->Opcode = M68K_INS_INVALID;
3587
3588
21.7k
  memset(ext, 0, sizeof(cs_m68k));
3589
21.7k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
3590
3591
108k
  for (i = 0; i < M68K_OPERAND_COUNT; ++i)
3592
87.0k
    ext->operands[i].type = M68K_OP_REG;
3593
3594
21.7k
  info->ir = peek_imm_16(info);
3595
21.7k
  if (instruction_is_valid(info, peek_imm_32(info) & 0xffff)) {
3596
21.7k
    info->ir = read_imm_16(info);
3597
21.7k
    g_instruction_table[info->ir].instruction(info);
3598
21.7k
  }
3599
3600
21.7k
  size = info->pc - (unsigned int)pc;
3601
21.7k
  info->pc = (unsigned int)pc;
3602
3603
21.7k
  return size;
3604
21.7k
}
3605
3606
bool M68K_getInstruction(csh ud, const uint8_t* code, size_t code_len, MCInst* instr, uint16_t* size, uint64_t address, void* inst_info)
3607
21.8k
{
3608
#ifdef M68K_DEBUG
3609
  SStream ss;
3610
#endif
3611
21.8k
  int s;
3612
21.8k
  int cpu_type = M68K_CPU_TYPE_68000;
3613
21.8k
  cs_struct* handle = instr->csh;
3614
21.8k
  m68k_info *info = (m68k_info*)handle->printer_info;
3615
3616
  // code len has to be at least 2 bytes to be valid m68k
3617
3618
21.8k
  if (code_len < 2) {
3619
67
    *size = 0;
3620
67
    return false;
3621
67
  }
3622
3623
21.7k
  if (instr->flat_insn->detail) {
3624
21.7k
    memset(instr->flat_insn->detail, 0, offsetof(cs_detail, m68k)+sizeof(cs_m68k));
3625
21.7k
  }
3626
3627
21.7k
  info->groups_count = 0;
3628
21.7k
  info->regs_read_count = 0;
3629
21.7k
  info->regs_write_count = 0;
3630
21.7k
  info->code = code;
3631
21.7k
  info->code_len = code_len;
3632
21.7k
  info->baseAddress = address;
3633
3634
21.7k
  if (handle->mode & CS_MODE_M68K_010)
3635
0
    cpu_type = M68K_CPU_TYPE_68010;
3636
21.7k
  if (handle->mode & CS_MODE_M68K_020)
3637
0
    cpu_type = M68K_CPU_TYPE_68020;
3638
21.7k
  if (handle->mode & CS_MODE_M68K_030)
3639
0
    cpu_type = M68K_CPU_TYPE_68030;
3640
21.7k
  if (handle->mode & CS_MODE_M68K_040)
3641
15.5k
    cpu_type = M68K_CPU_TYPE_68040;
3642
21.7k
  if (handle->mode & CS_MODE_M68K_060)
3643
0
    cpu_type = M68K_CPU_TYPE_68040; // 060 = 040 for now
3644
3645
21.7k
  m68k_setup_internals(info, instr, (unsigned int)address, cpu_type);
3646
21.7k
  s = m68k_disassemble(info, address);
3647
3648
21.7k
  if (s == 0) {
3649
47
    *size = 2;
3650
47
    return false;
3651
47
  }
3652
3653
21.7k
  build_regs_read_write_counts(info);
3654
3655
#ifdef M68K_DEBUG
3656
  SStream_Init(&ss);
3657
  M68K_printInst(instr, &ss, info);
3658
#endif
3659
3660
  // Make sure we always stay within range
3661
21.7k
  if (s > (int)code_len)
3662
117
    *size = (uint16_t)code_len;
3663
21.6k
  else
3664
21.6k
    *size = (uint16_t)s;
3665
3666
  return true;
3667
21.7k
}
3668