Coverage Report

Created: 2025-08-29 06:29

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