Coverage Report

Created: 2026-10-17 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/M68K/M68KDisassembler.c
Line
Count
Source
1
/* ======================================================================== */
2
/* ========================= LICENSING & COPYRIGHT ======================== */
3
/* ======================================================================== */
4
/*
5
 *                                  MUSASHI
6
 *                                Version 3.4
7
 *
8
 * A portable Motorola M680x0 processor emulation engine.
9
 * Copyright 1998-2001 Karl Stenerud.  All rights reserved.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 */
29
30
/* The code below is based on MUSASHI but has been heavily modified for Capstone by
31
 * Daniel Collin <daniel@collin.com> 2015-2019 */
32
33
/* ======================================================================== */
34
/* ================================ INCLUDES ============================== */
35
/* ======================================================================== */
36
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "../../cs_priv.h"
42
#include "../../utils.h"
43
44
#include "../../MCInst.h"
45
#include "../../MCInstrDesc.h"
46
#include "../../MCRegisterInfo.h"
47
#include "../../MathExtras.h"
48
#include "M68KDisassembler.h"
49
#include "M68KInstPrinter.h"
50
51
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52
53
static unsigned int m68k_read_disassembler_16(const m68k_info *info,
54
                const uint64_t addr)
55
751k
{
56
751k
  const uint16_t v0 = info->code[addr + 0];
57
751k
  const uint16_t v1 = info->code[addr + 1];
58
751k
  return (v0 << 8) | v1;
59
751k
}
60
61
static unsigned int m68k_read_disassembler_32(const m68k_info *info,
62
                const uint64_t addr)
63
324k
{
64
324k
  const uint32_t v0 = info->code[addr + 0];
65
324k
  const uint32_t v1 = info->code[addr + 1];
66
324k
  const uint32_t v2 = info->code[addr + 2];
67
324k
  const uint32_t v3 = info->code[addr + 3];
68
324k
  return (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
69
324k
}
70
71
static uint64_t m68k_read_disassembler_64(const m68k_info *info,
72
            const uint64_t addr)
73
3.47k
{
74
3.47k
  const uint64_t v0 = info->code[addr + 0];
75
3.47k
  const uint64_t v1 = info->code[addr + 1];
76
3.47k
  const uint64_t v2 = info->code[addr + 2];
77
3.47k
  const uint64_t v3 = info->code[addr + 3];
78
3.47k
  const uint64_t v4 = info->code[addr + 4];
79
3.47k
  const uint64_t v5 = info->code[addr + 5];
80
3.47k
  const uint64_t v6 = info->code[addr + 6];
81
3.47k
  const uint64_t v7 = info->code[addr + 7];
82
3.47k
  return (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) |
83
3.47k
         (v5 << 16) | (v6 << 8) | v7;
84
3.47k
}
85
86
static unsigned int m68k_read_safe_16(const m68k_info *info,
87
              const uint64_t address)
88
752k
{
89
752k
  const uint64_t addr = (address - info->baseAddress) &
90
752k
            info->address_mask;
91
752k
  if (info->code_len < addr + 2) {
92
1.19k
    return 0xaaaa;
93
1.19k
  }
94
751k
  return m68k_read_disassembler_16(info, addr);
95
752k
}
96
97
static unsigned int m68k_read_safe_32(const m68k_info *info,
98
              const uint64_t address)
99
328k
{
100
328k
  const uint64_t addr = (address - info->baseAddress) &
101
328k
            info->address_mask;
102
328k
  if (info->code_len < addr + 4) {
103
3.63k
    return 0xaaaaaaaa;
104
3.63k
  }
105
324k
  return m68k_read_disassembler_32(info, addr);
106
328k
}
107
108
static uint64_t m68k_read_safe_64(const m68k_info *info, const uint64_t address)
109
3.49k
{
110
3.49k
  const uint64_t addr = (address - info->baseAddress) &
111
3.49k
            info->address_mask;
112
3.49k
  if (info->code_len < addr + 8) {
113
14
    return 0xaaaaaaaaaaaaaaaaLL;
114
14
  }
115
3.47k
  return m68k_read_disassembler_64(info, addr);
116
3.49k
}
117
118
/* ======================================================================== */
119
/* =============================== PROTOTYPES ============================= */
120
/* ======================================================================== */
121
122
/* make signed integers 100% portably */
123
static int make_int_8(int value);
124
static int make_int_16(int value);
125
126
/* Stuff to build the opcode handler jump table */
127
static void d68000_invalid(m68k_info *info);
128
static void d68030_pmmu(m68k_info *info);
129
static void d68040_pflush(m68k_info *info);
130
static void d68040_ptest(m68k_info *info);
131
static void d68040_cpush(m68k_info *info);
132
static int instruction_is_valid(m68k_info *info, uint32_t word_check);
133
134
typedef struct {
135
  void (*instruction)(m68k_info *info); /* handler function */
136
  uint16_t word2_mask; /* mask the 2nd word */
137
  uint16_t word2_match; /* what to match after masking */
138
} instruction_struct;
139
140
static inline void invalid_insn(m68k_info *info)
141
54
{
142
54
  info->inst->Opcode = M68K_INS_INVALID;
143
54
  info->pc = (uint32_t)info->baseAddress;
144
54
}
145
146
/* ======================================================================== */
147
/* ================================= DATA ================================= */
148
/* ======================================================================== */
149
150
static const instruction_struct g_instruction_table[0x10000];
151
152
/* used by ops like asr, ror, addq, etc */
153
static const uint32_t g_3bit_qdata_table[8] = { 8, 1, 2, 3, 4, 5, 6, 7 };
154
155
static const uint32_t g_5bit_data_table[32] = {
156
  32, 1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
157
  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
158
};
159
160
static const m68k_insn s_branch_lut[] = {
161
  M68K_INS_INVALID, M68K_INS_INVALID, M68K_INS_BHI, M68K_INS_BLS,
162
  M68K_INS_BCC,   M68K_INS_BCS,     M68K_INS_BNE, M68K_INS_BEQ,
163
  M68K_INS_BVC,   M68K_INS_BVS,     M68K_INS_BPL, M68K_INS_BMI,
164
  M68K_INS_BGE,   M68K_INS_BLT,     M68K_INS_BGT, M68K_INS_BLE,
165
};
166
167
static const m68k_insn s_dbcc_lut[] = {
168
  M68K_INS_DBT,  M68K_INS_DBF,  M68K_INS_DBHI, M68K_INS_DBLS,
169
  M68K_INS_DBCC, M68K_INS_DBCS, M68K_INS_DBNE, M68K_INS_DBEQ,
170
  M68K_INS_DBVC, M68K_INS_DBVS, M68K_INS_DBPL, M68K_INS_DBMI,
171
  M68K_INS_DBGE, M68K_INS_DBLT, M68K_INS_DBGT, M68K_INS_DBLE,
172
};
173
174
static const m68k_insn s_scc_lut[] = {
175
  M68K_INS_ST,  M68K_INS_SF,  M68K_INS_SHI, M68K_INS_SLS,
176
  M68K_INS_SCC, M68K_INS_SCS, M68K_INS_SNE, M68K_INS_SEQ,
177
  M68K_INS_SVC, M68K_INS_SVS, M68K_INS_SPL, M68K_INS_SMI,
178
  M68K_INS_SGE, M68K_INS_SLT, M68K_INS_SGT, M68K_INS_SLE,
179
};
180
181
static const m68k_insn s_trap_lut[] = {
182
  M68K_INS_TRAPT,  M68K_INS_TRAPF,  M68K_INS_TRAPHI, M68K_INS_TRAPLS,
183
  M68K_INS_TRAPCC, M68K_INS_TRAPCS, M68K_INS_TRAPNE, M68K_INS_TRAPEQ,
184
  M68K_INS_TRAPVC, M68K_INS_TRAPVS, M68K_INS_TRAPPL, M68K_INS_TRAPMI,
185
  M68K_INS_TRAPGE, M68K_INS_TRAPLT, M68K_INS_TRAPGT, M68K_INS_TRAPLE,
186
};
187
188
/* ======================================================================== */
189
/* =========================== UTILITY FUNCTIONS ========================== */
190
/* ======================================================================== */
191
192
static unsigned int peek_imm_8(const m68k_info *info)
193
21.8k
{
194
21.8k
  return (m68k_read_safe_16((info), (info)->pc) & 0xff);
195
21.8k
}
196
static unsigned int peek_imm_16(const m68k_info *info)
197
731k
{
198
731k
  return m68k_read_safe_16((info), (info)->pc);
199
731k
}
200
static unsigned int peek_imm_32(const m68k_info *info)
201
328k
{
202
328k
  return m68k_read_safe_32((info), (info)->pc);
203
328k
}
204
static unsigned long long peek_imm_64(const m68k_info *info)
205
3.49k
{
206
3.49k
  return m68k_read_safe_64((info), (info)->pc);
207
3.49k
}
208
209
static unsigned int read_imm_8(m68k_info *info)
210
21.8k
{
211
21.8k
  const unsigned int value = peek_imm_8(info);
212
21.8k
  (info)->pc += 2;
213
21.8k
  return value & 0xff;
214
21.8k
}
215
static unsigned int read_imm_16(m68k_info *info)
216
405k
{
217
405k
  const unsigned int value = peek_imm_16(info);
218
405k
  (info)->pc += 2;
219
405k
  return value & 0xffff;
220
405k
}
221
static unsigned int read_imm_32(m68k_info *info)
222
16.1k
{
223
16.1k
  const unsigned int value = peek_imm_32(info);
224
16.1k
  (info)->pc += 4;
225
16.1k
  return value & 0xffffffff;
226
16.1k
}
227
static unsigned long long read_imm_64(m68k_info *info)
228
3.49k
{
229
3.49k
  const unsigned long long value = peek_imm_64(info);
230
3.49k
  (info)->pc += 8;
231
3.49k
  return value & 0xffffffffffffffff;
232
3.49k
}
233
234
/* Read a 12-byte Motorola extended-precision immediate: sign+exponent word,
235
 * reserved word, and 64-bit significand. */
236
static bool imm_bytes_available(const m68k_info *info, size_t size)
237
3.15k
{
238
3.15k
  const uint64_t addr = (info->pc - info->baseAddress) &
239
3.15k
            info->address_mask;
240
3.15k
  return addr <= info->code_len && info->code_len - addr >= size;
241
3.15k
}
242
243
static bool read_imm_extended(m68k_info *info, m68k_op_fp_extended *value)
244
2.11k
{
245
2.11k
  if (!imm_bytes_available(info, 12))
246
10
    return false;
247
248
2.10k
  memset(value, 0, sizeof(*value));
249
2.10k
  value->sign_exp = (uint16_t)read_imm_16(info);
250
2.10k
  value->reserved = (uint16_t)read_imm_16(info);
251
2.10k
  value->significand = read_imm_64(info);
252
2.10k
  return true;
253
2.11k
}
254
255
/* Read a 12-byte Motorola packed-decimal immediate. */
256
static bool read_imm_packed(m68k_info *info, m68k_op_fp_packed *value)
257
1.04k
{
258
1.04k
  if (!imm_bytes_available(info, 12))
259
8
    return false;
260
261
1.03k
  memset(value, 0, sizeof(*value));
262
1.03k
  value->header = read_imm_32(info);
263
1.03k
  value->fraction = read_imm_64(info);
264
1.03k
  return true;
265
1.04k
}
266
267
/* 100% portable signed int generators */
268
static int make_int_8(int value)
269
16.4k
{
270
16.4k
  return (value & 0x80) ? value | ~0xff : value & 0xff;
271
16.4k
}
272
273
static int make_int_16(int value)
274
4.28k
{
275
4.28k
  return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
276
4.28k
}
277
278
static void get_with_index_address_mode(m68k_info *info, cs_m68k_op *op,
279
          uint32_t instruction, uint32_t size,
280
          bool is_pc)
281
23.1k
{
282
23.1k
  uint32_t ext_addr = info->pc;
283
23.1k
  uint32_t extension = read_imm_16(info);
284
23.1k
  int32_t pc_adjust =
285
23.1k
    is_pc ? (int32_t)(ext_addr - info->baseAddress - 2) : 0;
286
287
23.1k
  op->address_mode = M68K_AM_AREGI_INDEX_BASE_DISP;
288
289
23.1k
  if (EXT_FULL(extension)) {
290
9.44k
    uint32_t preindex;
291
9.44k
    uint32_t postindex;
292
293
9.44k
    op->mem.base_reg = M68K_REG_INVALID;
294
9.44k
    op->mem.index_reg = M68K_REG_INVALID;
295
296
9.44k
    op->mem.in_disp =
297
9.44k
      EXT_BASE_DISPLACEMENT_PRESENT(extension) ?
298
4.49k
        (EXT_BASE_DISPLACEMENT_LONG(extension) ?
299
2.76k
           read_imm_32(info) :
300
4.49k
           (int16_t)read_imm_16(info)) :
301
9.44k
        0;
302
9.44k
    op->mem.in_disp += pc_adjust;
303
304
9.44k
    op->mem.in_disp_size =
305
9.44k
      EXT_BASE_DISPLACEMENT_PRESENT(extension) &&
306
4.49k
          EXT_BASE_DISPLACEMENT_LONG(extension) ?
307
2.76k
        1 :
308
9.44k
        0;
309
310
9.44k
    op->mem.out_disp =
311
9.44k
      EXT_OUTER_DISPLACEMENT_PRESENT(extension) ?
312
3.03k
        (EXT_OUTER_DISPLACEMENT_LONG(extension) ?
313
1.56k
           read_imm_32(info) :
314
3.03k
           (int16_t)read_imm_16(info)) :
315
9.44k
        0;
316
317
9.44k
    op->mem.out_disp_size =
318
9.44k
      EXT_OUTER_DISPLACEMENT_PRESENT(extension) &&
319
3.03k
          EXT_OUTER_DISPLACEMENT_LONG(extension) ?
320
1.56k
        1 :
321
9.44k
        0;
322
323
9.44k
    if (EXT_BASE_REGISTER_PRESENT(extension)) {
324
5.59k
      if (is_pc) {
325
1.44k
        op->mem.base_reg = M68K_REG_PC;
326
4.15k
      } else {
327
4.15k
        op->mem.base_reg =
328
4.15k
          M68K_REG_A0 + (instruction & 7);
329
4.15k
      }
330
5.59k
    }
331
332
9.44k
    if (EXT_INDEX_REGISTER_PRESENT(extension)) {
333
5.51k
      if (EXT_INDEX_AR(extension)) {
334
2.18k
        op->mem.index_reg =
335
2.18k
          M68K_REG_A0 +
336
2.18k
          EXT_INDEX_REGISTER(extension);
337
3.33k
      } else {
338
3.33k
        op->mem.index_reg =
339
3.33k
          M68K_REG_D0 +
340
3.33k
          EXT_INDEX_REGISTER(extension);
341
3.33k
      }
342
343
5.51k
      op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
344
345
5.51k
      if (EXT_INDEX_SCALE(extension)) {
346
4.08k
        op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
347
4.08k
      }
348
5.51k
    }
349
350
9.44k
    preindex = (extension & 7) > 0 && (extension & 7) < 4;
351
9.44k
    postindex = (extension & 7) > 4;
352
353
9.44k
    if (preindex) {
354
3.22k
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_PRE_INDEX :
355
3.22k
               M68K_AM_MEMI_PRE_INDEX;
356
6.21k
    } else if (postindex) {
357
2.84k
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_POST_INDEX :
358
2.84k
               M68K_AM_MEMI_POST_INDEX;
359
3.37k
    } else {
360
3.37k
      op->address_mode =
361
3.37k
        is_pc ? M68K_AM_PCI_INDEX_BASE_DISP :
362
3.37k
          M68K_AM_AREGI_INDEX_BASE_DISP;
363
3.37k
    }
364
365
9.44k
    return;
366
9.44k
  }
367
368
13.7k
  op->mem.index_reg =
369
13.7k
    (EXT_INDEX_AR(extension) ? M68K_REG_A0 : M68K_REG_D0) +
370
13.7k
    EXT_INDEX_REGISTER(extension);
371
13.7k
  op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
372
373
13.7k
  if (is_pc) {
374
2.02k
    op->mem.base_reg = M68K_REG_PC;
375
2.02k
    op->address_mode = M68K_AM_PCI_INDEX_8_BIT_DISP;
376
11.7k
  } else {
377
11.7k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
378
11.7k
    op->address_mode = M68K_AM_AREGI_INDEX_8_BIT_DISP;
379
11.7k
  }
380
381
13.7k
  op->mem.disp = (int8_t)(extension & 0xff);
382
13.7k
  op->mem.disp += (int16_t)pc_adjust;
383
13.7k
  op->mem.disp_size = 0;
384
385
13.7k
  if (EXT_INDEX_SCALE(extension)) {
386
8.51k
    op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
387
8.51k
  }
388
13.7k
}
389
390
/* Raw effective-address encoding bits, used before get_ea_mode_op() consumes
391
 * any extension words and fills cs_m68k_op.address_mode. The control and
392
 * alterable-control classifications follow Table 4-21 on page 4-133 of the
393
 * Motorola MC68881/MC68882 Floating-Point Coprocessor User's Manual, first
394
 * edition (1987):
395
 * https://www.bitsavers.org/components/motorola/68000/68020/MC68881_MC68882_Floating-Point_Coprocessor_Users_Manual_1ed_1987.pdf
396
 */
397
enum {
398
  M68K_EA_REGISTER_MASK = 0x07,
399
  M68K_EA_MODE_SHIFT = 3,
400
  M68K_EA_FIELD_MASK = 0x3f,
401
  M68K_EA_DATA_DIRECT_D0 = 0x00,
402
  M68K_EA_ADDR_DIRECT_A7 = 0x0f,
403
  M68K_EA_ADDR_INDIRECT_DISP_A7 = 0x2f,
404
  M68K_EA_IMMEDIATE_FIELD = 0x3c,
405
};
406
407
enum {
408
  M68K_EA_MODE_DATA_DIRECT = 0,
409
  M68K_EA_MODE_ADDR_DIRECT = 1,
410
  M68K_EA_MODE_ADDR_INDIRECT = 2,
411
  M68K_EA_MODE_ADDR_INDIRECT_POST_INC = 3,
412
  M68K_EA_MODE_ADDR_INDIRECT_PRE_DEC = 4,
413
  M68K_EA_MODE_ADDR_INDIRECT_DISP = 5,
414
  M68K_EA_MODE_ADDR_INDIRECT_INDEX = 6,
415
  M68K_EA_MODE_EXTENDED = 7,
416
};
417
418
enum {
419
  M68K_EA_EXT_ABSOLUTE_SHORT = 0,
420
  M68K_EA_EXT_ABSOLUTE_LONG = 1,
421
  M68K_EA_EXT_PC_DISPLACEMENT = 2,
422
  M68K_EA_EXT_PC_INDEX = 3,
423
};
424
425
static uint32_t m68k_ea_field(uint32_t ir)
426
206k
{
427
206k
  return ir & M68K_EA_FIELD_MASK;
428
206k
}
429
430
static uint32_t m68k_ea_mode(uint32_t ir)
431
11.6k
{
432
11.6k
  return m68k_ea_field(ir) >> M68K_EA_MODE_SHIFT;
433
11.6k
}
434
435
static uint32_t m68k_ea_register(uint32_t ir)
436
1.29k
{
437
1.29k
  return ir & M68K_EA_REGISTER_MASK;
438
1.29k
}
439
440
static bool m68k_ea_is_data_register_direct(uint32_t ir)
441
0
{
442
0
  return m68k_ea_mode(ir) == M68K_EA_MODE_DATA_DIRECT;
443
0
}
444
445
static bool m68k_ea_is_register_direct(uint32_t ir)
446
0
{
447
0
  return m68k_ea_field(ir) <= M68K_EA_ADDR_DIRECT_A7;
448
0
}
449
450
static bool m68k_ea_is_immediate(uint32_t ir)
451
3.57k
{
452
3.57k
  return m68k_ea_field(ir) == M68K_EA_IMMEDIATE_FIELD;
453
3.57k
}
454
455
static bool m68k_ea_is_control(uint32_t ir)
456
1.76k
{
457
1.76k
  uint32_t mode = m68k_ea_mode(ir);
458
1.76k
  return mode == M68K_EA_MODE_ADDR_INDIRECT ||
459
1.20k
         mode == M68K_EA_MODE_ADDR_INDIRECT_DISP ||
460
972
         mode == M68K_EA_MODE_ADDR_INDIRECT_INDEX ||
461
652
         (mode == M68K_EA_MODE_EXTENDED &&
462
650
    m68k_ea_register(ir) <= M68K_EA_EXT_PC_INDEX);
463
1.76k
}
464
465
static bool m68k_ea_is_alterable_control(uint32_t ir)
466
1.83k
{
467
1.83k
  uint32_t mode = m68k_ea_mode(ir);
468
1.83k
  return mode == M68K_EA_MODE_ADDR_INDIRECT ||
469
1.37k
         mode == M68K_EA_MODE_ADDR_INDIRECT_DISP ||
470
1.07k
         mode == M68K_EA_MODE_ADDR_INDIRECT_INDEX ||
471
644
         (mode == M68K_EA_MODE_EXTENDED &&
472
643
    m68k_ea_register(ir) <= M68K_EA_EXT_ABSOLUTE_LONG);
473
1.83k
}
474
475
static bool m68k_ea_is_data_register_direct_or_immediate(uint32_t ir)
476
0
{
477
0
  return m68k_ea_is_data_register_direct(ir) || m68k_ea_is_immediate(ir);
478
0
}
479
480
/* Make string of effective address mode */
481
static bool get_ea_mode_op(m68k_info *info, cs_m68k_op *op,
482
         uint32_t instruction, uint32_t size)
483
191k
{
484
  // default to memory
485
486
191k
  op->type = M68K_OP_MEM;
487
488
191k
  switch (m68k_ea_field(instruction)) {
489
23.9k
  case 0x00:
490
30.2k
  case 0x01:
491
33.1k
  case 0x02:
492
36.1k
  case 0x03:
493
40.8k
  case 0x04:
494
45.6k
  case 0x05:
495
49.9k
  case 0x06:
496
52.4k
  case 0x07:
497
    /* data register direct */
498
52.4k
    op->address_mode = M68K_AM_REG_DIRECT_DATA;
499
52.4k
    op->reg = M68K_REG_D0 + (instruction & 7);
500
52.4k
    op->type = M68K_OP_REG;
501
52.4k
    break;
502
503
722
  case 0x08:
504
1.46k
  case 0x09:
505
3.69k
  case 0x0a:
506
4.40k
  case 0x0b:
507
4.98k
  case 0x0c:
508
5.45k
  case 0x0d:
509
6.50k
  case 0x0e:
510
7.55k
  case 0x0f:
511
    /* address register direct */
512
7.55k
    op->address_mode = M68K_AM_REG_DIRECT_ADDR;
513
7.55k
    op->reg = M68K_REG_A0 + (instruction & 7);
514
7.55k
    op->type = M68K_OP_REG;
515
7.55k
    break;
516
517
3.80k
  case 0x10:
518
8.22k
  case 0x11:
519
10.1k
  case 0x12:
520
14.4k
  case 0x13:
521
15.8k
  case 0x14:
522
19.3k
  case 0x15:
523
21.6k
  case 0x16:
524
25.3k
  case 0x17:
525
    /* address register indirect */
526
25.3k
    op->address_mode = M68K_AM_REGI_ADDR;
527
25.3k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
528
25.3k
    break;
529
530
2.91k
  case 0x18:
531
5.88k
  case 0x19:
532
7.58k
  case 0x1a:
533
10.4k
  case 0x1b:
534
13.3k
  case 0x1c:
535
15.8k
  case 0x1d:
536
18.0k
  case 0x1e:
537
22.3k
  case 0x1f:
538
    /* address register indirect with postincrement */
539
22.3k
    op->address_mode = M68K_AM_REGI_ADDR_POST_INC;
540
22.3k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
541
22.3k
    break;
542
543
6.07k
  case 0x20:
544
9.40k
  case 0x21:
545
17.6k
  case 0x22:
546
20.5k
  case 0x23:
547
23.5k
  case 0x24:
548
27.3k
  case 0x25:
549
31.3k
  case 0x26:
550
34.4k
  case 0x27:
551
    /* address register indirect with predecrement */
552
34.4k
    op->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
553
34.4k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
554
34.4k
    break;
555
556
2.78k
  case 0x28:
557
4.00k
  case 0x29:
558
5.15k
  case 0x2a:
559
6.16k
  case 0x2b:
560
8.17k
  case 0x2c:
561
10.5k
  case 0x2d:
562
12.4k
  case 0x2e:
563
15.0k
  case 0x2f:
564
    /* address register indirect with displacement*/
565
15.0k
    op->address_mode = M68K_AM_REGI_ADDR_DISP;
566
15.0k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
567
15.0k
    op->mem.disp = (int16_t)read_imm_16(info);
568
15.0k
    op->mem.disp_size = 1;
569
15.0k
    break;
570
571
3.34k
  case 0x30:
572
4.79k
  case 0x31:
573
8.14k
  case 0x32:
574
11.0k
  case 0x33:
575
13.0k
  case 0x34:
576
15.5k
  case 0x35:
577
17.4k
  case 0x36:
578
19.1k
  case 0x37:
579
    /* address register indirect with index */
580
19.1k
    get_with_index_address_mode(info, op, instruction, size, false);
581
19.1k
    break;
582
583
3.50k
  case 0x38:
584
    /* absolute short address */
585
3.50k
    op->address_mode = M68K_AM_ABSOLUTE_DATA_SHORT;
586
3.50k
    op->mem.address = read_imm_16(info);
587
3.50k
    break;
588
589
2.06k
  case 0x39:
590
    /* absolute long address */
591
2.06k
    op->address_mode = M68K_AM_ABSOLUTE_DATA_LONG;
592
2.06k
    op->mem.address = read_imm_32(info);
593
2.06k
    break;
594
595
2.84k
  case 0x3a: {
596
    /* program counter with displacement */
597
    /* The printer computes the effective address as
598
     * instruction_start + 2 + disp, assuming the displacement
599
     * extension word immediately follows the opcode word.
600
     * When extra words precede the EA (e.g. an immediate in
601
     * BTST #imm,disp(PC)), the displacement word is further
602
     * along.  Adjust disp so the printer still produces the
603
     * correct absolute address. */
604
2.84k
    uint32_t disp_addr = info->pc;
605
2.84k
    op->address_mode = M68K_AM_PCI_DISP;
606
2.84k
    op->mem.disp = (int16_t)read_imm_16(info);
607
2.84k
    op->mem.disp += (int16_t)(disp_addr - info->baseAddress - 2);
608
2.84k
    op->mem.disp_size = 1;
609
2.84k
    break;
610
17.4k
  }
611
612
4.00k
  case 0x3b:
613
    /* program counter with index */
614
4.00k
    get_with_index_address_mode(info, op, instruction, size, true);
615
4.00k
    break;
616
617
2.80k
  case 0x3c:
618
2.80k
    op->address_mode = M68K_AM_IMMEDIATE;
619
2.80k
    op->type = M68K_OP_IMM;
620
621
2.80k
    if (size == 1)
622
758
      op->imm = read_imm_8(info);
623
2.05k
    else if (size == 2)
624
939
      op->imm = read_imm_16(info);
625
1.11k
    else if (size == 4)
626
752
      op->imm = read_imm_32(info);
627
360
    else
628
360
      op->imm = read_imm_64(info);
629
630
2.80k
    break;
631
632
9
  default:
633
9
    return false;
634
191k
  }
635
636
191k
  return true;
637
191k
}
638
639
static void set_insn_group(m68k_info *info, m68k_group_type group)
640
48.9k
{
641
48.9k
  info->groups[info->groups_count++] = (uint8_t)group;
642
48.9k
}
643
644
static cs_m68k *build_init_op(m68k_info *info, int opcode, int count, int size)
645
298k
{
646
298k
  cs_m68k *ext;
647
648
298k
  MCInst_setOpcode(info->inst, opcode);
649
650
298k
  ext = &info->extension;
651
652
298k
  ext->op_count = (uint8_t)count;
653
298k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
654
298k
  ext->op_size.cpu_size = size;
655
656
298k
  return ext;
657
298k
}
658
659
static cs_m68k *build_init_fpu_condition_op(m68k_info *info, int base_opcode,
660
              uint32_t condition_word, int count,
661
              int size)
662
3.72k
{
663
3.72k
  cs_m68k *ext = build_init_op(info, base_opcode, count, size);
664
3.72k
  MCInst_setOpcode(info->inst, base_opcode + m68k_fpu_condition_index(
665
3.72k
                 condition_word));
666
3.72k
  return ext;
667
3.72k
}
668
669
static void build_re_gen_1(m68k_info *info, bool isDreg, int opcode,
670
         uint8_t size)
671
22.9k
{
672
22.9k
  cs_m68k_op *op0;
673
22.9k
  cs_m68k_op *op1;
674
22.9k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
675
676
22.9k
  op0 = &ext->operands[0];
677
22.9k
  op1 = &ext->operands[1];
678
679
22.9k
  if (isDreg) {
680
22.9k
    op0->address_mode = M68K_AM_REG_DIRECT_DATA;
681
22.9k
    op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
682
22.9k
  } else {
683
0
    op0->address_mode = M68K_AM_REG_DIRECT_ADDR;
684
0
    op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
685
0
  }
686
687
22.9k
  if (!get_ea_mode_op(info, op1, info->ir, size)) {
688
0
    invalid_insn(info);
689
0
    return;
690
0
  }
691
22.9k
}
692
693
static void build_re_1(m68k_info *info, int opcode, uint8_t size)
694
22.9k
{
695
22.9k
  build_re_gen_1(info, true, opcode, size);
696
22.9k
}
697
698
static void build_er_gen_1(m68k_info *info, bool isDreg, int opcode,
699
         uint8_t size)
700
20.5k
{
701
20.5k
  cs_m68k_op *op0;
702
20.5k
  cs_m68k_op *op1;
703
20.5k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
704
705
20.5k
  op0 = &ext->operands[0];
706
20.5k
  op1 = &ext->operands[1];
707
708
20.5k
  if (!get_ea_mode_op(info, op0, info->ir, size)) {
709
0
    invalid_insn(info);
710
0
    return;
711
0
  }
712
713
20.5k
  if (isDreg) {
714
20.5k
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
715
20.5k
    op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
716
20.5k
  } else {
717
0
    op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
718
0
    op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
719
0
  }
720
20.5k
}
721
722
static void append_imm_operand(m68k_info *info, uint32_t value)
723
2.08k
{
724
2.08k
  cs_m68k *ext = &info->extension;
725
2.08k
  cs_m68k_op *op = &ext->operands[ext->op_count];
726
2.08k
  op->type = M68K_OP_IMM;
727
2.08k
  op->address_mode = M68K_AM_IMMEDIATE;
728
2.08k
  op->imm = value;
729
2.08k
  ext->op_count++;
730
2.08k
}
731
732
static void build_rr(m68k_info *info, int opcode, uint8_t size, int imm)
733
6.29k
{
734
6.29k
  cs_m68k_op *op0;
735
6.29k
  cs_m68k_op *op1;
736
6.29k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
737
738
6.29k
  op0 = &ext->operands[0];
739
6.29k
  op1 = &ext->operands[1];
740
741
6.29k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
742
6.29k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
743
744
6.29k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
745
6.29k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
746
747
6.29k
  if (imm > 0)
748
1.06k
    append_imm_operand(info, imm);
749
6.29k
}
750
751
static void build_r(m68k_info *info, int opcode, uint8_t size)
752
8.63k
{
753
8.63k
  cs_m68k_op *op0;
754
8.63k
  cs_m68k_op *op1;
755
8.63k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
756
757
8.63k
  op0 = &ext->operands[0];
758
8.63k
  op1 = &ext->operands[1];
759
760
8.63k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
761
8.63k
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
762
763
8.63k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
764
8.63k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
765
8.63k
}
766
767
static void build_imm_ea(m68k_info *info, int opcode, uint8_t size,
768
       uint32_t imm)
769
27.4k
{
770
27.4k
  cs_m68k_op *op0;
771
27.4k
  cs_m68k_op *op1;
772
27.4k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
773
774
27.4k
  op0 = &ext->operands[0];
775
27.4k
  op1 = &ext->operands[1];
776
777
27.4k
  op0->type = M68K_OP_IMM;
778
27.4k
  op0->address_mode = M68K_AM_IMMEDIATE;
779
27.4k
  op0->imm = imm;
780
781
27.4k
  if (!get_ea_mode_op(info, op1, info->ir, size)) {
782
0
    invalid_insn(info);
783
0
    return;
784
0
  }
785
27.4k
}
786
787
static void build_3bit_d(m68k_info *info, int opcode, int size)
788
7.53k
{
789
7.53k
  cs_m68k_op *op0;
790
7.53k
  cs_m68k_op *op1;
791
7.53k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
792
793
7.53k
  op0 = &ext->operands[0];
794
7.53k
  op1 = &ext->operands[1];
795
796
7.53k
  op0->type = M68K_OP_IMM;
797
7.53k
  op0->address_mode = M68K_AM_IMMEDIATE;
798
7.53k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
799
800
7.53k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
801
7.53k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
802
7.53k
}
803
804
static void build_3bit_ea(m68k_info *info, int opcode, int size)
805
10.3k
{
806
10.3k
  cs_m68k_op *op0;
807
10.3k
  cs_m68k_op *op1;
808
10.3k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
809
810
10.3k
  op0 = &ext->operands[0];
811
10.3k
  op1 = &ext->operands[1];
812
813
10.3k
  op0->type = M68K_OP_IMM;
814
10.3k
  op0->address_mode = M68K_AM_IMMEDIATE;
815
10.3k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
816
817
10.3k
  if (!get_ea_mode_op(info, op1, info->ir, size)) {
818
0
    invalid_insn(info);
819
0
    return;
820
0
  }
821
10.3k
}
822
823
static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm)
824
4.49k
{
825
4.49k
  cs_m68k_op *op0;
826
4.49k
  cs_m68k_op *op1;
827
4.49k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
828
829
4.49k
  op0 = &ext->operands[0];
830
4.49k
  op1 = &ext->operands[1];
831
832
4.49k
  op0->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
833
4.49k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
834
835
4.49k
  op1->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
836
4.49k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
837
838
4.49k
  if (imm > 0)
839
1.01k
    append_imm_operand(info, imm);
840
4.49k
}
841
842
static void build_ea(m68k_info *info, int opcode, uint8_t size)
843
14.8k
{
844
14.8k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
845
14.8k
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) {
846
0
    invalid_insn(info);
847
0
    return;
848
0
  }
849
14.8k
}
850
851
static void build_ea_a(m68k_info *info, int opcode, uint8_t size)
852
12.0k
{
853
12.0k
  cs_m68k_op *op0;
854
12.0k
  cs_m68k_op *op1;
855
12.0k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
856
857
12.0k
  op0 = &ext->operands[0];
858
12.0k
  op1 = &ext->operands[1];
859
860
12.0k
  if (!get_ea_mode_op(info, op0, info->ir, size)) {
861
0
    invalid_insn(info);
862
0
    return;
863
0
  }
864
865
12.0k
  op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
866
12.0k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
867
12.0k
}
868
869
static void build_ea_ea(m68k_info *info, int opcode, int size)
870
31.4k
{
871
31.4k
  cs_m68k_op *op0;
872
31.4k
  cs_m68k_op *op1;
873
31.4k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
874
875
31.4k
  op0 = &ext->operands[0];
876
31.4k
  op1 = &ext->operands[1];
877
878
31.4k
  if (!get_ea_mode_op(info, op0, info->ir, size)) {
879
0
    invalid_insn(info);
880
0
    return;
881
0
  }
882
31.4k
  if (!get_ea_mode_op(info, op1,
883
31.4k
          (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)),
884
31.4k
          size)) {
885
0
    invalid_insn(info);
886
0
    return;
887
0
  }
888
31.4k
}
889
890
static void build_pi_pi(m68k_info *info, int opcode, int size)
891
959
{
892
959
  cs_m68k_op *op0;
893
959
  cs_m68k_op *op1;
894
959
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
895
896
959
  op0 = &ext->operands[0];
897
959
  op1 = &ext->operands[1];
898
899
959
  op0->address_mode = M68K_AM_REGI_ADDR_POST_INC;
900
959
  op0->reg = M68K_REG_A0 + (info->ir & 7);
901
902
959
  op1->address_mode = M68K_AM_REGI_ADDR_POST_INC;
903
959
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
904
959
}
905
906
static void build_imm_special_reg(m68k_info *info, int opcode, uint32_t imm,
907
          int size, m68k_reg reg)
908
1.30k
{
909
1.30k
  cs_m68k_op *op0;
910
1.30k
  cs_m68k_op *op1;
911
1.30k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
912
913
1.30k
  op0 = &ext->operands[0];
914
1.30k
  op1 = &ext->operands[1];
915
916
1.30k
  op0->type = M68K_OP_IMM;
917
1.30k
  op0->address_mode = M68K_AM_IMMEDIATE;
918
1.30k
  op0->imm = imm;
919
920
1.30k
  op1->address_mode = M68K_AM_NONE;
921
1.30k
  op1->reg = reg;
922
1.30k
}
923
924
static void build_relative_branch(m68k_info *info, int opcode, int size,
925
          int displacement)
926
18.6k
{
927
18.6k
  cs_m68k_op *op;
928
18.6k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
929
930
18.6k
  op = &ext->operands[0];
931
932
18.6k
  op->type = M68K_OP_BR_DISP;
933
18.6k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
934
18.6k
  op->br_disp.disp = displacement;
935
18.6k
  op->br_disp.disp_size = size;
936
937
18.6k
  set_insn_group(info, M68K_GRP_JUMP);
938
18.6k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
939
18.6k
}
940
941
static void build_absolute_jump_with_immediate(m68k_info *info, int opcode,
942
                 int size, int immediate)
943
2.06k
{
944
2.06k
  cs_m68k_op *op;
945
2.06k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
946
947
2.06k
  op = &ext->operands[0];
948
949
2.06k
  op->type = M68K_OP_IMM;
950
2.06k
  op->address_mode = M68K_AM_IMMEDIATE;
951
2.06k
  op->imm = immediate;
952
953
2.06k
  set_insn_group(info, M68K_GRP_JUMP);
954
2.06k
}
955
956
static void build_bcc(m68k_info *info, int size, int displacement)
957
14.6k
{
958
14.6k
  build_relative_branch(info,
959
14.6k
            s_branch_lut[M68K_IR_CONDITION_NIBBLE(info)],
960
14.6k
            size, displacement);
961
14.6k
}
962
963
static void build_trap(m68k_info *info, int size, int immediate)
964
683
{
965
683
  build_absolute_jump_with_immediate(
966
683
    info, s_trap_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
967
683
    immediate);
968
683
}
969
970
static void build_dbxx(m68k_info *info, int opcode, int size, int displacement)
971
723
{
972
723
  cs_m68k_op *op0;
973
723
  cs_m68k_op *op1;
974
723
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
975
976
723
  op0 = &ext->operands[0];
977
723
  op1 = &ext->operands[1];
978
979
723
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
980
723
  op0->reg = M68K_REG_D0 + (info->ir & 7);
981
982
723
  op1->type = M68K_OP_BR_DISP;
983
723
  op1->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
984
723
  op1->br_disp.disp = displacement;
985
723
  op1->br_disp.disp_size = M68K_OP_BR_DISP_SIZE_LONG;
986
987
723
  set_insn_group(info, M68K_GRP_JUMP);
988
723
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
989
723
}
990
991
static void build_dbcc(m68k_info *info, int size, int displacement)
992
429
{
993
429
  build_dbxx(info, s_dbcc_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
994
429
       displacement);
995
429
}
996
997
static void build_d_d_ea(m68k_info *info, int opcode, int size)
998
438
{
999
438
  cs_m68k_op *op0;
1000
438
  cs_m68k_op *op1;
1001
438
  cs_m68k_op *op2;
1002
438
  uint32_t extension = read_imm_16(info);
1003
438
  cs_m68k *ext = build_init_op(info, opcode, 3, size);
1004
1005
438
  op0 = &ext->operands[0];
1006
438
  op1 = &ext->operands[1];
1007
438
  op2 = &ext->operands[2];
1008
1009
438
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
1010
438
  op0->reg = M68K_REG_D0 + (extension & 7);
1011
1012
438
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
1013
438
  op1->reg = M68K_REG_D0 + ((extension >> 6) & 7);
1014
1015
438
  if (!get_ea_mode_op(info, op2, info->ir, size)) {
1016
0
    invalid_insn(info);
1017
0
    return;
1018
0
  }
1019
438
}
1020
1021
static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg)
1022
2.10k
{
1023
2.10k
  uint8_t offset;
1024
2.10k
  uint8_t width;
1025
2.10k
  cs_m68k_op *op_ea;
1026
2.10k
  cs_m68k_op *op1;
1027
2.10k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
1028
2.10k
  uint32_t extension = read_imm_16(info);
1029
1030
2.10k
  op_ea = &ext->operands[0];
1031
2.10k
  op1 = &ext->operands[1];
1032
1033
2.10k
  if (BIT_B(extension))
1034
1.13k
    offset = M68K_BITFIELD_ENCODE_REG((extension >> 6) & 7);
1035
971
  else
1036
971
    offset = (extension >> 6) & 31;
1037
1038
2.10k
  if (BIT_5(extension))
1039
782
    width = M68K_BITFIELD_ENCODE_REG(extension & 7);
1040
1.32k
  else
1041
1.32k
    width = (uint8_t)g_5bit_data_table[extension & 31];
1042
1043
2.10k
  if (has_d_arg) {
1044
1.01k
    ext->op_count = 2;
1045
1.01k
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
1046
1.01k
    op1->reg = M68K_REG_D0 + ((extension >> 12) & 7);
1047
1.01k
  }
1048
1049
2.10k
  if (!get_ea_mode_op(info, op_ea, info->ir, 1)) {
1050
0
    invalid_insn(info);
1051
0
    return;
1052
0
  }
1053
1054
2.10k
  op_ea->mem.bitfield = 1;
1055
2.10k
  op_ea->mem.width = width;
1056
2.10k
  op_ea->mem.offset = offset;
1057
2.10k
}
1058
1059
static void build_d(m68k_info *info, int opcode, int size)
1060
835
{
1061
835
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
1062
835
  cs_m68k_op *op;
1063
1064
835
  op = &ext->operands[0];
1065
1066
835
  op->address_mode = M68K_AM_REG_DIRECT_DATA;
1067
835
  op->reg = M68K_REG_D0 + (info->ir & 7);
1068
835
}
1069
1070
static m68k_reg cf_reg_from_nibble(unsigned int reg)
1071
0
{
1072
0
  return (reg & 8) ? (m68k_reg)(M68K_REG_A0 + (reg & 7)) :
1073
0
         (m68k_reg)(M68K_REG_D0 + (reg & 7));
1074
0
}
1075
1076
static m68k_reg cf_acc_reg(unsigned int acc)
1077
0
{
1078
0
  switch (acc & 3) {
1079
0
  case 0:
1080
0
    return M68K_REG_ACC0;
1081
0
  case 1:
1082
0
    return M68K_REG_ACC1;
1083
0
  case 2:
1084
0
    return M68K_REG_ACC2;
1085
0
  default:
1086
0
    return M68K_REG_ACC3;
1087
0
  }
1088
0
}
1089
1090
static void cf_build_reg_op(cs_m68k_op *op, m68k_reg reg)
1091
0
{
1092
0
  op->address_mode = M68K_AM_NONE;
1093
0
  op->type = M68K_OP_REG;
1094
0
  op->reg = reg;
1095
0
}
1096
1097
static void cf_build_direct_reg_op(cs_m68k_op *op, m68k_reg reg)
1098
0
{
1099
0
  op->type = M68K_OP_REG;
1100
0
  op->reg = reg;
1101
0
  op->address_mode = (reg >= M68K_REG_A0 && reg <= M68K_REG_A7) ?
1102
0
           M68K_AM_REG_DIRECT_ADDR :
1103
0
           M68K_AM_REG_DIRECT_DATA;
1104
0
}
1105
1106
static void cf_build_imm_op(cs_m68k_op *op, uint32_t imm)
1107
0
{
1108
0
  op->type = M68K_OP_IMM;
1109
0
  op->address_mode = M68K_AM_IMMEDIATE;
1110
0
  op->imm = imm;
1111
0
}
1112
1113
static void cf_build_shift_op(cs_m68k_op *op, uint32_t shift)
1114
0
{
1115
0
  op->type = M68K_OP_SHIFT;
1116
0
  op->address_mode = M68K_AM_NONE;
1117
0
  op->flags = shift == 0x0200 ? M68K_OP_FLAG_SHIFT_LEFT :
1118
0
              M68K_OP_FLAG_SHIFT_RIGHT;
1119
0
}
1120
1121
static void cf_build_mac_reg_op(cs_m68k_op *op, uint32_t reg, bool long_size)
1122
0
{
1123
0
  cf_build_direct_reg_op(op, cf_reg_from_nibble(reg));
1124
0
  if (!long_size)
1125
0
    op->flags = (reg & 0x10) ? M68K_OP_FLAG_REG_UPPER :
1126
0
             M68K_OP_FLAG_REG_LOWER;
1127
0
}
1128
1129
static bool cf_mac_ea_is_valid(uint32_t ir)
1130
0
{
1131
0
  uint32_t mode = m68k_ea_mode(ir);
1132
1133
  /* ColdFire MAC/EMAC load forms accept (An), (An)+, -(An), and d16(An). */
1134
0
  return mode >= M68K_EA_MODE_ADDR_INDIRECT &&
1135
0
         mode <= M68K_EA_MODE_ADDR_INDIRECT_DISP;
1136
0
}
1137
1138
static bool cf_coproc_ea_is_valid(uint32_t ir)
1139
0
{
1140
0
  return m68k_ea_field(ir) <= M68K_EA_ADDR_INDIRECT_DISP_A7;
1141
0
}
1142
1143
static bool cf_alterable_memory_ea_is_valid(uint32_t ir)
1144
0
{
1145
0
  uint32_t mode = m68k_ea_mode(ir);
1146
0
  uint32_t reg = m68k_ea_register(ir);
1147
1148
0
  return (mode >= M68K_EA_MODE_ADDR_INDIRECT &&
1149
0
    mode <= M68K_EA_MODE_ADDR_INDIRECT_INDEX) ||
1150
0
         (mode == M68K_EA_MODE_EXTENDED &&
1151
0
    reg <= M68K_EA_EXT_ABSOLUTE_LONG);
1152
0
}
1153
1154
static bool cf_sr_ccr_source_ea_is_valid(uint32_t ir)
1155
0
{
1156
0
  return m68k_ea_is_data_register_direct_or_immediate(ir);
1157
0
}
1158
1159
static bool cf_sr_ccr_destination_ea_is_valid(uint32_t ir)
1160
0
{
1161
0
  return m68k_ea_is_data_register_direct(ir);
1162
0
}
1163
1164
static uint16_t reverse_bits(uint32_t v)
1165
1.15k
{
1166
1.15k
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1167
1.15k
  uint32_t s = 16 - 1; // extra shift needed at end
1168
1169
10.6k
  for (v >>= 1; v; v >>= 1) {
1170
9.45k
    r <<= 1;
1171
9.45k
    r |= v & 1;
1172
9.45k
    s--;
1173
9.45k
  }
1174
1175
1.15k
  r <<= s; // shift when v's highest bits are zero
1176
1.15k
  return r;
1177
1.15k
}
1178
1179
static uint8_t reverse_bits_8(uint32_t v)
1180
2.20k
{
1181
2.20k
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1182
2.20k
  uint32_t s = 8 - 1; // extra shift needed at end
1183
1184
14.7k
  for (v >>= 1; v; v >>= 1) {
1185
12.5k
    r <<= 1;
1186
12.5k
    r |= v & 1;
1187
12.5k
    s--;
1188
12.5k
  }
1189
1190
2.20k
  r <<= s; // shift when v's highest bits are zero
1191
2.20k
  return r;
1192
2.20k
}
1193
1194
static void build_movem_re(m68k_info *info, int opcode, int size)
1195
1.98k
{
1196
1.98k
  cs_m68k_op *op0;
1197
1.98k
  cs_m68k_op *op1;
1198
1.98k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
1199
1200
1.98k
  op0 = &ext->operands[0];
1201
1.98k
  op1 = &ext->operands[1];
1202
1203
1.98k
  op0->type = M68K_OP_REG_BITS;
1204
1.98k
  op0->register_bits = read_imm_16(info);
1205
1206
1.98k
  if (!get_ea_mode_op(info, op1, info->ir, size)) {
1207
0
    invalid_insn(info);
1208
0
    return;
1209
0
  }
1210
1211
1.98k
  if (op1->address_mode == M68K_AM_REGI_ADDR_PRE_DEC)
1212
1.15k
    op0->register_bits = reverse_bits(op0->register_bits);
1213
1.98k
}
1214
1215
static void build_movem_er(m68k_info *info, int opcode, int size)
1216
1.29k
{
1217
1.29k
  cs_m68k_op *op0;
1218
1.29k
  cs_m68k_op *op1;
1219
1.29k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
1220
1221
1.29k
  op0 = &ext->operands[0];
1222
1.29k
  op1 = &ext->operands[1];
1223
1224
1.29k
  op1->type = M68K_OP_REG_BITS;
1225
1.29k
  op1->register_bits = read_imm_16(info);
1226
1227
1.29k
  if (!get_ea_mode_op(info, op0, info->ir, size)) {
1228
0
    invalid_insn(info);
1229
0
    return;
1230
0
  }
1231
1.29k
}
1232
1233
static void build_imm(m68k_info *info, int opcode, uint32_t data)
1234
63.4k
{
1235
63.4k
  cs_m68k_op *op;
1236
63.4k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
1237
1238
63.4k
  MCInst_setOpcode(info->inst, opcode);
1239
1240
63.4k
  op = &ext->operands[0];
1241
1242
63.4k
  op->type = M68K_OP_IMM;
1243
63.4k
  op->address_mode = M68K_AM_IMMEDIATE;
1244
63.4k
  op->imm = data;
1245
63.4k
}
1246
1247
static void build_illegal(m68k_info *info, uint32_t data)
1248
278
{
1249
278
  build_imm(info, M68K_INS_ILLEGAL, data);
1250
278
}
1251
1252
static void build_invalid(m68k_info *info, uint32_t data)
1253
63.1k
{
1254
63.1k
  build_imm(info, M68K_INS_INVALID, data);
1255
63.1k
}
1256
1257
static void build_cas2(m68k_info *info, int size)
1258
2.04k
{
1259
2.04k
  uint32_t word3;
1260
2.04k
  uint32_t extension;
1261
2.04k
  cs_m68k_op *op0;
1262
2.04k
  cs_m68k_op *op1;
1263
2.04k
  cs_m68k_op *op2;
1264
2.04k
  cs_m68k *ext = build_init_op(info, M68K_INS_CAS2, 3, size);
1265
2.04k
  uint32_t reg_0, reg_1;
1266
1267
  /* cas2 is the only 3 words instruction, word2 and word3 have the same motif bits to check */
1268
2.04k
  word3 = peek_imm_32(info) & 0xffff;
1269
2.04k
  if (!instruction_is_valid(info, word3))
1270
593
    return;
1271
1272
1.45k
  op0 = &ext->operands[0];
1273
1.45k
  op1 = &ext->operands[1];
1274
1.45k
  op2 = &ext->operands[2];
1275
1276
1.45k
  extension = read_imm_32(info);
1277
1278
1.45k
  op0->address_mode = M68K_AM_NONE;
1279
1.45k
  op0->type = M68K_OP_REG_PAIR;
1280
1.45k
  op0->reg_pair.reg_0 = ((extension >> 16) & 7) + M68K_REG_D0;
1281
1.45k
  op0->reg_pair.reg_1 = (extension & 7) + M68K_REG_D0;
1282
1283
1.45k
  op1->address_mode = M68K_AM_NONE;
1284
1.45k
  op1->type = M68K_OP_REG_PAIR;
1285
1.45k
  op1->reg_pair.reg_0 = ((extension >> 22) & 7) + M68K_REG_D0;
1286
1.45k
  op1->reg_pair.reg_1 = ((extension >> 6) & 7) + M68K_REG_D0;
1287
1288
1.45k
  reg_0 = (extension >> 28) & 7;
1289
1.45k
  reg_1 = (extension >> 12) & 7;
1290
1291
1.45k
  op2->address_mode = M68K_AM_NONE;
1292
1.45k
  op2->type = M68K_OP_REG_PAIR;
1293
1.45k
  op2->reg_pair.reg_0 = reg_0 + (BIT_1F(extension) ? 8 : 0) + M68K_REG_D0;
1294
1.45k
  op2->reg_pair.reg_1 = reg_1 + (BIT_F(extension) ? 8 : 0) + M68K_REG_D0;
1295
1.45k
}
1296
1297
static void build_chk2_cmp2(m68k_info *info, int size)
1298
591
{
1299
591
  cs_m68k_op *op0;
1300
591
  cs_m68k_op *op1;
1301
591
  cs_m68k *ext = build_init_op(info, M68K_INS_CHK2, 2, size);
1302
1303
591
  uint32_t extension = read_imm_16(info);
1304
1305
591
  if (BIT_B(extension))
1306
67
    MCInst_setOpcode(info->inst, M68K_INS_CHK2);
1307
524
  else
1308
524
    MCInst_setOpcode(info->inst, M68K_INS_CMP2);
1309
1310
591
  op0 = &ext->operands[0];
1311
591
  op1 = &ext->operands[1];
1312
1313
591
  if (!get_ea_mode_op(info, op0, info->ir, size)) {
1314
0
    invalid_insn(info);
1315
0
    return;
1316
0
  }
1317
1318
591
  op1->address_mode = M68K_AM_NONE;
1319
591
  op1->type = M68K_OP_REG;
1320
591
  op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1321
591
       ((extension >> 12) & 7);
1322
591
}
1323
1324
static void build_move16(m68k_info *info, const uint32_t data[2],
1325
       const uint32_t modes[2])
1326
1.42k
{
1327
1.42k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE16, 2, 0);
1328
1.42k
  int i;
1329
1330
4.26k
  for (i = 0; i < 2; ++i) {
1331
2.84k
    cs_m68k_op *op = &ext->operands[i];
1332
2.84k
    const uint32_t d = data[i];
1333
2.84k
    const uint32_t m = modes[i];
1334
1335
2.84k
    op->type = M68K_OP_MEM;
1336
2.84k
    op->address_mode = m;
1337
1338
2.84k
    if (m == M68K_AM_REGI_ADDR_POST_INC || m == M68K_AM_REGI_ADDR)
1339
1.69k
      op->mem.base_reg = M68K_REG_A0 + d;
1340
1.15k
    else
1341
1.15k
      op->mem.address = d;
1342
2.84k
  }
1343
1.42k
}
1344
1345
static void build_link(m68k_info *info, int disp, int size)
1346
531
{
1347
531
  cs_m68k_op *op0;
1348
531
  cs_m68k_op *op1;
1349
531
  cs_m68k *ext = build_init_op(info, M68K_INS_LINK, 2, size);
1350
1351
531
  op0 = &ext->operands[0];
1352
531
  op1 = &ext->operands[1];
1353
1354
531
  op0->address_mode = M68K_AM_NONE;
1355
531
  op0->reg = M68K_REG_A0 + (info->ir & 7);
1356
1357
531
  op1->address_mode = M68K_AM_IMMEDIATE;
1358
531
  op1->type = M68K_OP_IMM;
1359
531
  op1->imm = disp;
1360
531
}
1361
1362
static void build_cpush_cinv(m68k_info *info, int op_offset)
1363
2.27k
{
1364
2.27k
  cs_m68k_op *op0;
1365
2.27k
  cs_m68k_op *op1;
1366
2.27k
  cs_m68k *ext = build_init_op(info, M68K_INS_INVALID, 2, 0);
1367
1368
2.27k
  switch (M68K_IR_CACHE_SCOPE(info)) {
1369
276
  case 0:
1370
276
    d68000_invalid(info);
1371
276
    return;
1372
931
  case 1: // Line
1373
931
    MCInst_setOpcode(info->inst, op_offset + 0);
1374
931
    break;
1375
795
  case 2: // Page
1376
795
    MCInst_setOpcode(info->inst, op_offset + 1);
1377
795
    break;
1378
277
  case 3: // All
1379
277
    ext->op_count = 1;
1380
277
    MCInst_setOpcode(info->inst, op_offset + 2);
1381
277
    break;
1382
0
  default:
1383
0
    return;
1384
2.27k
  }
1385
1386
2.00k
  op0 = &ext->operands[0];
1387
2.00k
  op1 = &ext->operands[1];
1388
1389
2.00k
  op0->address_mode = M68K_AM_IMMEDIATE;
1390
2.00k
  op0->type = M68K_OP_IMM;
1391
2.00k
  op0->imm = M68K_IR_CACHE_SEL(info);
1392
1393
2.00k
  op1->type = M68K_OP_MEM;
1394
2.00k
  op1->address_mode = M68K_AM_REGI_ADDR;
1395
2.00k
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1396
2.00k
}
1397
1398
static void build_movep_re(m68k_info *info, int size)
1399
496
{
1400
496
  cs_m68k_op *op0;
1401
496
  cs_m68k_op *op1;
1402
496
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1403
1404
496
  op0 = &ext->operands[0];
1405
496
  op1 = &ext->operands[1];
1406
1407
496
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1408
1409
496
  op1->address_mode = M68K_AM_REGI_ADDR_DISP;
1410
496
  op1->type = M68K_OP_MEM;
1411
496
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1412
496
  op1->mem.disp = (int16_t)read_imm_16(info);
1413
496
}
1414
1415
static void build_movep_er(m68k_info *info, int size)
1416
1.41k
{
1417
1.41k
  cs_m68k_op *op0;
1418
1.41k
  cs_m68k_op *op1;
1419
1.41k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1420
1421
1.41k
  op0 = &ext->operands[0];
1422
1.41k
  op1 = &ext->operands[1];
1423
1424
1.41k
  op0->address_mode = M68K_AM_REGI_ADDR_DISP;
1425
1.41k
  op0->type = M68K_OP_MEM;
1426
1.41k
  op0->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1427
1.41k
  op0->mem.disp = (int16_t)read_imm_16(info);
1428
1429
1.41k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1430
1.41k
}
1431
1432
static void build_moves(m68k_info *info, int size)
1433
270
{
1434
270
  cs_m68k_op *op0;
1435
270
  cs_m68k_op *op1;
1436
270
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVES, 2, size);
1437
270
  uint32_t extension = read_imm_16(info);
1438
1439
270
  op0 = &ext->operands[0];
1440
270
  op1 = &ext->operands[1];
1441
1442
270
  if (BIT_B(extension)) {
1443
126
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1444
126
         ((extension >> 12) & 7);
1445
126
    if (!get_ea_mode_op(info, op1, info->ir, size)) {
1446
0
      invalid_insn(info);
1447
0
      return;
1448
0
    }
1449
144
  } else {
1450
144
    if (!get_ea_mode_op(info, op0, info->ir, size)) {
1451
0
      invalid_insn(info);
1452
0
      return;
1453
0
    }
1454
144
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1455
144
         ((extension >> 12) & 7);
1456
144
  }
1457
270
}
1458
1459
static void build_er_1(m68k_info *info, int opcode, uint8_t size)
1460
20.5k
{
1461
20.5k
  build_er_gen_1(info, true, opcode, size);
1462
20.5k
}
1463
1464
/* ======================================================================== */
1465
/* ========================= INSTRUCTION HANDLERS ========================= */
1466
/* ======================================================================== */
1467
/* Instruction handler function names follow this convention:
1468
 *
1469
 * d68000_NAME_EXTENSIONS(void)
1470
 * where NAME is the name of the opcode it handles and EXTENSIONS are any
1471
 * extensions for special instances of that opcode.
1472
 *
1473
 * Examples:
1474
 *   d68000_add_er_8(): add opcode, from effective address to register,
1475
 *                      size = byte
1476
 *
1477
 *   d68000_asr_s_8(): arithmetic shift right, static count, size = byte
1478
 *
1479
 *
1480
 * Common extensions:
1481
 * 8   : size = byte
1482
 * 16  : size = word
1483
 * 32  : size = long
1484
 * rr  : register to register
1485
 * mm  : memory to memory
1486
 * r   : register
1487
 * s   : static
1488
 * er  : effective address -> register
1489
 * re  : register -> effective address
1490
 * ea  : using effective address mode of operation
1491
 * d   : data register direct
1492
 * a   : address register direct
1493
 * ai  : address register indirect
1494
 * pi  : address register indirect with postincrement
1495
 * pd  : address register indirect with predecrement
1496
 * di  : address register indirect with displacement
1497
 * ix  : address register indirect with index
1498
 * aw  : absolute word
1499
 * al  : absolute long
1500
 */
1501
1502
static void d68000_invalid(m68k_info *info)
1503
63.1k
{
1504
63.1k
  build_invalid(info, info->ir);
1505
63.1k
}
1506
1507
static void d68000_illegal(m68k_info *info)
1508
278
{
1509
278
  build_illegal(info, info->ir);
1510
278
}
1511
1512
static void dcf_1111(m68k_info *info)
1513
10.4k
{
1514
10.4k
  d68000_invalid(info);
1515
10.4k
}
1516
1517
static void dcf_bitop_d(m68k_info *info, m68k_insn insn)
1518
1.24k
{
1519
1.24k
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A_PLUS | CS_MODE_M68K_CF_ISA_C);
1520
0
  build_d(info, insn, 0);
1521
0
}
1522
1523
static void dcf_bitrev(m68k_info *info)
1524
626
{
1525
626
  dcf_bitop_d(info, M68K_INS_BITREV);
1526
626
}
1527
1528
static void dcf_byterev(m68k_info *info)
1529
408
{
1530
408
  dcf_bitop_d(info, M68K_INS_BYTEREV);
1531
408
}
1532
1533
static void dcf_ff1(m68k_info *info)
1534
211
{
1535
211
  dcf_bitop_d(info, M68K_INS_FF1);
1536
211
}
1537
1538
static uint32_t cf_mov3q_imm(uint32_t ir)
1539
0
{
1540
0
  uint32_t imm = (ir >> 9) & 7;
1541
1542
0
  return imm == 0 ? UINT32_MAX : imm;
1543
0
}
1544
1545
static void dcf_mov3q(m68k_info *info)
1546
757
{
1547
757
  cs_m68k *ext;
1548
757
  cs_m68k_op *op0;
1549
757
  cs_m68k_op *op1;
1550
1551
757
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1552
1553
0
  ext = build_init_op(info, M68K_INS_MOV3Q, 2, 4);
1554
0
  op0 = &ext->operands[0];
1555
0
  op1 = &ext->operands[1];
1556
1557
0
  cf_build_imm_op(op0, cf_mov3q_imm(info->ir));
1558
0
  if (!get_ea_mode_op(info, op1, info->ir, 4)) {
1559
0
    invalid_insn(info);
1560
0
    return;
1561
0
  }
1562
0
}
1563
1564
static void cf_init_two_op(m68k_info *info, m68k_insn insn, cs_m68k_op **op0,
1565
         cs_m68k_op **op1)
1566
0
{
1567
0
  cs_m68k *ext = build_init_op(info, insn, 2, 4);
1568
1569
0
  *op0 = &ext->operands[0];
1570
0
  *op1 = &ext->operands[1];
1571
0
}
1572
1573
static m68k_reg cf_primary_acc_reg(const m68k_info *info)
1574
0
{
1575
0
  return m68k_has_feature(info, CS_MODE_M68K_CF_EMAC) ? M68K_REG_ACC0 :
1576
0
                    M68K_REG_ACC;
1577
0
}
1578
1579
static m68k_insn cf_dual_acc_insn(uint16_t ext_word)
1580
0
{
1581
0
  if (ext_word & 0x0100)
1582
0
    return (ext_word & 0x2) ? M68K_INS_MSSAC : M68K_INS_MSAAC;
1583
0
  return (ext_word & 0x2) ? M68K_INS_MASAC : M68K_INS_MAAAC;
1584
0
}
1585
1586
static m68k_reg cf_accext_reg(uint32_t ir)
1587
0
{
1588
0
  return (ir & 0x0400) ? M68K_REG_ACCEXT23 : M68K_REG_ACCEXT01;
1589
0
}
1590
1591
static void dcf_movclr_accn_reg(m68k_info *info)
1592
225
{
1593
225
  cs_m68k_op *op0;
1594
225
  cs_m68k_op *op1;
1595
1596
225
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1597
0
  cf_init_two_op(info, M68K_INS_MOVCLR, &op0, &op1);
1598
0
  cf_build_reg_op(op0, cf_acc_reg((info->ir >> 9) & 3));
1599
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1600
0
}
1601
1602
static void dcf_move_acc_reg(m68k_info *info)
1603
260
{
1604
260
  cs_m68k_op *op0;
1605
260
  cs_m68k_op *op1;
1606
1607
260
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1608
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1609
0
  cf_build_reg_op(op0, cf_primary_acc_reg(info));
1610
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1611
0
}
1612
1613
static void dcf_move_accn_reg(m68k_info *info)
1614
531
{
1615
531
  cs_m68k_op *op0;
1616
531
  cs_m68k_op *op1;
1617
1618
531
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1619
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1620
0
  cf_build_reg_op(op0, cf_acc_reg((info->ir >> 9) & 3));
1621
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1622
0
}
1623
1624
static void dcf_move_acc_acc(m68k_info *info)
1625
196
{
1626
196
  cs_m68k_op *op0;
1627
196
  cs_m68k_op *op1;
1628
1629
196
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1630
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1631
0
  cf_build_reg_op(op0, cf_acc_reg(info->ir & 3));
1632
0
  cf_build_reg_op(op1, cf_acc_reg((info->ir >> 9) & 3));
1633
0
}
1634
1635
static void dcf_move_reg_acc(m68k_info *info)
1636
132
{
1637
132
  cs_m68k_op *op0;
1638
132
  cs_m68k_op *op1;
1639
1640
132
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1641
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1642
0
  cf_build_direct_reg_op(op0, cf_reg_from_nibble(info->ir & 0xf));
1643
0
  cf_build_reg_op(op1, cf_primary_acc_reg(info));
1644
0
}
1645
1646
static void dcf_move_reg_accn(m68k_info *info)
1647
381
{
1648
381
  cs_m68k_op *op0;
1649
381
  cs_m68k_op *op1;
1650
1651
381
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1652
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1653
0
  cf_build_direct_reg_op(op0, cf_reg_from_nibble(info->ir & 0xf));
1654
0
  cf_build_reg_op(op1, cf_acc_reg((info->ir >> 9) & 3));
1655
0
}
1656
1657
static void dcf_move_imm_acc(m68k_info *info)
1658
201
{
1659
201
  cs_m68k_op *op0;
1660
201
  cs_m68k_op *op1;
1661
1662
201
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1663
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1664
0
  cf_build_imm_op(op0, read_imm_32(info));
1665
0
  cf_build_reg_op(op1, cf_primary_acc_reg(info));
1666
0
}
1667
1668
static void dcf_move_imm_accn(m68k_info *info)
1669
445
{
1670
445
  cs_m68k_op *op0;
1671
445
  cs_m68k_op *op1;
1672
1673
445
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1674
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1675
0
  cf_build_imm_op(op0, read_imm_32(info));
1676
0
  cf_build_reg_op(op1, cf_acc_reg((info->ir >> 9) & 3));
1677
0
}
1678
1679
static void dcf_move_accext_reg(m68k_info *info)
1680
247
{
1681
247
  cs_m68k_op *op0;
1682
247
  cs_m68k_op *op1;
1683
1684
247
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1685
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1686
0
  cf_build_reg_op(op0, cf_accext_reg(info->ir));
1687
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1688
0
}
1689
1690
static void dcf_move_reg_accext(m68k_info *info)
1691
270
{
1692
270
  cs_m68k_op *op0;
1693
270
  cs_m68k_op *op1;
1694
1695
270
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1696
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1697
0
  cf_build_direct_reg_op(op0, cf_reg_from_nibble(info->ir & 0xf));
1698
0
  cf_build_reg_op(op1, cf_accext_reg(info->ir));
1699
0
}
1700
1701
static void dcf_move_imm_accext(m68k_info *info)
1702
205
{
1703
205
  cs_m68k_op *op0;
1704
205
  cs_m68k_op *op1;
1705
1706
205
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_EMAC);
1707
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1708
0
  cf_build_imm_op(op0, read_imm_32(info));
1709
0
  cf_build_reg_op(op1, cf_accext_reg(info->ir));
1710
0
}
1711
1712
static void dcf_move_macsr_reg(m68k_info *info)
1713
174
{
1714
174
  cs_m68k_op *op0;
1715
174
  cs_m68k_op *op1;
1716
1717
174
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1718
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1719
0
  cf_build_reg_op(op0, M68K_REG_MACSR);
1720
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1721
0
}
1722
1723
static void dcf_move_reg_macsr(m68k_info *info)
1724
207
{
1725
207
  cs_m68k_op *op0;
1726
207
  cs_m68k_op *op1;
1727
1728
207
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1729
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1730
0
  cf_build_direct_reg_op(op0, cf_reg_from_nibble(info->ir & 0xf));
1731
0
  cf_build_reg_op(op1, M68K_REG_MACSR);
1732
0
}
1733
1734
static void dcf_move_imm_macsr(m68k_info *info)
1735
321
{
1736
321
  cs_m68k_op *op0;
1737
321
  cs_m68k_op *op1;
1738
1739
321
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1740
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1741
0
  cf_build_imm_op(op0, read_imm_32(info));
1742
0
  cf_build_reg_op(op1, M68K_REG_MACSR);
1743
0
}
1744
1745
static void dcf_move_mask_reg(m68k_info *info)
1746
454
{
1747
454
  cs_m68k_op *op0;
1748
454
  cs_m68k_op *op1;
1749
1750
454
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1751
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1752
0
  cf_build_reg_op(op0, M68K_REG_MASK);
1753
0
  cf_build_direct_reg_op(op1, cf_reg_from_nibble(info->ir & 0xf));
1754
0
}
1755
1756
static void dcf_move_reg_mask(m68k_info *info)
1757
221
{
1758
221
  cs_m68k_op *op0;
1759
221
  cs_m68k_op *op1;
1760
1761
221
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1762
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1763
0
  cf_build_direct_reg_op(op0, cf_reg_from_nibble(info->ir & 0xf));
1764
0
  cf_build_reg_op(op1, M68K_REG_MASK);
1765
0
}
1766
1767
static void dcf_move_imm_mask(m68k_info *info)
1768
407
{
1769
407
  cs_m68k_op *op0;
1770
407
  cs_m68k_op *op1;
1771
1772
407
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1773
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1774
0
  cf_build_imm_op(op0, read_imm_32(info));
1775
0
  cf_build_reg_op(op1, M68K_REG_MASK);
1776
0
}
1777
1778
static void dcf_move_macsr_ccr(m68k_info *info)
1779
211
{
1780
211
  cs_m68k_op *op0;
1781
211
  cs_m68k_op *op1;
1782
1783
211
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1784
0
  cf_init_two_op(info, M68K_INS_MOVE, &op0, &op1);
1785
0
  cf_build_reg_op(op0, M68K_REG_MACSR);
1786
0
  cf_build_reg_op(op1, M68K_REG_CCR);
1787
0
}
1788
1789
static void dcf_mac_arith(m68k_info *info)
1790
6.72k
{
1791
6.72k
  uint16_t ext_word;
1792
6.72k
  cs_m68k *ext;
1793
6.72k
  cs_m68k_op *op0;
1794
6.72k
  cs_m68k_op *op1;
1795
6.72k
  cs_m68k_op *op;
1796
6.72k
  uint32_t src0;
1797
6.72k
  uint32_t src1;
1798
6.72k
  uint32_t update;
1799
6.72k
  uint32_t acc;
1800
6.72k
  bool is_memory;
1801
6.72k
  bool is_emac;
1802
6.72k
  bool is_dual_acc;
1803
6.72k
  int size;
1804
1805
6.72k
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC);
1806
1807
0
  is_memory = !m68k_ea_is_register_direct(info->ir);
1808
0
  if (is_memory && !cf_mac_ea_is_valid(info->ir)) {
1809
0
    d68000_invalid(info);
1810
0
    return;
1811
0
  }
1812
1813
0
  ext_word = (uint16_t)read_imm_16(info);
1814
0
  if (!is_memory && (ext_word & 0xf000)) {
1815
0
    d68000_invalid(info);
1816
0
    return;
1817
0
  }
1818
1819
0
  is_emac = m68k_has_feature(info, CS_MODE_M68K_CF_EMAC) != 0;
1820
0
  is_dual_acc = !is_memory && (ext_word & 0x1) &&
1821
0
          m68k_has_feature(info, CS_MODE_M68K_CF_EMAC_B);
1822
0
  size = (ext_word & 0x0800) ? 4 : 2;
1823
1824
0
  ext = build_init_op(info,
1825
0
          is_dual_acc    ? cf_dual_acc_insn(ext_word) :
1826
0
          (ext_word & 0x0100) ? M68K_INS_MSAC :
1827
0
              M68K_INS_MAC,
1828
0
          is_memory ? 0 : 2, size);
1829
0
  op0 = &ext->operands[0];
1830
0
  op1 = &ext->operands[1];
1831
1832
0
  if (is_memory) {
1833
0
    src0 = ext_word & 0xf;
1834
0
    src1 = (ext_word >> 12) & 0xf;
1835
0
    if (!(ext_word & 0x0800)) {
1836
0
      if (ext_word & 0x40)
1837
0
        src0 |= 0x10;
1838
0
      if (ext_word & 0x80)
1839
0
        src1 |= 0x10;
1840
0
    }
1841
0
  } else {
1842
0
    src0 = info->ir & 0xf;
1843
0
    src1 = ((info->ir >> 9) & 7) | ((info->ir & 0x40) ? 8 : 0);
1844
0
    if (!(ext_word & 0x0800)) {
1845
0
      if (ext_word & 0x40)
1846
0
        src0 |= 0x10;
1847
0
      if (ext_word & 0x80)
1848
0
        src1 |= 0x10;
1849
0
    }
1850
0
  }
1851
1852
0
  cf_build_mac_reg_op(op0, src0, size == 4);
1853
0
  cf_build_mac_reg_op(op1, src1, size == 4);
1854
0
  ext->op_count = 2;
1855
1856
0
  if (ext_word & 0x0600) {
1857
0
    op = &ext->operands[ext->op_count++];
1858
0
    cf_build_shift_op(op, ext_word & 0x0600);
1859
0
  }
1860
1861
0
  if (is_memory) {
1862
0
    op = &ext->operands[ext->op_count++];
1863
0
    if (!get_ea_mode_op(info, op, info->ir, size)) {
1864
0
      invalid_insn(info);
1865
0
      return;
1866
0
    }
1867
0
    if (ext_word & 0x20)
1868
0
      op->flags |= M68K_OP_FLAG_MEM_UPDATE;
1869
1870
0
    update = ((info->ir >> 9) & 7) | ((info->ir & 0x40) ? 8 : 0);
1871
0
    op = &ext->operands[ext->op_count++];
1872
0
    cf_build_direct_reg_op(op, cf_reg_from_nibble(update));
1873
0
  }
1874
1875
0
  if (is_dual_acc) {
1876
0
    acc = ((info->ir & 0x80) ? 1 : 0) | ((ext_word & 0x10) ? 2 : 0);
1877
0
    op = &ext->operands[ext->op_count++];
1878
0
    cf_build_reg_op(op, cf_acc_reg(acc));
1879
0
    op = &ext->operands[ext->op_count++];
1880
0
    cf_build_reg_op(op, cf_acc_reg((ext_word >> 2) & 0x3));
1881
0
  } else if (is_emac) {
1882
0
    if (is_memory)
1883
0
      acc = ((ext_word >> 3) & 0x2) |
1884
0
            ((~info->ir >> 7) & 0x1);
1885
0
    else
1886
0
      acc = ((info->ir & 0x80) ? 1 : 0) |
1887
0
            ((ext_word & 0x10) ? 2 : 0);
1888
0
    op = &ext->operands[ext->op_count++];
1889
0
    cf_build_reg_op(op, cf_acc_reg(acc));
1890
0
  }
1891
0
}
1892
1893
static void dcf_mvs_8(m68k_info *info)
1894
1.13k
{
1895
1.13k
  cs_m68k *ext;
1896
1897
1.13k
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1898
0
  ext = build_init_op(info, M68K_INS_MVS, 2, 1);
1899
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
1900
0
    invalid_insn(info);
1901
0
    return;
1902
0
  }
1903
0
  cf_build_direct_reg_op(&ext->operands[1],
1904
0
             (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7)));
1905
0
}
1906
1907
static void dcf_mvs_16(m68k_info *info)
1908
2.54k
{
1909
2.54k
  cs_m68k *ext;
1910
1911
2.54k
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1912
0
  ext = build_init_op(info, M68K_INS_MVS, 2, 2);
1913
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 2)) {
1914
0
    invalid_insn(info);
1915
0
    return;
1916
0
  }
1917
0
  cf_build_direct_reg_op(&ext->operands[1],
1918
0
             (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7)));
1919
0
}
1920
1921
static void dcf_mvz_8(m68k_info *info)
1922
410
{
1923
410
  cs_m68k *ext;
1924
1925
410
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1926
0
  ext = build_init_op(info, M68K_INS_MVZ, 2, 1);
1927
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
1928
0
    invalid_insn(info);
1929
0
    return;
1930
0
  }
1931
0
  cf_build_direct_reg_op(&ext->operands[1],
1932
0
             (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7)));
1933
0
}
1934
1935
static void dcf_mvz_16(m68k_info *info)
1936
708
{
1937
708
  cs_m68k *ext;
1938
1939
708
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1940
0
  ext = build_init_op(info, M68K_INS_MVZ, 2, 2);
1941
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 2)) {
1942
0
    invalid_insn(info);
1943
0
    return;
1944
0
  }
1945
0
  cf_build_direct_reg_op(&ext->operands[1],
1946
0
             (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7)));
1947
0
}
1948
1949
static void dcf_sats(m68k_info *info)
1950
245
{
1951
245
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
1952
0
  build_d(info, M68K_INS_SATS, 4);
1953
0
}
1954
1955
static void dcf_strldsr(m68k_info *info)
1956
0
{
1957
0
  cs_m68k *ext;
1958
0
  cs_m68k_op *op;
1959
1960
0
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A_PLUS | CS_MODE_M68K_CF_ISA_C);
1961
1962
0
  (void)read_imm_16(info);
1963
0
  ext = build_init_op(info, M68K_INS_STRLDSR, 1, 2);
1964
0
  op = &ext->operands[0];
1965
0
  cf_build_imm_op(op, read_imm_16(info));
1966
0
}
1967
1968
static void dcf_wddata(m68k_info *info)
1969
693
{
1970
693
  int size_bits = (info->ir >> 6) & 3;
1971
693
  int size;
1972
693
  cs_m68k *ext;
1973
1974
693
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A);
1975
1976
0
  switch (size_bits) {
1977
0
  case 0:
1978
0
    size = 1;
1979
0
    break;
1980
0
  case 1:
1981
0
    size = 2;
1982
0
    break;
1983
0
  case 2:
1984
0
    size = 4;
1985
0
    break;
1986
0
  default:
1987
0
    d68000_invalid(info);
1988
0
    return;
1989
0
  }
1990
1991
0
  if (!cf_alterable_memory_ea_is_valid(info->ir)) {
1992
0
    d68000_invalid(info);
1993
0
    return;
1994
0
  }
1995
1996
0
  ext = build_init_op(info, M68K_INS_WDDATA, 1, size);
1997
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) {
1998
0
    invalid_insn(info);
1999
0
    return;
2000
0
  }
2001
0
}
2002
2003
static void dcf_wdebug(m68k_info *info)
2004
68
{
2005
68
  cs_m68k *ext;
2006
2007
68
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A);
2008
2009
0
  if (read_imm_16(info) != 3) {
2010
0
    d68000_invalid(info);
2011
0
    return;
2012
0
  }
2013
2014
0
  ext = build_init_op(info, M68K_INS_WDEBUG, 1, 4);
2015
0
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) {
2016
0
    invalid_insn(info);
2017
0
    return;
2018
0
  }
2019
0
}
2020
2021
static void dcf_intouch(m68k_info *info)
2022
167
{
2023
167
  cs_m68k *ext;
2024
167
  cs_m68k_op *op;
2025
2026
167
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C);
2027
2028
0
  ext = build_init_op(info, M68K_INS_INTOUCH, 1, 0);
2029
0
  op = &ext->operands[0];
2030
0
  op->type = M68K_OP_MEM;
2031
0
  op->address_mode = M68K_AM_REGI_ADDR;
2032
0
  op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
2033
0
}
2034
2035
static void dcf_build_coproc_branch(m68k_info *info, int opcode,
2036
            int displacement)
2037
0
{
2038
0
  cs_m68k_op *op;
2039
0
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
2040
2041
0
  op = &ext->operands[0];
2042
0
  op->type = M68K_OP_BR_DISP;
2043
0
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
2044
0
  op->br_disp.disp = displacement;
2045
0
  op->br_disp.disp_size = 2;
2046
2047
0
  set_insn_group(info, M68K_GRP_JUMP);
2048
0
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2049
0
}
2050
2051
static int cf_coproc_size(uint16_t ir)
2052
0
{
2053
0
  switch (ir & 0x00c0) {
2054
0
  case 0x0000:
2055
0
    return 1;
2056
0
  case 0x0040:
2057
0
    return 2;
2058
0
  case 0x0080:
2059
0
    return 4;
2060
0
  default:
2061
0
    return 0;
2062
0
  }
2063
0
}
2064
2065
static void dcf_cp0bcbusy(m68k_info *info)
2066
209
{
2067
209
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A);
2068
0
  dcf_build_coproc_branch(info, M68K_INS_CP0BCBUSY,
2069
0
        make_int_16(read_imm_16(info)));
2070
0
}
2071
2072
static void dcf_cp1bcbusy(m68k_info *info)
2073
69
{
2074
69
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A);
2075
0
  dcf_build_coproc_branch(info, M68K_INS_CP1BCBUSY,
2076
0
        make_int_16(read_imm_16(info)));
2077
0
}
2078
2079
static void dcf_coproc_ldst(m68k_info *info)
2080
3.61k
{
2081
3.61k
  uint16_t ext_word;
2082
3.61k
  bool cp1;
2083
3.61k
  bool store;
2084
3.61k
  int size;
2085
3.61k
  int opcode;
2086
3.61k
  cs_m68k *ext;
2087
2088
3.61k
  LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_A);
2089
2090
0
  size = cf_coproc_size(info->ir);
2091
0
  if (!size || !cf_coproc_ea_is_valid(info->ir)) {
2092
0
    d68000_invalid(info);
2093
0
    return;
2094
0
  }
2095
2096
0
  cp1 = (info->ir & 0x0200) != 0;
2097
0
  store = (info->ir & 0x0100) != 0;
2098
0
  ext_word = (uint16_t)read_imm_16(info);
2099
2100
0
  if (!store && m68k_ea_field(info->ir) == M68K_EA_DATA_DIRECT_D0 &&
2101
0
      (ext_word & 0xf1ff) == 0) {
2102
0
    opcode = cp1 ? M68K_INS_CP1NOP : M68K_INS_CP0NOP;
2103
0
    ext = build_init_op(info, opcode, 1, 0);
2104
0
    cf_build_imm_op(&ext->operands[0], ((ext_word >> 9) & 7) + 1);
2105
0
    return;
2106
0
  }
2107
2108
0
  opcode = cp1 ? (store ? M68K_INS_CP1ST : M68K_INS_CP1LD) :
2109
0
           (store ? M68K_INS_CP0ST : M68K_INS_CP0LD);
2110
0
  ext = build_init_op(info, opcode, 4, size);
2111
2112
0
  if (store) {
2113
0
    cf_build_direct_reg_op(&ext->operands[0],
2114
0
               cf_reg_from_nibble((ext_word >> 12) &
2115
0
                0xf));
2116
0
    if (!get_ea_mode_op(info, &ext->operands[1], info->ir, size)) {
2117
0
      invalid_insn(info);
2118
0
      return;
2119
0
    }
2120
0
  } else {
2121
0
    if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) {
2122
0
      invalid_insn(info);
2123
0
      return;
2124
0
    }
2125
0
    cf_build_direct_reg_op(&ext->operands[1],
2126
0
               cf_reg_from_nibble((ext_word >> 12) &
2127
0
                0xf));
2128
0
  }
2129
2130
0
  cf_build_imm_op(&ext->operands[2], ((ext_word >> 9) & 7) + 1);
2131
0
  cf_build_imm_op(&ext->operands[3], ext_word & 0x1ff);
2132
0
}
2133
2134
static void d68000_abcd_rr(m68k_info *info)
2135
350
{
2136
350
  build_rr(info, M68K_INS_ABCD, 1, 0);
2137
350
}
2138
2139
static void d68000_abcd_mm(m68k_info *info)
2140
252
{
2141
252
  build_mm(info, M68K_INS_ABCD, 1, 0);
2142
252
}
2143
2144
static void d68000_add_er_8(m68k_info *info)
2145
634
{
2146
634
  build_er_1(info, M68K_INS_ADD, 1);
2147
634
}
2148
2149
static void d68000_add_er_16(m68k_info *info)
2150
496
{
2151
496
  build_er_1(info, M68K_INS_ADD, 2);
2152
496
}
2153
2154
static void d68000_add_er_32(m68k_info *info)
2155
598
{
2156
598
  build_er_1(info, M68K_INS_ADD, 4);
2157
598
}
2158
2159
static void d68000_add_re_8(m68k_info *info)
2160
1.03k
{
2161
1.03k
  build_re_1(info, M68K_INS_ADD, 1);
2162
1.03k
}
2163
2164
static void d68000_add_re_16(m68k_info *info)
2165
637
{
2166
637
  build_re_1(info, M68K_INS_ADD, 2);
2167
637
}
2168
2169
static void d68000_add_re_32(m68k_info *info)
2170
568
{
2171
568
  build_re_1(info, M68K_INS_ADD, 4);
2172
568
}
2173
2174
static void d68000_adda_16(m68k_info *info)
2175
1.34k
{
2176
1.34k
  build_ea_a(info, M68K_INS_ADDA, 2);
2177
1.34k
}
2178
2179
static void d68000_adda_32(m68k_info *info)
2180
2.42k
{
2181
2.42k
  build_ea_a(info, M68K_INS_ADDA, 4);
2182
2.42k
}
2183
2184
static void d68000_addi_8(m68k_info *info)
2185
548
{
2186
548
  build_imm_ea(info, M68K_INS_ADDI, 1, read_imm_8(info));
2187
548
}
2188
2189
static void d68000_addi_16(m68k_info *info)
2190
237
{
2191
237
  build_imm_ea(info, M68K_INS_ADDI, 2, read_imm_16(info));
2192
237
}
2193
2194
static void d68000_addi_32(m68k_info *info)
2195
255
{
2196
255
  build_imm_ea(info, M68K_INS_ADDI, 4, read_imm_32(info));
2197
255
}
2198
2199
static void d68000_addq_8(m68k_info *info)
2200
1.16k
{
2201
1.16k
  build_3bit_ea(info, M68K_INS_ADDQ, 1);
2202
1.16k
}
2203
2204
static void d68000_addq_16(m68k_info *info)
2205
3.62k
{
2206
3.62k
  build_3bit_ea(info, M68K_INS_ADDQ, 2);
2207
3.62k
}
2208
2209
static void d68000_addq_32(m68k_info *info)
2210
373
{
2211
373
  build_3bit_ea(info, M68K_INS_ADDQ, 4);
2212
373
}
2213
2214
static void d68000_addx_rr_8(m68k_info *info)
2215
687
{
2216
687
  build_rr(info, M68K_INS_ADDX, 1, 0);
2217
687
}
2218
2219
static void d68000_addx_rr_16(m68k_info *info)
2220
623
{
2221
623
  build_rr(info, M68K_INS_ADDX, 2, 0);
2222
623
}
2223
2224
static void d68000_addx_rr_32(m68k_info *info)
2225
304
{
2226
304
  build_rr(info, M68K_INS_ADDX, 4, 0);
2227
304
}
2228
2229
static void d68000_addx_mm_8(m68k_info *info)
2230
305
{
2231
305
  build_mm(info, M68K_INS_ADDX, 1, 0);
2232
305
}
2233
2234
static void d68000_addx_mm_16(m68k_info *info)
2235
308
{
2236
308
  build_mm(info, M68K_INS_ADDX, 2, 0);
2237
308
}
2238
2239
static void d68000_addx_mm_32(m68k_info *info)
2240
751
{
2241
751
  build_mm(info, M68K_INS_ADDX, 4, 0);
2242
751
}
2243
2244
static void d68000_and_er_8(m68k_info *info)
2245
562
{
2246
562
  build_er_1(info, M68K_INS_AND, 1);
2247
562
}
2248
2249
static void d68000_and_er_16(m68k_info *info)
2250
980
{
2251
980
  build_er_1(info, M68K_INS_AND, 2);
2252
980
}
2253
2254
static void d68000_and_er_32(m68k_info *info)
2255
726
{
2256
726
  build_er_1(info, M68K_INS_AND, 4);
2257
726
}
2258
2259
static void d68000_and_re_8(m68k_info *info)
2260
323
{
2261
323
  build_re_1(info, M68K_INS_AND, 1);
2262
323
}
2263
2264
static void d68000_and_re_16(m68k_info *info)
2265
558
{
2266
558
  build_re_1(info, M68K_INS_AND, 2);
2267
558
}
2268
2269
static void d68000_and_re_32(m68k_info *info)
2270
640
{
2271
640
  build_re_1(info, M68K_INS_AND, 4);
2272
640
}
2273
2274
static void d68000_andi_8(m68k_info *info)
2275
541
{
2276
541
  build_imm_ea(info, M68K_INS_ANDI, 1, read_imm_8(info));
2277
541
}
2278
2279
static void d68000_andi_16(m68k_info *info)
2280
359
{
2281
359
  build_imm_ea(info, M68K_INS_ANDI, 2, read_imm_16(info));
2282
359
}
2283
2284
static void d68000_andi_32(m68k_info *info)
2285
418
{
2286
418
  build_imm_ea(info, M68K_INS_ANDI, 4, read_imm_32(info));
2287
418
}
2288
2289
static void d68000_andi_to_ccr(m68k_info *info)
2290
208
{
2291
208
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_8(info), 1,
2292
208
            M68K_REG_CCR);
2293
208
}
2294
2295
static void d68000_andi_to_sr(m68k_info *info)
2296
250
{
2297
250
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_16(info), 2,
2298
250
            M68K_REG_SR);
2299
250
}
2300
2301
static void d68000_asr_s_8(m68k_info *info)
2302
758
{
2303
758
  build_3bit_d(info, M68K_INS_ASR, 1);
2304
758
}
2305
2306
static void d68000_asr_s_16(m68k_info *info)
2307
244
{
2308
244
  build_3bit_d(info, M68K_INS_ASR, 2);
2309
244
}
2310
2311
static void d68000_asr_s_32(m68k_info *info)
2312
278
{
2313
278
  build_3bit_d(info, M68K_INS_ASR, 4);
2314
278
}
2315
2316
static void d68000_asr_r_8(m68k_info *info)
2317
631
{
2318
631
  build_r(info, M68K_INS_ASR, 1);
2319
631
}
2320
2321
static void d68000_asr_r_16(m68k_info *info)
2322
770
{
2323
770
  build_r(info, M68K_INS_ASR, 2);
2324
770
}
2325
2326
static void d68000_asr_r_32(m68k_info *info)
2327
215
{
2328
215
  build_r(info, M68K_INS_ASR, 4);
2329
215
}
2330
2331
static void d68000_asr_ea(m68k_info *info)
2332
441
{
2333
441
  build_ea(info, M68K_INS_ASR, 2);
2334
441
}
2335
2336
static void d68000_asl_s_8(m68k_info *info)
2337
790
{
2338
790
  build_3bit_d(info, M68K_INS_ASL, 1);
2339
790
}
2340
2341
static void d68000_asl_s_16(m68k_info *info)
2342
445
{
2343
445
  build_3bit_d(info, M68K_INS_ASL, 2);
2344
445
}
2345
2346
static void d68000_asl_s_32(m68k_info *info)
2347
145
{
2348
145
  build_3bit_d(info, M68K_INS_ASL, 4);
2349
145
}
2350
2351
static void d68000_asl_r_8(m68k_info *info)
2352
342
{
2353
342
  build_r(info, M68K_INS_ASL, 1);
2354
342
}
2355
2356
static void d68000_asl_r_16(m68k_info *info)
2357
429
{
2358
429
  build_r(info, M68K_INS_ASL, 2);
2359
429
}
2360
2361
static void d68000_asl_r_32(m68k_info *info)
2362
358
{
2363
358
  build_r(info, M68K_INS_ASL, 4);
2364
358
}
2365
2366
static void d68000_asl_ea(m68k_info *info)
2367
172
{
2368
172
  build_ea(info, M68K_INS_ASL, 2);
2369
172
}
2370
2371
static void d68000_bcc_8(m68k_info *info)
2372
13.6k
{
2373
13.6k
  build_bcc(info, 1, make_int_8(info->ir));
2374
13.6k
}
2375
2376
static void d68000_bcc_16(m68k_info *info)
2377
738
{
2378
738
  build_bcc(info, 2, make_int_16(read_imm_16(info)));
2379
738
}
2380
2381
static void d68020_bcc_32(m68k_info *info)
2382
536
{
2383
536
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2384
536
            CS_MODE_M68K_CF_ISA_C);
2385
226
  build_bcc(info, 4, read_imm_32(info));
2386
226
}
2387
2388
12.1k
#define CS_M68K_EA_MODE_FIELD_MASK 0x38
2389
2390
/* Bit operations are long on a data register and byte on memory. */
2391
static uint8_t bit_op_size(const m68k_info *info)
2392
12.1k
{
2393
12.1k
  return (info->ir & CS_M68K_EA_MODE_FIELD_MASK) ? 1 : 4;
2394
12.1k
}
2395
2396
static void d68000_bchg_r(m68k_info *info)
2397
1.81k
{
2398
1.81k
  build_re_1(info, M68K_INS_BCHG, bit_op_size(info));
2399
1.81k
}
2400
2401
static void d68000_bchg_s(m68k_info *info)
2402
233
{
2403
233
  build_imm_ea(info, M68K_INS_BCHG, bit_op_size(info), read_imm_8(info));
2404
233
}
2405
2406
static void d68000_bclr_r(m68k_info *info)
2407
2.24k
{
2408
2.24k
  build_re_1(info, M68K_INS_BCLR, bit_op_size(info));
2409
2.24k
}
2410
2411
static void d68000_bclr_s(m68k_info *info)
2412
131
{
2413
131
  build_imm_ea(info, M68K_INS_BCLR, bit_op_size(info), read_imm_8(info));
2414
131
}
2415
2416
static void d68010_bkpt(m68k_info *info)
2417
752
{
2418
752
  LIMIT_FEATURE(info, M68010_PLUS);
2419
461
  build_absolute_jump_with_immediate(info, M68K_INS_BKPT, 0,
2420
461
             info->ir & 7);
2421
461
}
2422
2423
static void d68020_bfchg(m68k_info *info)
2424
635
{
2425
  /* Bit field ops are 68020+ only; CPU32 does NOT support them
2426
   * despite sharing CS_MODE_M68K_020. */
2427
635
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2428
337
  build_bitfield_ins(info, M68K_INS_BFCHG, false);
2429
337
}
2430
2431
static void d68020_bfclr(m68k_info *info)
2432
561
{
2433
561
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2434
349
  build_bitfield_ins(info, M68K_INS_BFCLR, false);
2435
349
}
2436
2437
static void d68020_bfexts(m68k_info *info)
2438
562
{
2439
562
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2440
291
  build_bitfield_ins(info, M68K_INS_BFEXTS, true);
2441
291
}
2442
2443
static void d68020_bfextu(m68k_info *info)
2444
401
{
2445
401
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2446
218
  build_bitfield_ins(info, M68K_INS_BFEXTU, true);
2447
218
}
2448
2449
static void d68020_bfffo(m68k_info *info)
2450
475
{
2451
475
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2452
283
  build_bitfield_ins(info, M68K_INS_BFFFO, true);
2453
283
}
2454
2455
static void d68020_bfins(m68k_info *info)
2456
322
{
2457
322
  cs_m68k *ext = &info->extension;
2458
322
  cs_m68k_op temp;
2459
2460
322
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2461
225
  build_bitfield_ins(info, M68K_INS_BFINS, true);
2462
2463
  // a bit hacky but we need to flip the args on only this instruction
2464
2465
225
  temp = ext->operands[0];
2466
225
  ext->operands[0] = ext->operands[1];
2467
225
  ext->operands[1] = temp;
2468
225
}
2469
2470
static void d68020_bfset(m68k_info *info)
2471
288
{
2472
288
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2473
205
  build_bitfield_ins(info, M68K_INS_BFSET, false);
2474
205
}
2475
2476
static void d68020_bftst(m68k_info *info)
2477
411
{
2478
411
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2479
201
  build_bitfield_ins(info, M68K_INS_BFTST, false);
2480
201
}
2481
2482
static void d68000_bra_8(m68k_info *info)
2483
1.58k
{
2484
1.58k
  build_relative_branch(info, M68K_INS_BRA, 1, make_int_8(info->ir));
2485
1.58k
}
2486
2487
static void d68000_bra_16(m68k_info *info)
2488
376
{
2489
376
  build_relative_branch(info, M68K_INS_BRA, 2,
2490
376
            make_int_16(read_imm_16(info)));
2491
376
}
2492
2493
static void d68020_bra_32(m68k_info *info)
2494
140
{
2495
140
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2496
140
            CS_MODE_M68K_CF_ISA_C);
2497
72
  build_relative_branch(info, M68K_INS_BRA, 4, read_imm_32(info));
2498
72
}
2499
2500
static void d68000_bset_r(m68k_info *info)
2501
2.22k
{
2502
2.22k
  build_re_1(info, M68K_INS_BSET, bit_op_size(info));
2503
2.22k
}
2504
2505
static void d68000_bset_s(m68k_info *info)
2506
362
{
2507
362
  build_imm_ea(info, M68K_INS_BSET, bit_op_size(info), read_imm_8(info));
2508
362
}
2509
2510
static void d68000_bsr_8(m68k_info *info)
2511
1.19k
{
2512
1.19k
  build_relative_branch(info, M68K_INS_BSR, 1, make_int_8(info->ir));
2513
1.19k
}
2514
2515
static void d68000_bsr_16(m68k_info *info)
2516
594
{
2517
594
  build_relative_branch(info, M68K_INS_BSR, 2,
2518
594
            make_int_16(read_imm_16(info)));
2519
594
}
2520
2521
static void d68020_bsr_32(m68k_info *info)
2522
405
{
2523
405
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2524
405
            CS_MODE_M68K_CF_ISA_C);
2525
210
  build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info));
2526
210
}
2527
2528
static void d68000_btst_r(m68k_info *info)
2529
4.84k
{
2530
  // Size 2 reads a #imm destination as its full extension word.
2531
4.84k
  build_re_1(info, M68K_INS_BTST, 2);
2532
4.84k
  ISIZE = bit_op_size(info);
2533
4.84k
}
2534
2535
static void d68000_btst_s(m68k_info *info)
2536
336
{
2537
336
  build_imm_ea(info, M68K_INS_BTST, bit_op_size(info), read_imm_8(info));
2538
336
}
2539
2540
static void d68020_callm(m68k_info *info)
2541
507
{
2542
507
  LIMIT_FEATURE(info, M68020_ONLY);
2543
0
  build_imm_ea(info, M68K_INS_CALLM, 0, read_imm_8(info));
2544
0
}
2545
2546
static void d68020_cas_8(m68k_info *info)
2547
147
{
2548
  /*
2549
   * MC68060 traps CAS/CAS2/CHK2/CMP2 for software emulation, but they remain
2550
   * valid opcodes and must still disassemble successfully.
2551
   * CAS/CAS2 are NOT available on CPU32 despite its CS_MODE_M68K_020 overlap.
2552
   */
2553
147
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2554
81
  build_d_d_ea(info, M68K_INS_CAS, 1);
2555
81
}
2556
2557
static void d68020_cas_16(m68k_info *info)
2558
140
{
2559
140
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2560
74
  build_d_d_ea(info, M68K_INS_CAS, 2);
2561
74
}
2562
2563
static void d68020_cas_32(m68k_info *info)
2564
351
{
2565
351
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2566
283
  build_d_d_ea(info, M68K_INS_CAS, 4);
2567
283
}
2568
2569
static void d68020_cas2_16(m68k_info *info)
2570
219
{
2571
219
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2572
152
  build_cas2(info, 2);
2573
152
}
2574
2575
static void d68020_cas2_32(m68k_info *info)
2576
2.09k
{
2577
2.09k
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2578
1.89k
  build_cas2(info, 4);
2579
1.89k
}
2580
2581
static void d68000_chk_16(m68k_info *info)
2582
453
{
2583
453
  build_er_1(info, M68K_INS_CHK, 2);
2584
453
}
2585
2586
static void d68020_chk_32(m68k_info *info)
2587
1.09k
{
2588
1.09k
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2589
781
  build_er_1(info, M68K_INS_CHK, 4);
2590
781
}
2591
2592
static void d68020_chk2_cmp2_8(m68k_info *info)
2593
421
{
2594
421
  LIMIT_FEATURE(info, M68020_PLUS);
2595
124
  build_chk2_cmp2(info, 1);
2596
124
}
2597
2598
static void d68020_chk2_cmp2_16(m68k_info *info)
2599
390
{
2600
390
  LIMIT_FEATURE(info, M68020_PLUS);
2601
202
  build_chk2_cmp2(info, 2);
2602
202
}
2603
2604
static void d68020_chk2_cmp2_32(m68k_info *info)
2605
331
{
2606
331
  LIMIT_FEATURE(info, M68020_PLUS);
2607
265
  build_chk2_cmp2(info, 4);
2608
265
}
2609
2610
static void d68040_cinv(m68k_info *info)
2611
1.26k
{
2612
1.26k
  LIMIT_FEATURE(info, M68040_PLUS);
2613
1.03k
  build_cpush_cinv(info, M68K_INS_CINVL);
2614
1.03k
}
2615
2616
static void d68000_clr_8(m68k_info *info)
2617
303
{
2618
303
  build_ea(info, M68K_INS_CLR, 1);
2619
303
}
2620
2621
static void d68000_clr_16(m68k_info *info)
2622
484
{
2623
484
  build_ea(info, M68K_INS_CLR, 2);
2624
484
}
2625
2626
static void d68000_clr_32(m68k_info *info)
2627
251
{
2628
251
  build_ea(info, M68K_INS_CLR, 4);
2629
251
}
2630
2631
static void d68000_cmp_8(m68k_info *info)
2632
600
{
2633
600
  build_er_1(info, M68K_INS_CMP, 1);
2634
600
}
2635
2636
static void d68000_cmp_16(m68k_info *info)
2637
473
{
2638
473
  build_er_1(info, M68K_INS_CMP, 2);
2639
473
}
2640
2641
static void d68000_cmp_32(m68k_info *info)
2642
2.24k
{
2643
2.24k
  build_er_1(info, M68K_INS_CMP, 4);
2644
2.24k
}
2645
2646
static void d68000_cmpa_16(m68k_info *info)
2647
656
{
2648
656
  build_ea_a(info, M68K_INS_CMPA, 2);
2649
656
}
2650
2651
static void d68000_cmpa_32(m68k_info *info)
2652
579
{
2653
579
  build_ea_a(info, M68K_INS_CMPA, 4);
2654
579
}
2655
2656
static void d68000_cmpi_8(m68k_info *info)
2657
589
{
2658
589
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2659
589
}
2660
2661
static void d68020_cmpi_pcdi_8(m68k_info *info)
2662
326
{
2663
326
  LIMIT_FEATURE(info, M68010_PLUS);
2664
240
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2665
240
}
2666
2667
static void d68020_cmpi_pcix_8(m68k_info *info)
2668
575
{
2669
575
  LIMIT_FEATURE(info, M68010_PLUS);
2670
289
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2671
289
}
2672
2673
static void d68000_cmpi_16(m68k_info *info)
2674
326
{
2675
326
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2676
326
}
2677
2678
static void d68020_cmpi_pcdi_16(m68k_info *info)
2679
564
{
2680
564
  LIMIT_FEATURE(info, M68010_PLUS);
2681
227
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2682
227
}
2683
2684
static void d68020_cmpi_pcix_16(m68k_info *info)
2685
528
{
2686
528
  LIMIT_FEATURE(info, M68010_PLUS);
2687
80
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2688
80
}
2689
2690
static void d68000_cmpi_32(m68k_info *info)
2691
100
{
2692
100
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2693
100
}
2694
2695
static void d68020_cmpi_pcdi_32(m68k_info *info)
2696
406
{
2697
406
  LIMIT_FEATURE(info, M68010_PLUS);
2698
205
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2699
205
}
2700
2701
static void d68020_cmpi_pcix_32(m68k_info *info)
2702
324
{
2703
324
  LIMIT_FEATURE(info, M68010_PLUS);
2704
229
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2705
229
}
2706
2707
static void d68000_cmpm_8(m68k_info *info)
2708
167
{
2709
167
  build_pi_pi(info, M68K_INS_CMPM, 1);
2710
167
}
2711
2712
static void d68000_cmpm_16(m68k_info *info)
2713
540
{
2714
540
  build_pi_pi(info, M68K_INS_CMPM, 2);
2715
540
}
2716
2717
static void d68000_cmpm_32(m68k_info *info)
2718
252
{
2719
252
  build_pi_pi(info, M68K_INS_CMPM, 4);
2720
252
}
2721
2722
static void make_cpbcc_operand(cs_m68k_op *op, int size, int displacement)
2723
2.80k
{
2724
2.80k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
2725
2.80k
  op->type = M68K_OP_BR_DISP;
2726
2.80k
  op->br_disp.disp = displacement;
2727
2.80k
  op->br_disp.disp_size = size;
2728
2.80k
}
2729
2730
static void d68020_cpbcc_16(m68k_info *info)
2731
2.12k
{
2732
2.12k
  cs_m68k_op *op0;
2733
2.12k
  cs_m68k *ext;
2734
2.12k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2735
1.85k
  int cpid = M68K_CPID(info);
2736
1.85k
  int cond = m68k_coprocessor_condition(info->ir);
2737
1.85k
  if (cpid == M68K_CPID_MMU) {
2738
865
    if (cond >= M68K_PMMU_MAX_COND ||
2739
639
        m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
2740
226
      d68000_invalid(info);
2741
226
      return;
2742
226
    }
2743
988
  } else if (cpid != M68K_CPID_FPU) {
2744
257
    d68000_invalid(info);
2745
257
    return;
2746
257
  }
2747
2748
1.37k
  if (info->ir == 0xf280 && peek_imm_16(info) == 0) {
2749
22
    MCInst_setOpcode(info->inst, M68K_INS_FNOP);
2750
22
    info->pc += 2;
2751
22
    return;
2752
22
  }
2753
2754
1.34k
  ext = build_init_fpu_condition_op(info, M68K_INS_FBF, info->ir, 1, 2);
2755
1.34k
  op0 = &ext->operands[0];
2756
2757
1.34k
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_WORD,
2758
1.34k
         make_int_16(read_imm_16(info)));
2759
2760
1.34k
  set_insn_group(info, M68K_GRP_JUMP);
2761
1.34k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2762
1.34k
}
2763
2764
static void d68020_cpbcc_32(m68k_info *info)
2765
3.75k
{
2766
3.75k
  cs_m68k *ext;
2767
3.75k
  cs_m68k_op *op0;
2768
3.75k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2769
2.73k
  int cpid = M68K_CPID(info);
2770
2.73k
  int cond = m68k_coprocessor_condition(info->ir);
2771
2.73k
  if (cpid == M68K_CPID_MMU) {
2772
1.01k
    if (cond >= M68K_PMMU_MAX_COND ||
2773
784
        m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
2774
784
      d68000_invalid(info);
2775
784
      return;
2776
784
    }
2777
1.72k
  } else if (cpid != M68K_CPID_FPU) {
2778
1.00k
    d68000_invalid(info);
2779
1.00k
    return;
2780
1.00k
  }
2781
2782
943
  ext = build_init_fpu_condition_op(info, M68K_INS_FBF, info->ir, 1, 4);
2783
943
  op0 = &ext->operands[0];
2784
2785
943
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_LONG, read_imm_32(info));
2786
2787
943
  set_insn_group(info, M68K_GRP_JUMP);
2788
943
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2789
943
}
2790
2791
static void d68020_cpdbcc(m68k_info *info)
2792
1.37k
{
2793
1.37k
  cs_m68k *ext;
2794
1.37k
  cs_m68k_op *op0;
2795
1.37k
  cs_m68k_op *op1;
2796
1.37k
  uint32_t ext1, ext2;
2797
2798
1.37k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2799
2800
1.05k
  if (M68K_CPID(info) == M68K_CPID_CACHE &&
2801
253
      m68k_has_feature(info, M68040_PLUS)) {
2802
253
    if (M68K_IR_IS_CPUSH(info))
2803
0
      d68040_cpush(info);
2804
253
    else
2805
253
      d68040_cinv(info);
2806
253
    return;
2807
253
  }
2808
2809
805
  REQUIRE_CPID_FPU(info);
2810
2811
509
  ext1 = read_imm_16(info);
2812
509
  ext2 = read_imm_16(info);
2813
2814
509
  ext = build_init_fpu_condition_op(info, M68K_INS_FDBF, ext1, 2, 0);
2815
509
  op0 = &ext->operands[0];
2816
509
  op1 = &ext->operands[1];
2817
2818
509
  op0->reg = M68K_REG_D0 + (info->ir & 7);
2819
2820
509
  make_cpbcc_operand(op1, M68K_OP_BR_DISP_SIZE_WORD,
2821
509
         make_int_16(ext2) + 2);
2822
2823
509
  set_insn_group(info, M68K_GRP_JUMP);
2824
509
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2825
509
}
2826
2827
static void fmove_fpcr(m68k_info *info, uint32_t extension)
2828
1.08k
{
2829
1.08k
  cs_m68k_op *special;
2830
1.08k
  cs_m68k_op *op_ea;
2831
2832
1.08k
  int regsel = M68K_FEXT_REGSEL(extension);
2833
1.08k
  int dir = M68K_FEXT_DIR(extension);
2834
2835
1.08k
  cs_m68k *ext = build_init_op(info, M68K_INS_FMOVE, 2, 4);
2836
2837
1.08k
  special = &ext->operands[0];
2838
1.08k
  op_ea = &ext->operands[1];
2839
2840
1.08k
  if (!dir) {
2841
652
    cs_m68k_op *t = special;
2842
652
    special = op_ea;
2843
652
    op_ea = t;
2844
652
  }
2845
2846
1.08k
  if (!get_ea_mode_op(info, op_ea, info->ir, 4)) {
2847
1
    invalid_insn(info);
2848
1
    return;
2849
1
  }
2850
2851
1.08k
  if (regsel & 4)
2852
371
    special->reg = M68K_REG_FPCR;
2853
709
  else if (regsel & 2)
2854
102
    special->reg = M68K_REG_FPSR;
2855
607
  else if (regsel & 1)
2856
245
    special->reg = M68K_REG_FPIAR;
2857
1.08k
}
2858
2859
static bool m68k_fmovem_is_valid(uint32_t ir, uint32_t extension)
2860
4.01k
{
2861
4.01k
  int dir = M68K_FEXT_DIR(extension);
2862
4.01k
  m68k_fmovem_mode mode = m68k_fmovem_get_mode(extension);
2863
4.01k
  bool is_predecrement = m68k_ea_mode(ir) ==
2864
4.01k
             M68K_EA_MODE_ADDR_INDIRECT_PRE_DEC;
2865
4.01k
  bool is_postincrement = m68k_ea_mode(ir) ==
2866
4.01k
        M68K_EA_MODE_ADDR_INDIRECT_POST_INC;
2867
2868
4.01k
  if (BITFIELD(extension, 10, 8) != 0)
2869
16
    return false;
2870
2871
4.00k
  switch (mode) {
2872
200
  case M68K_FMOVEM_MODE_STATIC_PREDECREMENT:
2873
200
    return dir && is_predecrement;
2874
70
  case M68K_FMOVEM_MODE_DYNAMIC_PREDECREMENT:
2875
70
    return m68k_fmovem_dynamic_reserved_bits_are_zero(extension) &&
2876
69
           dir && is_predecrement;
2877
2.20k
  case M68K_FMOVEM_MODE_STATIC_POSTINCREMENT_OR_CONTROL:
2878
2.20k
    return dir ? m68k_ea_is_alterable_control(ir) :
2879
2.20k
           (is_postincrement || m68k_ea_is_control(ir));
2880
1.52k
  case M68K_FMOVEM_MODE_DYNAMIC_POSTINCREMENT_OR_CONTROL:
2881
1.52k
    return m68k_fmovem_dynamic_reserved_bits_are_zero(extension) &&
2882
1.51k
           (dir ? m68k_ea_is_alterable_control(ir) :
2883
1.51k
            (is_postincrement || m68k_ea_is_control(ir)));
2884
0
  default:
2885
0
    return false;
2886
4.00k
  }
2887
4.00k
}
2888
2889
static void fmovem(m68k_info *info, uint32_t extension)
2890
4.01k
{
2891
4.01k
  cs_m68k_op *op_reglist;
2892
4.01k
  cs_m68k_op *op_ea;
2893
4.01k
  int dir = M68K_FEXT_DIR(extension);
2894
4.01k
  m68k_fmovem_mode mode = m68k_fmovem_get_mode(extension);
2895
4.01k
  uint32_t reglist = m68k_fmovem_register_list(extension);
2896
4.01k
  cs_m68k *ext;
2897
2898
4.01k
  if (!m68k_fmovem_is_valid(info->ir, extension)) {
2899
27
    invalid_insn(info);
2900
27
    return;
2901
27
  }
2902
2903
3.98k
  ext = build_init_op(info, M68K_INS_FMOVEM, 2, 0);
2904
2905
3.98k
  op_reglist = &ext->operands[0];
2906
3.98k
  op_ea = &ext->operands[1];
2907
2908
  // flip args around
2909
2910
3.98k
  if (!dir) {
2911
1.88k
    cs_m68k_op *t = op_reglist;
2912
1.88k
    op_reglist = op_ea;
2913
1.88k
    op_ea = t;
2914
1.88k
  }
2915
2916
3.98k
  if (!get_ea_mode_op(info, op_ea, info->ir, 0)) {
2917
0
    invalid_insn(info);
2918
0
    return;
2919
0
  }
2920
2921
3.98k
  switch (mode) {
2922
68
  case M68K_FMOVEM_MODE_DYNAMIC_PREDECREMENT:
2923
1.58k
  case M68K_FMOVEM_MODE_DYNAMIC_POSTINCREMENT_OR_CONTROL:
2924
1.58k
    op_reglist->reg =
2925
1.58k
      M68K_REG_D0 + m68k_fmovem_dynamic_register(extension);
2926
1.58k
    break;
2927
2928
199
  case M68K_FMOVEM_MODE_STATIC_PREDECREMENT:
2929
199
    op_reglist->address_mode = M68K_AM_NONE;
2930
199
    op_reglist->type = M68K_OP_REG_BITS;
2931
199
    op_reglist->register_bits = reglist << 16;
2932
199
    break;
2933
2934
2.20k
  case M68K_FMOVEM_MODE_STATIC_POSTINCREMENT_OR_CONTROL:
2935
2.20k
    op_reglist->address_mode = M68K_AM_NONE;
2936
2.20k
    op_reglist->type = M68K_OP_REG_BITS;
2937
2.20k
    op_reglist->register_bits = ((uint32_t)reverse_bits_8(reglist))
2938
2.20k
              << 16;
2939
2.20k
    break;
2940
0
  default:
2941
0
    break;
2942
3.98k
  }
2943
3.98k
}
2944
2945
static void d68020_cpgen(m68k_info *info)
2946
17.3k
{
2947
17.3k
  cs_m68k *ext;
2948
17.3k
  cs_m68k_op *op0;
2949
17.3k
  cs_m68k_op *op1;
2950
17.3k
  bool supports_single_op;
2951
17.3k
  bool is_fmove;
2952
17.3k
  bool packed_destination;
2953
17.3k
  bool ea_operand;
2954
17.3k
  uint32_t next;
2955
17.3k
  int command_type, src, dst, opmode;
2956
2957
17.3k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2958
2959
16.0k
  if (M68K_CPID(info) == M68K_CPID_MMU &&
2960
402
      m68k_has_feature(info, CS_MODE_M68K_030)) {
2961
0
    d68030_pmmu(info);
2962
0
    return;
2963
0
  }
2964
2965
16.0k
  if (M68K_CPID(info) != M68K_CPID_FPU) {
2966
808
    d68000_invalid(info);
2967
808
    return;
2968
808
  }
2969
2970
15.2k
  supports_single_op = true;
2971
2972
  /* 68040+ single/double-precision FPU opcodes (SD flag set in command
2973
   * word) must be rejected on pre-68040 CPUs.  Only guard general FPU
2974
   * operations (type 0-1); fmove_fpcr/fmovem types are dispatched
2975
   * separately and never reach the SD path. */
2976
15.2k
  uint32_t peeked = peek_imm_16(info);
2977
15.2k
  if (M68K_FEXT_TYPE(peeked) <= M68K_FEXT_TYPE_GENERAL_MAX &&
2978
2.22k
      M68K_FEXT_SD_FLAG(peeked))
2979
847
    LIMIT_FEATURE(info, M68040_PLUS | CS_MODE_M68K_CF_FPU);
2980
2981
15.2k
  next = read_imm_16(info);
2982
2983
15.2k
  ea_operand = M68K_FEXT_RM(next) != 0;
2984
15.2k
  command_type = M68K_FEXT_TYPE(next);
2985
15.2k
  src = M68K_FEXT_SRC(next);
2986
15.2k
  dst = M68K_FEXT_DST(next);
2987
15.2k
  opmode = M68K_FEXT_OPMODE(next);
2988
15.2k
  packed_destination = command_type == M68K_FEXT_TYPE_FMOVE_TO_EA &&
2989
2.15k
           (src == M68K_FPDST_PACKED_STATIC ||
2990
1.80k
            src == M68K_FPDST_PACKED_DYNAMIC);
2991
2992
15.2k
  if (BITFIELD(info->ir, 5, 0) == 0 && M68K_FEXT_IS_FMOVECR(next)) {
2993
581
    ext = build_init_op(info, M68K_INS_FMOVECR, 2, 0);
2994
2995
581
    op0 = &ext->operands[0];
2996
581
    op1 = &ext->operands[1];
2997
2998
581
    op0->address_mode = M68K_AM_IMMEDIATE;
2999
581
    op0->type = M68K_OP_IMM;
3000
581
    op0->imm = M68K_FEXT_OPMODE(next);
3001
3002
581
    op1->reg = M68K_REG_FP0 + M68K_FEXT_DST(next);
3003
3004
581
    return;
3005
581
  }
3006
3007
14.7k
  switch (command_type) {
3008
652
  case M68K_FEXT_TYPE_FPCR_FROM_EA:
3009
1.08k
  case M68K_FEXT_TYPE_FPCR_TO_EA:
3010
1.08k
    fmove_fpcr(info, next);
3011
1.08k
    return;
3012
3013
1.90k
  case M68K_FEXT_TYPE_FMOVEM_FROM_EA:
3014
4.01k
  case M68K_FEXT_TYPE_FMOVEM_TO_EA:
3015
4.01k
    fmovem(info, next);
3016
4.01k
    return;
3017
9.60k
  default:
3018
9.60k
    break;
3019
14.7k
  }
3020
3021
  /* In a packed register-to-memory FMOVE, bits 6:0 encode the static
3022
   * k-factor or dynamic Dn selector rather than an arithmetic opmode. */
3023
9.60k
  if (packed_destination) {
3024
521
    MCInst_setOpcode(info->inst, M68K_INS_FMOVE);
3025
521
    supports_single_op = false;
3026
521
    goto fpu_operands;
3027
521
  }
3028
3029
9.08k
  if (M68K_FEXT_SD_FLAG(next)) {
3030
2.29k
    if (opmode == M68K_FPOP_FSSQRT_RAW) {
3031
90
      MCInst_setOpcode(info->inst, M68K_INS_FSSQRT);
3032
90
      goto fpu_operands;
3033
2.20k
    } else if (opmode == M68K_FPOP_FDSQRT_RAW) {
3034
392
      MCInst_setOpcode(info->inst, M68K_INS_FDSQRT);
3035
392
      goto fpu_operands;
3036
392
    }
3037
1.80k
    opmode &= ~4;
3038
1.80k
  }
3039
3040
8.60k
  switch (opmode) {
3041
3.90k
  case 0x00:
3042
3.90k
    MCInst_setOpcode(info->inst, M68K_INS_FMOVE);
3043
3.90k
    supports_single_op = false;
3044
3.90k
    break;
3045
7
  case 0x01:
3046
7
    MCInst_setOpcode(info->inst, M68K_INS_FINT);
3047
7
    break;
3048
8
  case 0x02:
3049
8
    MCInst_setOpcode(info->inst, M68K_INS_FSINH);
3050
8
    break;
3051
1
  case 0x03:
3052
1
    MCInst_setOpcode(info->inst, M68K_INS_FINTRZ);
3053
1
    break;
3054
84
  case 0x04:
3055
84
    MCInst_setOpcode(info->inst, M68K_INS_FSQRT);
3056
84
    break;
3057
14
  case 0x06:
3058
14
    MCInst_setOpcode(info->inst, M68K_INS_FLOGNP1);
3059
14
    break;
3060
448
  case 0x08:
3061
448
    MCInst_setOpcode(info->inst, M68K_INS_FETOXM1);
3062
448
    break;
3063
155
  case 0x09:
3064
155
    MCInst_setOpcode(info->inst, M68K_INS_FATANH);
3065
155
    break;
3066
346
  case 0x0a:
3067
346
    MCInst_setOpcode(info->inst, M68K_INS_FATAN);
3068
346
    break;
3069
0
  case 0x0c:
3070
0
    MCInst_setOpcode(info->inst, M68K_INS_FASIN);
3071
0
    break;
3072
2
  case 0x0d:
3073
2
    MCInst_setOpcode(info->inst, M68K_INS_FATANH);
3074
2
    break;
3075
0
  case 0x0e:
3076
0
    MCInst_setOpcode(info->inst, M68K_INS_FSIN);
3077
0
    break;
3078
32
  case 0x0f:
3079
32
    MCInst_setOpcode(info->inst, M68K_INS_FTAN);
3080
32
    break;
3081
224
  case 0x10:
3082
224
    MCInst_setOpcode(info->inst, M68K_INS_FETOX);
3083
224
    break;
3084
9
  case 0x11:
3085
9
    MCInst_setOpcode(info->inst, M68K_INS_FTWOTOX);
3086
9
    break;
3087
114
  case 0x12:
3088
114
    MCInst_setOpcode(info->inst, M68K_INS_FTENTOX);
3089
114
    break;
3090
284
  case 0x14:
3091
284
    MCInst_setOpcode(info->inst, M68K_INS_FLOGN);
3092
284
    break;
3093
8
  case 0x15:
3094
8
    MCInst_setOpcode(info->inst, M68K_INS_FLOG10);
3095
8
    break;
3096
2
  case 0x16:
3097
2
    MCInst_setOpcode(info->inst, M68K_INS_FLOG2);
3098
2
    break;
3099
5
  case 0x18:
3100
5
    MCInst_setOpcode(info->inst, M68K_INS_FABS);
3101
5
    break;
3102
5
  case 0x19:
3103
5
    MCInst_setOpcode(info->inst, M68K_INS_FCOSH);
3104
5
    break;
3105
94
  case 0x1a:
3106
94
    MCInst_setOpcode(info->inst, M68K_INS_FNEG);
3107
94
    break;
3108
100
  case 0x1c:
3109
100
    MCInst_setOpcode(info->inst, M68K_INS_FACOS);
3110
100
    break;
3111
2
  case 0x1d:
3112
2
    MCInst_setOpcode(info->inst, M68K_INS_FCOS);
3113
2
    break;
3114
0
  case 0x1e:
3115
0
    MCInst_setOpcode(info->inst, M68K_INS_FGETEXP);
3116
0
    break;
3117
33
  case 0x1f:
3118
33
    MCInst_setOpcode(info->inst, M68K_INS_FGETMAN);
3119
33
    break;
3120
105
  case 0x20:
3121
105
    MCInst_setOpcode(info->inst, M68K_INS_FDIV);
3122
105
    supports_single_op = false;
3123
105
    break;
3124
22
  case 0x21:
3125
22
    MCInst_setOpcode(info->inst, M68K_INS_FMOD);
3126
22
    supports_single_op = false;
3127
22
    break;
3128
465
  case 0x22:
3129
465
    MCInst_setOpcode(info->inst, M68K_INS_FADD);
3130
465
    supports_single_op = false;
3131
465
    break;
3132
21
  case 0x23:
3133
21
    MCInst_setOpcode(info->inst, M68K_INS_FMUL);
3134
21
    supports_single_op = false;
3135
21
    break;
3136
6
  case 0x24:
3137
6
    MCInst_setOpcode(info->inst, M68K_INS_FSGLDIV);
3138
6
    supports_single_op = false;
3139
6
    break;
3140
216
  case 0x25:
3141
216
    MCInst_setOpcode(info->inst, M68K_INS_FREM);
3142
216
    break;
3143
284
  case 0x26:
3144
284
    MCInst_setOpcode(info->inst, M68K_INS_FSCALE);
3145
284
    break;
3146
3
  case 0x27:
3147
3
    MCInst_setOpcode(info->inst, M68K_INS_FSGLMUL);
3148
3
    break;
3149
42
  case 0x28:
3150
42
    MCInst_setOpcode(info->inst, M68K_INS_FSUB);
3151
42
    supports_single_op = false;
3152
42
    break;
3153
15
  case 0x38:
3154
15
    MCInst_setOpcode(info->inst, M68K_INS_FCMP);
3155
15
    supports_single_op = false;
3156
15
    break;
3157
75
  case 0x3a:
3158
75
    MCInst_setOpcode(info->inst, M68K_INS_FTST);
3159
75
    break;
3160
1.46k
  default:
3161
1.46k
    break;
3162
8.60k
  }
3163
3164
8.60k
  if (M68K_FEXT_SD_FLAG(next)) {
3165
1.80k
    if ((next >> 2) & 1)
3166
1.23k
      info->inst->Opcode += 2;
3167
573
    else
3168
573
      info->inst->Opcode += 1;
3169
1.80k
  }
3170
3171
9.60k
fpu_operands:
3172
9.60k
  ext = &info->extension;
3173
9.60k
  is_fmove = MCInst_getOpcode(info->inst) == M68K_INS_FMOVE;
3174
3175
9.60k
  ext->op_count = 2;
3176
9.60k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
3177
9.60k
  ext->op_size.cpu_size = 0;
3178
3179
9.60k
  if ((opmode == 0x00 || packed_destination) &&
3180
4.43k
      M68K_FEXT_DIR(next) != 0) {
3181
881
    op0 = &ext->operands[1];
3182
881
    op1 = &ext->operands[0];
3183
8.72k
  } else {
3184
8.72k
    op0 = &ext->operands[0];
3185
8.72k
    op1 = &ext->operands[1];
3186
8.72k
  }
3187
3188
9.60k
  if (!ea_operand && supports_single_op && src == dst) {
3189
340
    ext->op_count = 1;
3190
340
    op0->reg = M68K_REG_FP0 + dst;
3191
340
    return;
3192
340
  }
3193
3194
9.26k
  if (packed_destination) {
3195
521
    cs_m68k_op *op_k = &ext->operands[2];
3196
521
    ext->op_size.type = M68K_SIZE_TYPE_FPU;
3197
521
    ext->op_size.fpu_size = M68K_FPU_SIZE_PACKED;
3198
521
    if (!get_ea_mode_op(info, op0, info->ir, 12)) {
3199
1
      invalid_insn(info);
3200
1
      return;
3201
1
    }
3202
3203
520
    ext->op_count = 3;
3204
520
    if (src == M68K_FPDST_PACKED_STATIC) {
3205
347
      int k_factor = next & 0x7f;
3206
347
      if (k_factor & 0x40)
3207
275
        k_factor -= 0x80;
3208
347
      op_k->address_mode = M68K_AM_IMMEDIATE;
3209
347
      op_k->type = M68K_OP_IMM;
3210
347
      op_k->imm = (uint64_t)(int64_t)k_factor;
3211
347
    } else {
3212
173
      op_k->address_mode = M68K_AM_NONE;
3213
173
      op_k->type = M68K_OP_REG;
3214
173
      op_k->reg = M68K_REG_D0 + ((next >> 4) & 7);
3215
173
    }
3216
520
    op1->reg = M68K_REG_FP0 + dst;
3217
520
    return;
3218
521
  }
3219
3220
8.74k
  if (ea_operand) {
3221
6.86k
    switch (src) {
3222
287
    case M68K_FPSRC_LONG:
3223
287
      ext->op_size.cpu_size = M68K_CPU_SIZE_LONG;
3224
287
      if (!get_ea_mode_op(info, op0, info->ir, 4)) {
3225
1
        invalid_insn(info);
3226
1
        return;
3227
1
      }
3228
286
      break;
3229
3230
286
    case M68K_FPSRC_BYTE:
3231
199
      ext->op_size.cpu_size = M68K_CPU_SIZE_BYTE;
3232
199
      if (!get_ea_mode_op(info, op0, info->ir, 1)) {
3233
1
        invalid_insn(info);
3234
1
        return;
3235
1
      }
3236
198
      break;
3237
3238
264
    case M68K_FPSRC_WORD:
3239
264
      ext->op_size.cpu_size = M68K_CPU_SIZE_WORD;
3240
264
      if (!get_ea_mode_op(info, op0, info->ir, 2)) {
3241
1
        invalid_insn(info);
3242
1
        return;
3243
1
      }
3244
263
      break;
3245
3246
879
    case M68K_FPSRC_SINGLE:
3247
879
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3248
879
      ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE;
3249
879
      if (!get_ea_mode_op(info, op0, info->ir, 4)) {
3250
1
        invalid_insn(info);
3251
1
        return;
3252
1
      }
3253
878
      if (op0->address_mode == M68K_AM_IMMEDIATE) {
3254
372
        op0->simm = BitsToFloat(op0->imm);
3255
372
        op0->type = M68K_OP_FP_SINGLE;
3256
372
      }
3257
878
      break;
3258
3259
454
    case M68K_FPSRC_DOUBLE:
3260
454
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3261
454
      ext->op_size.fpu_size = M68K_FPU_SIZE_DOUBLE;
3262
454
      if (!get_ea_mode_op(info, op0, info->ir, 8)) {
3263
1
        invalid_insn(info);
3264
1
        return;
3265
1
      }
3266
453
      if (op0->address_mode == M68K_AM_IMMEDIATE)
3267
76
        op0->type = M68K_OP_FP_DOUBLE;
3268
453
      break;
3269
3270
2.91k
    case M68K_FPSRC_EXTENDED:
3271
2.91k
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3272
2.91k
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3273
2.91k
      if (is_fmove && m68k_ea_is_immediate(info->ir)) {
3274
2.11k
        if (!read_imm_extended(info,
3275
2.11k
                   &op0->fp_extended)) {
3276
10
          invalid_insn(info);
3277
10
          return;
3278
10
        }
3279
2.10k
        op0->address_mode = M68K_AM_IMMEDIATE;
3280
2.10k
        op0->type = M68K_OP_FP_EXTENDED;
3281
2.10k
      } else if (!get_ea_mode_op(info, op0, info->ir, 12)) {
3282
1
        invalid_insn(info);
3283
1
        return;
3284
1
      }
3285
2.90k
      break;
3286
3287
2.90k
    case M68K_FPSRC_PACKED:
3288
1.56k
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3289
1.56k
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3290
1.56k
      if (is_fmove)
3291
1.25k
        ext->op_size.fpu_size = M68K_FPU_SIZE_PACKED;
3292
1.56k
      if (is_fmove && m68k_ea_is_immediate(info->ir)) {
3293
1.04k
        if (!read_imm_packed(info, &op0->fp_packed)) {
3294
8
          invalid_insn(info);
3295
8
          return;
3296
8
        }
3297
1.03k
        op0->address_mode = M68K_AM_IMMEDIATE;
3298
1.03k
        op0->type = M68K_OP_FP_PACKED;
3299
1.03k
      } else if (!get_ea_mode_op(info, op0, info->ir, 12)) {
3300
1
        invalid_insn(info);
3301
1
        return;
3302
1
      }
3303
1.55k
      break;
3304
3305
1.55k
    default:
3306
293
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3307
293
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3308
293
      break;
3309
6.86k
    }
3310
6.86k
  } else {
3311
1.88k
    op0->reg = M68K_REG_FP0 + src;
3312
1.88k
  }
3313
3314
8.71k
  op1->reg = M68K_REG_FP0 + dst;
3315
8.71k
}
3316
3317
static void d68020_cprestore(m68k_info *info)
3318
1.21k
{
3319
1.21k
  cs_m68k *ext;
3320
1.21k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3321
647
  REQUIRE_CPID_FPU(info);
3322
3323
261
  ext = build_init_op(info, M68K_INS_FRESTORE, 1, 0);
3324
261
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
3325
0
    invalid_insn(info);
3326
0
    return;
3327
0
  }
3328
261
}
3329
3330
static void d68020_cpsave(m68k_info *info)
3331
1.91k
{
3332
1.91k
  cs_m68k *ext;
3333
1.91k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3334
909
  REQUIRE_CPID_FPU(info);
3335
3336
378
  ext = build_init_op(info, M68K_INS_FSAVE, 1, 0);
3337
378
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
3338
0
    invalid_insn(info);
3339
0
    return;
3340
0
  }
3341
378
}
3342
3343
static void d68040_pflush_or_cpsave(m68k_info *info)
3344
579
{
3345
579
  if (m68k_has_feature(info, M68040_PLUS)) {
3346
333
    d68040_pflush(info);
3347
333
    return;
3348
333
  }
3349
246
  d68020_cpsave(info);
3350
246
}
3351
3352
static void d68040_ptest_or_cprestore(m68k_info *info)
3353
574
{
3354
574
  if (m68k_has_feature(info, CS_MODE_M68K_040)) {
3355
238
    d68040_ptest(info);
3356
238
    return;
3357
238
  }
3358
336
  if (m68k_has_feature(info, CS_MODE_M68K_060)) {
3359
0
    d68000_invalid(info);
3360
0
    return;
3361
0
  }
3362
336
  d68020_cprestore(info);
3363
336
}
3364
3365
static void d68020_cpscc(m68k_info *info)
3366
1.16k
{
3367
1.16k
  cs_m68k *ext;
3368
1.16k
  uint32_t condition;
3369
1.16k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3370
902
  REQUIRE_CPID_FPU(info);
3371
403
  condition = read_imm_16(info);
3372
403
  ext = build_init_fpu_condition_op(info, M68K_INS_FSF, condition, 1, 1);
3373
3374
403
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
3375
0
    invalid_insn(info);
3376
0
    return;
3377
0
  }
3378
403
}
3379
3380
static void d68020_cptrapcc_0(m68k_info *info)
3381
624
{
3382
624
  uint32_t extension1;
3383
624
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3384
420
  REQUIRE_CPID_FPU(info);
3385
3386
201
  extension1 = read_imm_16(info);
3387
3388
201
  build_init_fpu_condition_op(info, M68K_INS_FTRAPF, extension1, 0, 0);
3389
201
}
3390
3391
static void d68020_cptrapcc_16(m68k_info *info)
3392
752
{
3393
752
  uint32_t extension1, extension2;
3394
752
  cs_m68k_op *op0;
3395
752
  cs_m68k *ext;
3396
752
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3397
535
  REQUIRE_CPID_FPU(info);
3398
3399
70
  extension1 = read_imm_16(info);
3400
70
  extension2 = read_imm_16(info);
3401
3402
70
  ext = build_init_fpu_condition_op(info, M68K_INS_FTRAPF, extension1, 1,
3403
70
            2);
3404
3405
70
  op0 = &ext->operands[0];
3406
3407
70
  op0->address_mode = M68K_AM_IMMEDIATE;
3408
70
  op0->type = M68K_OP_IMM;
3409
70
  op0->imm = extension2;
3410
70
}
3411
3412
static void d68020_cptrapcc_32(m68k_info *info)
3413
697
{
3414
697
  uint32_t extension1, extension2;
3415
697
  cs_m68k *ext;
3416
697
  cs_m68k_op *op0;
3417
697
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3418
490
  REQUIRE_CPID_FPU(info);
3419
3420
253
  extension1 = read_imm_16(info);
3421
253
  extension2 = read_imm_32(info);
3422
3423
253
  ext = build_init_fpu_condition_op(info, M68K_INS_FTRAPF, extension1, 1,
3424
253
            4);
3425
3426
253
  op0 = &ext->operands[0];
3427
3428
253
  op0->address_mode = M68K_AM_IMMEDIATE;
3429
253
  op0->type = M68K_OP_IMM;
3430
253
  op0->imm = extension2;
3431
253
}
3432
3433
static void d68040_cpush(m68k_info *info)
3434
1.55k
{
3435
1.55k
  LIMIT_FEATURE(info, M68040_PLUS | CS_MODE_M68K_CF_ISA_A);
3436
1.24k
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3437
0
      M68K_IR_CACHE_SCOPE(info) != 1) {
3438
0
    d68000_invalid(info);
3439
0
    return;
3440
0
  }
3441
1.24k
  build_cpush_cinv(info, M68K_INS_CPUSHL);
3442
1.24k
}
3443
3444
static void d68000_dbra(m68k_info *info)
3445
294
{
3446
294
  build_dbxx(info, M68K_INS_DBRA, 0, make_int_16(read_imm_16(info)));
3447
294
}
3448
3449
static void d68000_dbcc(m68k_info *info)
3450
429
{
3451
429
  build_dbcc(info, 0, make_int_16(read_imm_16(info)));
3452
429
}
3453
3454
static void d68000_divs(m68k_info *info)
3455
946
{
3456
946
  build_er_1(info, M68K_INS_DIVS, 2);
3457
946
}
3458
3459
static void d68000_divu(m68k_info *info)
3460
937
{
3461
937
  build_er_1(info, M68K_INS_DIVU, 2);
3462
937
}
3463
3464
static void d68020_divl(m68k_info *info)
3465
587
{
3466
587
  uint32_t extension, insn_signed;
3467
587
  bool cf_remainder;
3468
587
  cs_m68k *ext;
3469
587
  cs_m68k_op *op0;
3470
587
  cs_m68k_op *op1;
3471
587
  uint32_t reg_0, reg_1;
3472
587
  m68k_insn opcode;
3473
3474
587
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_DIV);
3475
3476
390
  extension = read_imm_16(info);
3477
390
  insn_signed = 0;
3478
3479
390
  if (BIT_B((extension)))
3480
110
    insn_signed = 1;
3481
3482
390
  reg_0 = extension & 7;
3483
390
  reg_1 = (extension >> 12) & 7;
3484
390
  cf_remainder = m68k_has_feature(info, CS_MODE_M68K_CF_DIV) &&
3485
0
           !BIT_A(extension) && (reg_0 != reg_1);
3486
3487
390
  if (cf_remainder)
3488
0
    opcode = insn_signed ? M68K_INS_REMS : M68K_INS_REMU;
3489
390
  else
3490
390
    opcode = insn_signed ? M68K_INS_DIVS : M68K_INS_DIVU;
3491
3492
390
  ext = build_init_op(info, opcode, 2, 4);
3493
390
  op0 = &ext->operands[0];
3494
390
  op1 = &ext->operands[1];
3495
3496
390
  if (!get_ea_mode_op(info, op0, info->ir, 4)) {
3497
0
    invalid_insn(info);
3498
0
    return;
3499
0
  }
3500
3501
390
  op1->address_mode = M68K_AM_NONE;
3502
390
  op1->type = M68K_OP_REG_PAIR;
3503
390
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
3504
390
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
3505
3506
390
  if ((reg_0 == reg_1) || (!BIT_A(extension) && !cf_remainder)) {
3507
270
    op1->type = M68K_OP_REG;
3508
270
    op1->reg = M68K_REG_D0 + reg_1;
3509
270
  }
3510
390
}
3511
3512
static void d68000_eor_8(m68k_info *info)
3513
674
{
3514
674
  build_re_1(info, M68K_INS_EOR, 1);
3515
674
}
3516
3517
static void d68000_eor_16(m68k_info *info)
3518
490
{
3519
490
  build_re_1(info, M68K_INS_EOR, 2);
3520
490
}
3521
3522
static void d68000_eor_32(m68k_info *info)
3523
1.02k
{
3524
1.02k
  build_re_1(info, M68K_INS_EOR, 4);
3525
1.02k
}
3526
3527
static void d68000_eori_8(m68k_info *info)
3528
834
{
3529
834
  build_imm_ea(info, M68K_INS_EORI, 1, read_imm_8(info));
3530
834
}
3531
3532
static void d68000_eori_16(m68k_info *info)
3533
340
{
3534
340
  build_imm_ea(info, M68K_INS_EORI, 2, read_imm_16(info));
3535
340
}
3536
3537
static void d68000_eori_32(m68k_info *info)
3538
270
{
3539
270
  build_imm_ea(info, M68K_INS_EORI, 4, read_imm_32(info));
3540
270
}
3541
3542
static void d68000_eori_to_ccr(m68k_info *info)
3543
207
{
3544
207
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_8(info), 1,
3545
207
            M68K_REG_CCR);
3546
207
}
3547
3548
static void d68000_eori_to_sr(m68k_info *info)
3549
216
{
3550
216
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_16(info), 2,
3551
216
            M68K_REG_SR);
3552
216
}
3553
3554
static void d68000_exg_dd(m68k_info *info)
3555
933
{
3556
933
  build_r(info, M68K_INS_EXG, 4);
3557
933
}
3558
3559
static void d68000_exg_aa(m68k_info *info)
3560
203
{
3561
203
  cs_m68k_op *op0;
3562
203
  cs_m68k_op *op1;
3563
203
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3564
3565
203
  op0 = &ext->operands[0];
3566
203
  op1 = &ext->operands[1];
3567
3568
203
  op0->address_mode = M68K_AM_NONE;
3569
203
  op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
3570
3571
203
  op1->address_mode = M68K_AM_NONE;
3572
203
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3573
203
}
3574
3575
static void d68000_exg_da(m68k_info *info)
3576
399
{
3577
399
  cs_m68k_op *op0;
3578
399
  cs_m68k_op *op1;
3579
399
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3580
3581
399
  op0 = &ext->operands[0];
3582
399
  op1 = &ext->operands[1];
3583
3584
399
  op0->address_mode = M68K_AM_NONE;
3585
399
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3586
3587
399
  op1->address_mode = M68K_AM_NONE;
3588
399
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3589
399
}
3590
3591
static void d68000_ext_16(m68k_info *info)
3592
99
{
3593
99
  build_d(info, M68K_INS_EXT, 2);
3594
99
}
3595
3596
static void d68000_ext_32(m68k_info *info)
3597
335
{
3598
335
  build_d(info, M68K_INS_EXT, 4);
3599
335
}
3600
3601
static void d68020_extb_32(m68k_info *info)
3602
396
{
3603
396
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
3604
201
  build_d(info, M68K_INS_EXTB, 4);
3605
201
}
3606
3607
static void d68000_jmp(m68k_info *info)
3608
296
{
3609
296
  cs_m68k *ext = build_init_op(info, M68K_INS_JMP, 1, 0);
3610
296
  set_insn_group(info, M68K_GRP_JUMP);
3611
296
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) {
3612
0
    invalid_insn(info);
3613
0
    return;
3614
0
  }
3615
296
}
3616
3617
static void d68000_jsr(m68k_info *info)
3618
614
{
3619
614
  cs_m68k *ext = build_init_op(info, M68K_INS_JSR, 1, 0);
3620
614
  set_insn_group(info, M68K_GRP_JUMP);
3621
614
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) {
3622
0
    invalid_insn(info);
3623
0
    return;
3624
0
  }
3625
614
}
3626
3627
static void d68000_lea(m68k_info *info)
3628
626
{
3629
626
  build_ea_a(info, M68K_INS_LEA, 4);
3630
626
}
3631
3632
static void d68000_link_16(m68k_info *info)
3633
218
{
3634
218
  build_link(info, read_imm_16(info), 2);
3635
218
}
3636
3637
static void d68020_link_32(m68k_info *info)
3638
512
{
3639
512
  LIMIT_FEATURE(info, M68020_PLUS);
3640
313
  build_link(info, read_imm_32(info), 4);
3641
313
}
3642
3643
static void d68000_lsr_s_8(m68k_info *info)
3644
263
{
3645
263
  build_3bit_d(info, M68K_INS_LSR, 1);
3646
263
}
3647
3648
static void d68000_lsr_s_16(m68k_info *info)
3649
280
{
3650
280
  build_3bit_d(info, M68K_INS_LSR, 2);
3651
280
}
3652
3653
static void d68000_lsr_s_32(m68k_info *info)
3654
265
{
3655
265
  build_3bit_d(info, M68K_INS_LSR, 4);
3656
265
}
3657
3658
static void d68000_lsr_r_8(m68k_info *info)
3659
404
{
3660
404
  build_r(info, M68K_INS_LSR, 1);
3661
404
}
3662
3663
static void d68000_lsr_r_16(m68k_info *info)
3664
376
{
3665
376
  build_r(info, M68K_INS_LSR, 2);
3666
376
}
3667
3668
static void d68000_lsr_r_32(m68k_info *info)
3669
233
{
3670
233
  build_r(info, M68K_INS_LSR, 4);
3671
233
}
3672
3673
static void d68000_lsr_ea(m68k_info *info)
3674
653
{
3675
653
  build_ea(info, M68K_INS_LSR, 2);
3676
653
}
3677
3678
static void d68000_lsl_s_8(m68k_info *info)
3679
158
{
3680
158
  build_3bit_d(info, M68K_INS_LSL, 1);
3681
158
}
3682
3683
static void d68000_lsl_s_16(m68k_info *info)
3684
444
{
3685
444
  build_3bit_d(info, M68K_INS_LSL, 2);
3686
444
}
3687
3688
static void d68000_lsl_s_32(m68k_info *info)
3689
229
{
3690
229
  build_3bit_d(info, M68K_INS_LSL, 4);
3691
229
}
3692
3693
static void d68000_lsl_r_8(m68k_info *info)
3694
298
{
3695
298
  build_r(info, M68K_INS_LSL, 1);
3696
298
}
3697
3698
static void d68000_lsl_r_16(m68k_info *info)
3699
338
{
3700
338
  build_r(info, M68K_INS_LSL, 2);
3701
338
}
3702
3703
static void d68000_lsl_r_32(m68k_info *info)
3704
342
{
3705
342
  build_r(info, M68K_INS_LSL, 4);
3706
342
}
3707
3708
static void d68000_lsl_ea(m68k_info *info)
3709
284
{
3710
284
  build_ea(info, M68K_INS_LSL, 2);
3711
284
}
3712
3713
static void d68000_move_8(m68k_info *info)
3714
8.18k
{
3715
8.18k
  build_ea_ea(info, M68K_INS_MOVE, 1);
3716
8.18k
}
3717
3718
static void d68000_move_16(m68k_info *info)
3719
9.37k
{
3720
9.37k
  build_ea_ea(info, M68K_INS_MOVE, 2);
3721
9.37k
}
3722
3723
static void d68000_move_32(m68k_info *info)
3724
13.8k
{
3725
13.8k
  build_ea_ea(info, M68K_INS_MOVE, 4);
3726
13.8k
}
3727
3728
static void d68000_movea_16(m68k_info *info)
3729
2.02k
{
3730
2.02k
  build_ea_a(info, M68K_INS_MOVEA, 2);
3731
2.02k
}
3732
3733
static void d68000_movea_32(m68k_info *info)
3734
2.53k
{
3735
2.53k
  build_ea_a(info, M68K_INS_MOVEA, 4);
3736
2.53k
}
3737
3738
static void d68000_move_to_ccr(m68k_info *info)
3739
277
{
3740
277
  cs_m68k_op *op0;
3741
277
  cs_m68k_op *op1;
3742
277
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3743
3744
277
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3745
0
      (!m68k_has_feature(info, CS_MODE_M68K_CF_ISA_A) ||
3746
0
       !cf_sr_ccr_source_ea_is_valid(info->ir))) {
3747
0
    d68000_invalid(info);
3748
0
    return;
3749
0
  }
3750
3751
277
  op0 = &ext->operands[0];
3752
277
  op1 = &ext->operands[1];
3753
3754
277
  if (!get_ea_mode_op(info, op0, info->ir, 1)) {
3755
0
    invalid_insn(info);
3756
0
    return;
3757
0
  }
3758
3759
277
  op1->address_mode = M68K_AM_NONE;
3760
277
  op1->reg = M68K_REG_CCR;
3761
277
}
3762
3763
static void d68010_move_fr_ccr(m68k_info *info)
3764
502
{
3765
502
  cs_m68k_op *op0;
3766
502
  cs_m68k_op *op1;
3767
502
  cs_m68k *ext;
3768
3769
502
  LIMIT_FEATURE(info, M68010_PLUS | CS_MODE_M68K_CF_ISA_A);
3770
3771
253
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3772
0
      !cf_sr_ccr_destination_ea_is_valid(info->ir)) {
3773
0
    d68000_invalid(info);
3774
0
    return;
3775
0
  }
3776
3777
253
  ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3778
3779
253
  op0 = &ext->operands[0];
3780
253
  op1 = &ext->operands[1];
3781
3782
253
  op0->address_mode = M68K_AM_NONE;
3783
253
  op0->reg = M68K_REG_CCR;
3784
3785
253
  if (!get_ea_mode_op(info, op1, info->ir, 1)) {
3786
0
    invalid_insn(info);
3787
0
    return;
3788
0
  }
3789
253
}
3790
3791
static void d68000_move_fr_sr(m68k_info *info)
3792
485
{
3793
485
  cs_m68k_op *op0;
3794
485
  cs_m68k_op *op1;
3795
485
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3796
3797
485
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3798
0
      (!m68k_has_feature(info, CS_MODE_M68K_CF_ISA_A) ||
3799
0
       !cf_sr_ccr_destination_ea_is_valid(info->ir))) {
3800
0
    d68000_invalid(info);
3801
0
    return;
3802
0
  }
3803
3804
485
  op0 = &ext->operands[0];
3805
485
  op1 = &ext->operands[1];
3806
3807
485
  op0->address_mode = M68K_AM_NONE;
3808
485
  op0->reg = M68K_REG_SR;
3809
3810
485
  if (!get_ea_mode_op(info, op1, info->ir, 2)) {
3811
0
    invalid_insn(info);
3812
0
    return;
3813
0
  }
3814
485
}
3815
3816
static void d68000_move_to_sr(m68k_info *info)
3817
311
{
3818
311
  cs_m68k_op *op0;
3819
311
  cs_m68k_op *op1;
3820
311
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3821
3822
311
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3823
0
      (!m68k_has_feature(info, CS_MODE_M68K_CF_ISA_A) ||
3824
0
       !cf_sr_ccr_source_ea_is_valid(info->ir))) {
3825
0
    d68000_invalid(info);
3826
0
    return;
3827
0
  }
3828
3829
311
  op0 = &ext->operands[0];
3830
311
  op1 = &ext->operands[1];
3831
3832
311
  if (!get_ea_mode_op(info, op0, info->ir, 2)) {
3833
0
    invalid_insn(info);
3834
0
    return;
3835
0
  }
3836
3837
311
  op1->address_mode = M68K_AM_NONE;
3838
311
  op1->reg = M68K_REG_SR;
3839
311
}
3840
3841
static void d68000_move_fr_usp(m68k_info *info)
3842
441
{
3843
441
  cs_m68k_op *op0;
3844
441
  cs_m68k_op *op1;
3845
441
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
3846
3847
441
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3848
0
      !m68k_has_feature(info, CS_MODE_M68K_CF_USP)) {
3849
0
    d68000_invalid(info);
3850
0
    return;
3851
0
  }
3852
3853
441
  op0 = &ext->operands[0];
3854
441
  op1 = &ext->operands[1];
3855
3856
441
  op0->address_mode = M68K_AM_NONE;
3857
441
  op0->reg = M68K_REG_USP;
3858
3859
441
  op1->address_mode = M68K_AM_NONE;
3860
441
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3861
441
}
3862
3863
static void d68000_move_to_usp(m68k_info *info)
3864
283
{
3865
283
  cs_m68k_op *op0;
3866
283
  cs_m68k_op *op1;
3867
283
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
3868
3869
283
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE) &&
3870
0
      !m68k_has_feature(info, CS_MODE_M68K_CF_USP)) {
3871
0
    d68000_invalid(info);
3872
0
    return;
3873
0
  }
3874
3875
283
  op0 = &ext->operands[0];
3876
283
  op1 = &ext->operands[1];
3877
3878
283
  op0->address_mode = M68K_AM_NONE;
3879
283
  op0->reg = M68K_REG_A0 + (info->ir & 7);
3880
3881
283
  op1->address_mode = M68K_AM_NONE;
3882
283
  op1->reg = M68K_REG_USP;
3883
283
}
3884
3885
static void d68010_movec(m68k_info *info)
3886
4.30k
{
3887
4.30k
  uint32_t extension;
3888
4.30k
  m68k_reg reg;
3889
4.30k
  cs_m68k *ext;
3890
4.30k
  cs_m68k_op *op0;
3891
4.30k
  cs_m68k_op *op1;
3892
3893
4.30k
  LIMIT_FEATURE(info, M68010_PLUS | CS_MODE_M68K_CF_ISA_A);
3894
3895
4.04k
  extension = read_imm_16(info);
3896
4.04k
  reg = M68K_REG_INVALID;
3897
3898
4.04k
  ext = build_init_op(info, M68K_INS_MOVEC, 2, 0);
3899
3900
4.04k
  op0 = &ext->operands[0];
3901
4.04k
  op1 = &ext->operands[1];
3902
3903
4.04k
  switch (extension & 0xfff) {
3904
284
  case 0x000:
3905
284
    reg = M68K_REG_SFC;
3906
284
    break;
3907
66
  case 0x001:
3908
66
    reg = M68K_REG_DFC;
3909
66
    break;
3910
225
  case 0x800:
3911
225
    reg = M68K_REG_USP;
3912
225
    break;
3913
53
  case 0x801:
3914
53
    reg = M68K_REG_VBR;
3915
53
    break;
3916
428
  case 0x002:
3917
428
    reg = M68K_REG_CACR;
3918
428
    break;
3919
220
  case 0x802:
3920
220
    reg = M68K_REG_CAAR;
3921
220
    break;
3922
352
  case 0x803:
3923
352
    reg = M68K_REG_MSP;
3924
352
    break;
3925
63
  case 0x804:
3926
63
    reg = M68K_REG_ISP;
3927
63
    break;
3928
299
  case 0x003:
3929
299
    reg = M68K_REG_TC;
3930
299
    break;
3931
37
  case 0x004:
3932
37
    reg = M68K_REG_ITT0;
3933
37
    break;
3934
81
  case 0x005:
3935
81
    reg = M68K_REG_ITT1;
3936
81
    break;
3937
79
  case 0x006:
3938
79
    reg = M68K_REG_DTT0;
3939
79
    break;
3940
318
  case 0x007:
3941
318
    reg = M68K_REG_DTT1;
3942
318
    break;
3943
71
  case 0x805:
3944
71
    reg = M68K_REG_MMUSR;
3945
71
    break;
3946
294
  case 0x806:
3947
294
    reg = M68K_REG_URP;
3948
294
    break;
3949
70
  case 0x807:
3950
70
    reg = M68K_REG_SRP;
3951
70
    break;
3952
1.10k
  default:
3953
1.10k
    break;
3954
4.04k
  }
3955
3956
4.04k
  if (BIT_0(info->ir)) {
3957
1.06k
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
3958
1.06k
         ((extension >> 12) & 7);
3959
1.06k
    op1->reg = reg;
3960
2.98k
  } else {
3961
2.98k
    op0->reg = reg;
3962
2.98k
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
3963
2.98k
         ((extension >> 12) & 7);
3964
2.98k
  }
3965
4.04k
}
3966
3967
static void d68000_movem_pd_16(m68k_info *info)
3968
852
{
3969
852
  build_movem_re(info, M68K_INS_MOVEM, 2);
3970
852
}
3971
3972
static void d68000_movem_pd_32(m68k_info *info)
3973
305
{
3974
305
  build_movem_re(info, M68K_INS_MOVEM, 4);
3975
305
}
3976
3977
static void d68000_movem_er_16(m68k_info *info)
3978
538
{
3979
538
  build_movem_er(info, M68K_INS_MOVEM, 2);
3980
538
}
3981
3982
static void d68000_movem_er_32(m68k_info *info)
3983
754
{
3984
754
  build_movem_er(info, M68K_INS_MOVEM, 4);
3985
754
}
3986
3987
static void d68000_movem_re_16(m68k_info *info)
3988
345
{
3989
345
  build_movem_re(info, M68K_INS_MOVEM, 2);
3990
345
}
3991
3992
static void d68000_movem_re_32(m68k_info *info)
3993
487
{
3994
487
  build_movem_re(info, M68K_INS_MOVEM, 4);
3995
487
}
3996
3997
static void d68000_movep_re_16(m68k_info *info)
3998
367
{
3999
  /*
4000
   * MC68060 leaves MOVEP to the software package, but the encoding is still
4001
   * part of the ISA and should decode as MOVEP.
4002
   */
4003
367
  build_movep_re(info, 2);
4004
367
}
4005
4006
static void d68000_movep_re_32(m68k_info *info)
4007
129
{
4008
129
  build_movep_re(info, 4);
4009
129
}
4010
4011
static void d68000_movep_er_16(m68k_info *info)
4012
948
{
4013
948
  build_movep_er(info, 2);
4014
948
}
4015
4016
static void d68000_movep_er_32(m68k_info *info)
4017
462
{
4018
462
  build_movep_er(info, 4);
4019
462
}
4020
4021
static void d68010_moves_8(m68k_info *info)
4022
361
{
4023
361
  LIMIT_FEATURE(info, M68010_PLUS);
4024
89
  build_moves(info, 1);
4025
89
}
4026
4027
static void d68010_moves_16(m68k_info *info)
4028
274
{
4029
  //uint32_t extension;
4030
274
  LIMIT_FEATURE(info, M68010_PLUS);
4031
110
  build_moves(info, 2);
4032
110
}
4033
4034
static void d68010_moves_32(m68k_info *info)
4035
138
{
4036
138
  LIMIT_FEATURE(info, M68010_PLUS);
4037
71
  build_moves(info, 4);
4038
71
}
4039
4040
static void d68000_moveq(m68k_info *info)
4041
8.26k
{
4042
8.26k
  cs_m68k_op *op0;
4043
8.26k
  cs_m68k_op *op1;
4044
4045
8.26k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEQ, 2, 0);
4046
4047
8.26k
  op0 = &ext->operands[0];
4048
8.26k
  op1 = &ext->operands[1];
4049
4050
8.26k
  op0->type = M68K_OP_IMM;
4051
8.26k
  op0->address_mode = M68K_AM_IMMEDIATE;
4052
8.26k
  op0->imm = (info->ir & 0xff);
4053
4054
8.26k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
4055
8.26k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
4056
8.26k
}
4057
4058
static void d68040_move16_pi_pi(m68k_info *info)
4059
517
{
4060
517
  uint32_t data[] = { info->ir & 7, (read_imm_16(info) >> 12) & 7 };
4061
517
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
4062
517
           M68K_AM_REGI_ADDR_POST_INC };
4063
4064
517
  LIMIT_FEATURE(info, M68040_PLUS);
4065
4066
268
  build_move16(info, data, modes);
4067
268
}
4068
4069
static void d68040_move16_pi_al(m68k_info *info)
4070
835
{
4071
835
  uint32_t data[2];
4072
835
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
4073
835
           M68K_AM_ABSOLUTE_DATA_LONG };
4074
4075
835
  LIMIT_FEATURE(info, M68040_PLUS);
4076
4077
366
  data[0] = info->ir & 7;
4078
366
  data[1] = read_imm_32(info);
4079
366
  build_move16(info, data, modes);
4080
366
}
4081
4082
static void d68040_move16_al_pi(m68k_info *info)
4083
546
{
4084
546
  uint32_t data[2];
4085
546
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG,
4086
546
           M68K_AM_REGI_ADDR_POST_INC };
4087
4088
546
  LIMIT_FEATURE(info, M68040_PLUS);
4089
4090
273
  data[0] = read_imm_32(info);
4091
273
  data[1] = info->ir & 7;
4092
273
  build_move16(info, data, modes);
4093
273
}
4094
4095
static void d68040_move16_ai_al(m68k_info *info)
4096
575
{
4097
575
  uint32_t data[2];
4098
575
  uint32_t modes[] = { M68K_AM_REGI_ADDR, M68K_AM_ABSOLUTE_DATA_LONG };
4099
4100
575
  LIMIT_FEATURE(info, M68040_PLUS);
4101
4102
309
  data[0] = info->ir & 7;
4103
309
  data[1] = read_imm_32(info);
4104
309
  build_move16(info, data, modes);
4105
309
}
4106
4107
static void d68040_move16_al_ai(m68k_info *info)
4108
293
{
4109
293
  uint32_t data[2];
4110
293
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REGI_ADDR };
4111
4112
293
  LIMIT_FEATURE(info, M68040_PLUS);
4113
4114
207
  data[0] = read_imm_32(info);
4115
207
  data[1] = info->ir & 7;
4116
207
  build_move16(info, data, modes);
4117
207
}
4118
4119
static void d68000_muls(m68k_info *info)
4120
1.31k
{
4121
1.31k
  build_er_1(info, M68K_INS_MULS, 2);
4122
1.31k
}
4123
4124
static void d68000_mulu(m68k_info *info)
4125
959
{
4126
959
  build_er_1(info, M68K_INS_MULU, 2);
4127
959
}
4128
4129
static void d68020_mull(m68k_info *info)
4130
648
{
4131
648
  uint32_t extension, insn_signed;
4132
648
  cs_m68k *ext;
4133
648
  cs_m68k_op *op0;
4134
648
  cs_m68k_op *op1;
4135
648
  uint32_t reg_0, reg_1;
4136
4137
648
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A |
4138
648
            CS_MODE_M68K_CF_ISA_B |
4139
648
            CS_MODE_M68K_CF_ISA_C);
4140
4141
452
  extension = read_imm_16(info);
4142
452
  insn_signed = 0;
4143
4144
452
  if (BIT_B((extension)))
4145
63
    insn_signed = 1;
4146
4147
452
  ext = build_init_op(info, insn_signed ? M68K_INS_MULS : M68K_INS_MULU,
4148
452
          2, 4);
4149
4150
452
  op0 = &ext->operands[0];
4151
452
  op1 = &ext->operands[1];
4152
4153
452
  if (!get_ea_mode_op(info, op0, info->ir, 4)) {
4154
0
    invalid_insn(info);
4155
0
    return;
4156
0
  }
4157
4158
452
  reg_0 = extension & 7;
4159
452
  reg_1 = (extension >> 12) & 7;
4160
4161
452
  op1->address_mode = M68K_AM_NONE;
4162
452
  op1->type = M68K_OP_REG_PAIR;
4163
452
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
4164
452
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
4165
4166
452
  if (!BIT_A(extension)) {
4167
219
    op1->type = M68K_OP_REG;
4168
219
    op1->reg = M68K_REG_D0 + reg_1;
4169
219
  }
4170
452
}
4171
4172
static void d68000_nbcd(m68k_info *info)
4173
419
{
4174
419
  build_ea(info, M68K_INS_NBCD, 1);
4175
419
}
4176
4177
static void d68000_neg_8(m68k_info *info)
4178
252
{
4179
252
  build_ea(info, M68K_INS_NEG, 1);
4180
252
}
4181
4182
static void d68000_neg_16(m68k_info *info)
4183
453
{
4184
453
  build_ea(info, M68K_INS_NEG, 2);
4185
453
}
4186
4187
static void d68000_neg_32(m68k_info *info)
4188
540
{
4189
540
  build_ea(info, M68K_INS_NEG, 4);
4190
540
}
4191
4192
static void d68000_negx_8(m68k_info *info)
4193
653
{
4194
653
  build_ea(info, M68K_INS_NEGX, 1);
4195
653
}
4196
4197
static void d68000_negx_16(m68k_info *info)
4198
259
{
4199
259
  build_ea(info, M68K_INS_NEGX, 2);
4200
259
}
4201
4202
static void d68000_negx_32(m68k_info *info)
4203
613
{
4204
613
  build_ea(info, M68K_INS_NEGX, 4);
4205
613
}
4206
4207
static void d68000_nop(m68k_info *info)
4208
260
{
4209
260
  MCInst_setOpcode(info->inst, M68K_INS_NOP);
4210
260
}
4211
4212
static void d68000_not_8(m68k_info *info)
4213
297
{
4214
297
  build_ea(info, M68K_INS_NOT, 1);
4215
297
}
4216
4217
static void d68000_not_16(m68k_info *info)
4218
380
{
4219
380
  build_ea(info, M68K_INS_NOT, 2);
4220
380
}
4221
4222
static void d68000_not_32(m68k_info *info)
4223
370
{
4224
370
  build_ea(info, M68K_INS_NOT, 4);
4225
370
}
4226
4227
static void d68000_or_er_8(m68k_info *info)
4228
1.50k
{
4229
1.50k
  build_er_1(info, M68K_INS_OR, 1);
4230
1.50k
}
4231
4232
static void d68000_or_er_16(m68k_info *info)
4233
387
{
4234
387
  build_er_1(info, M68K_INS_OR, 2);
4235
387
}
4236
4237
static void d68000_or_er_32(m68k_info *info)
4238
1.11k
{
4239
1.11k
  build_er_1(info, M68K_INS_OR, 4);
4240
1.11k
}
4241
4242
static void d68000_or_re_8(m68k_info *info)
4243
631
{
4244
631
  build_re_1(info, M68K_INS_OR, 1);
4245
631
}
4246
4247
static void d68000_or_re_16(m68k_info *info)
4248
926
{
4249
926
  build_re_1(info, M68K_INS_OR, 2);
4250
926
}
4251
4252
static void d68000_or_re_32(m68k_info *info)
4253
795
{
4254
795
  build_re_1(info, M68K_INS_OR, 4);
4255
795
}
4256
4257
static void d68000_ori_8(m68k_info *info)
4258
14.8k
{
4259
14.8k
  build_imm_ea(info, M68K_INS_ORI, 1, read_imm_8(info));
4260
14.8k
}
4261
4262
static void d68000_ori_16(m68k_info *info)
4263
1.96k
{
4264
1.96k
  build_imm_ea(info, M68K_INS_ORI, 2, read_imm_16(info));
4265
1.96k
}
4266
4267
static void d68000_ori_32(m68k_info *info)
4268
1.36k
{
4269
1.36k
  build_imm_ea(info, M68K_INS_ORI, 4, read_imm_32(info));
4270
1.36k
}
4271
4272
static void d68000_ori_to_ccr(m68k_info *info)
4273
145
{
4274
145
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_8(info), 1,
4275
145
            M68K_REG_CCR);
4276
145
}
4277
4278
static void d68000_ori_to_sr(m68k_info *info)
4279
274
{
4280
274
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_16(info), 2,
4281
274
            M68K_REG_SR);
4282
274
}
4283
4284
static void d68020_pack_rr(m68k_info *info)
4285
884
{
4286
884
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
4287
716
  build_rr(info, M68K_INS_PACK, 0, read_imm_16(info));
4288
716
}
4289
4290
static void d68020_pack_mm(m68k_info *info)
4291
826
{
4292
826
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
4293
525
  build_mm(info, M68K_INS_PACK, 0, read_imm_16(info));
4294
525
}
4295
4296
static void d68000_pea(m68k_info *info)
4297
343
{
4298
343
  build_ea(info, M68K_INS_PEA, 4);
4299
343
}
4300
4301
static void d68000_reset(m68k_info *info)
4302
444
{
4303
444
  MCInst_setOpcode(info->inst, M68K_INS_RESET);
4304
444
}
4305
4306
static void d68000_ror_s_8(m68k_info *info)
4307
398
{
4308
398
  build_3bit_d(info, M68K_INS_ROR, 1);
4309
398
}
4310
4311
static void d68000_ror_s_16(m68k_info *info)
4312
357
{
4313
357
  build_3bit_d(info, M68K_INS_ROR, 2);
4314
357
}
4315
4316
static void d68000_ror_s_32(m68k_info *info)
4317
343
{
4318
343
  build_3bit_d(info, M68K_INS_ROR, 4);
4319
343
}
4320
4321
static void d68000_ror_r_8(m68k_info *info)
4322
245
{
4323
245
  build_r(info, M68K_INS_ROR, 1);
4324
245
}
4325
4326
static void d68000_ror_r_16(m68k_info *info)
4327
84
{
4328
84
  build_r(info, M68K_INS_ROR, 2);
4329
84
}
4330
4331
static void d68000_ror_r_32(m68k_info *info)
4332
375
{
4333
375
  build_r(info, M68K_INS_ROR, 4);
4334
375
}
4335
4336
static void d68000_ror_ea(m68k_info *info)
4337
496
{
4338
496
  build_ea(info, M68K_INS_ROR, 2);
4339
496
}
4340
4341
static void d68000_rol_s_8(m68k_info *info)
4342
219
{
4343
219
  build_3bit_d(info, M68K_INS_ROL, 1);
4344
219
}
4345
4346
static void d68000_rol_s_16(m68k_info *info)
4347
313
{
4348
313
  build_3bit_d(info, M68K_INS_ROL, 2);
4349
313
}
4350
4351
static void d68000_rol_s_32(m68k_info *info)
4352
146
{
4353
146
  build_3bit_d(info, M68K_INS_ROL, 4);
4354
146
}
4355
4356
static void d68000_rol_r_8(m68k_info *info)
4357
251
{
4358
251
  build_r(info, M68K_INS_ROL, 1);
4359
251
}
4360
4361
static void d68000_rol_r_16(m68k_info *info)
4362
358
{
4363
358
  build_r(info, M68K_INS_ROL, 2);
4364
358
}
4365
4366
static void d68000_rol_r_32(m68k_info *info)
4367
221
{
4368
221
  build_r(info, M68K_INS_ROL, 4);
4369
221
}
4370
4371
static void d68000_rol_ea(m68k_info *info)
4372
1.16k
{
4373
1.16k
  build_ea(info, M68K_INS_ROL, 2);
4374
1.16k
}
4375
4376
static void d68000_roxr_s_8(m68k_info *info)
4377
210
{
4378
210
  build_3bit_d(info, M68K_INS_ROXR, 1);
4379
210
}
4380
4381
static void d68000_roxr_s_16(m68k_info *info)
4382
222
{
4383
222
  build_3bit_d(info, M68K_INS_ROXR, 2);
4384
222
}
4385
4386
static void d68000_roxr_s_32(m68k_info *info)
4387
147
{
4388
147
  build_3bit_d(info, M68K_INS_ROXR, 4);
4389
147
}
4390
4391
static void d68000_roxr_r_8(m68k_info *info)
4392
95
{
4393
95
  build_r(info, M68K_INS_ROXR, 1);
4394
95
}
4395
4396
static void d68000_roxr_r_16(m68k_info *info)
4397
213
{
4398
213
  build_r(info, M68K_INS_ROXR, 2);
4399
213
}
4400
4401
static void d68000_roxr_r_32(m68k_info *info)
4402
214
{
4403
214
  build_r(info, M68K_INS_ROXR, 4);
4404
214
}
4405
4406
static void d68000_roxr_ea(m68k_info *info)
4407
819
{
4408
819
  build_ea(info, M68K_INS_ROXR, 2);
4409
819
}
4410
4411
static void d68000_roxl_s_8(m68k_info *info)
4412
346
{
4413
346
  build_3bit_d(info, M68K_INS_ROXL, 1);
4414
346
}
4415
4416
static void d68000_roxl_s_16(m68k_info *info)
4417
137
{
4418
137
  build_3bit_d(info, M68K_INS_ROXL, 2);
4419
137
}
4420
4421
static void d68000_roxl_s_32(m68k_info *info)
4422
394
{
4423
394
  build_3bit_d(info, M68K_INS_ROXL, 4);
4424
394
}
4425
4426
static void d68000_roxl_r_8(m68k_info *info)
4427
210
{
4428
210
  build_r(info, M68K_INS_ROXL, 1);
4429
210
}
4430
4431
static void d68000_roxl_r_16(m68k_info *info)
4432
461
{
4433
461
  build_r(info, M68K_INS_ROXL, 2);
4434
461
}
4435
4436
static void d68000_roxl_r_32(m68k_info *info)
4437
236
{
4438
236
  build_r(info, M68K_INS_ROXL, 4);
4439
236
}
4440
4441
static void d68000_roxl_ea(m68k_info *info)
4442
481
{
4443
481
  build_ea(info, M68K_INS_ROXL, 2);
4444
481
}
4445
4446
static void d68010_rtd(m68k_info *info)
4447
594
{
4448
594
  set_insn_group(info, M68K_GRP_RET);
4449
594
  LIMIT_FEATURE(info, M68010_PLUS);
4450
297
  build_absolute_jump_with_immediate(info, M68K_INS_RTD, 0,
4451
297
             read_imm_16(info));
4452
297
}
4453
4454
static void d68000_rte(m68k_info *info)
4455
212
{
4456
212
  set_insn_group(info, M68K_GRP_IRET);
4457
212
  MCInst_setOpcode(info->inst, M68K_INS_RTE);
4458
212
}
4459
4460
static void d68020_rtm(m68k_info *info)
4461
283
{
4462
283
  cs_m68k *ext;
4463
283
  cs_m68k_op *op;
4464
4465
283
  set_insn_group(info, M68K_GRP_RET);
4466
4467
283
  LIMIT_FEATURE(info, M68020_ONLY);
4468
4469
0
  build_absolute_jump_with_immediate(info, M68K_INS_RTM, 0, 0);
4470
4471
0
  ext = &info->extension;
4472
0
  op = &ext->operands[0];
4473
4474
0
  op->address_mode = M68K_AM_NONE;
4475
0
  op->type = M68K_OP_REG;
4476
4477
0
  if (BIT_3(info->ir)) {
4478
0
    op->reg = M68K_REG_A0 + (info->ir & 7);
4479
0
  } else {
4480
0
    op->reg = M68K_REG_D0 + (info->ir & 7);
4481
0
  }
4482
0
}
4483
4484
static void d68000_rtr(m68k_info *info)
4485
217
{
4486
217
  set_insn_group(info, M68K_GRP_RET);
4487
217
  MCInst_setOpcode(info->inst, M68K_INS_RTR);
4488
217
}
4489
4490
static void d68000_rts(m68k_info *info)
4491
229
{
4492
229
  set_insn_group(info, M68K_GRP_RET);
4493
229
  MCInst_setOpcode(info->inst, M68K_INS_RTS);
4494
229
}
4495
4496
static void d68000_sbcd_rr(m68k_info *info)
4497
661
{
4498
661
  build_rr(info, M68K_INS_SBCD, 1, 0);
4499
661
}
4500
4501
static void d68000_sbcd_mm(m68k_info *info)
4502
544
{
4503
544
  build_mm(info, M68K_INS_SBCD, 1, 0);
4504
544
}
4505
4506
static void d68000_scc(m68k_info *info)
4507
636
{
4508
636
  cs_m68k *ext = build_init_op(
4509
636
    info, s_scc_lut[M68K_IR_CONDITION_NIBBLE(info)], 1, 1);
4510
636
  if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) {
4511
0
    invalid_insn(info);
4512
0
    return;
4513
0
  }
4514
636
}
4515
4516
static void d68000_stop(m68k_info *info)
4517
214
{
4518
214
  build_absolute_jump_with_immediate(info, M68K_INS_STOP, 0,
4519
214
             read_imm_16(info));
4520
214
}
4521
4522
static void d68040_pflush(m68k_info *info)
4523
1.32k
{
4524
  /* 68040/060 PFLUSH variants in the 0xF500-0xF51F range:
4525
   *   F500-F507: PFLUSHN (An)  — flush non-global ATC entries for (An)
4526
   *   F508-F50F: PFLUSH (An)   — flush all ATC entries for (An)
4527
   *   F510-F517: PFLUSHAN      — flush all non-global ATC entries
4528
   *   F518-F51F: PFLUSHA       — flush all ATC entries
4529
   */
4530
1.32k
  int mode;
4531
1.32k
  cs_m68k *ext;
4532
1.32k
  cs_m68k_op *op;
4533
4534
1.32k
  LIMIT_FEATURE(info, M68040_PLUS);
4535
4536
1.07k
  mode = (info->ir >> 3) & 3;
4537
4538
1.07k
  switch (mode) {
4539
128
  case 0: /* PFLUSHN (An) */
4540
128
    ext = build_init_op(info, M68K_INS_PFLUSHN, 1, 0);
4541
128
    op = &ext->operands[0];
4542
128
    op->address_mode = M68K_AM_REGI_ADDR;
4543
128
    op->type = M68K_OP_MEM;
4544
128
    op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4545
128
    break;
4546
353
  case 1: /* PFLUSH (An) */
4547
353
    ext = build_init_op(info, M68K_INS_PFLUSH, 1, 0);
4548
353
    op = &ext->operands[0];
4549
353
    op->address_mode = M68K_AM_REGI_ADDR;
4550
353
    op->type = M68K_OP_MEM;
4551
353
    op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4552
353
    break;
4553
333
  case 2: /* PFLUSHAN */
4554
333
    build_init_op(info, M68K_INS_PFLUSHAN, 0, 0);
4555
333
    break;
4556
264
  case 3: /* PFLUSHA */
4557
264
    build_init_op(info, M68K_INS_PFLUSHA, 0, 0);
4558
264
    break;
4559
0
  default:
4560
0
    break;
4561
1.07k
  }
4562
1.07k
}
4563
4564
static void d68040_ptest(m68k_info *info)
4565
625
{
4566
  /* 68040-only PTEST instructions:
4567
   *   F548-F54F: PTESTW (An)
4568
   *   F568-F56F: PTESTR (An)
4569
   */
4570
625
  int is_read;
4571
625
  cs_m68k *ext;
4572
625
  cs_m68k_op *op;
4573
625
  int insn;
4574
4575
625
  LIMIT_FEATURE(info, CS_MODE_M68K_040);
4576
4577
511
  is_read = (info->ir >> 5) & 1;
4578
511
  insn = is_read ? M68K_INS_PTESTR : M68K_INS_PTESTW;
4579
4580
511
  ext = build_init_op(info, insn, 1, 0);
4581
511
  op = &ext->operands[0];
4582
511
  op->address_mode = M68K_AM_REGI_ADDR;
4583
511
  op->type = M68K_OP_MEM;
4584
511
  op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4585
511
}
4586
4587
static void d68060_plpa(m68k_info *info)
4588
723
{
4589
  /* 68060-only PLPA instructions:
4590
   *   F588-F58F: PLPAW (An)
4591
   *   F5C8-F5CF: PLPAR (An)
4592
   */
4593
723
  int is_read;
4594
723
  cs_m68k *ext;
4595
723
  cs_m68k_op *op;
4596
723
  int insn;
4597
4598
723
  LIMIT_FEATURE(info, CS_MODE_M68K_060);
4599
4600
0
  is_read = (info->ir >> 6) & 1;
4601
0
  insn = is_read ? M68K_INS_PLPAR : M68K_INS_PLPAW;
4602
4603
0
  ext = build_init_op(info, insn, 1, 0);
4604
0
  op = &ext->operands[0];
4605
0
  op->address_mode = M68K_AM_REGI_ADDR;
4606
0
  op->type = M68K_OP_MEM;
4607
0
  op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4608
0
}
4609
4610
static void d68060_halt(m68k_info *info)
4611
1
{
4612
1
  LIMIT_FEATURE_UNDECODED(info, CS_MODE_M68K_060 | CS_MODE_M68K_CF_ISA_A);
4613
0
  build_init_op(info, M68K_INS_HALT, 0, 0);
4614
0
}
4615
4616
static void d68cpu32_bgnd(m68k_info *info)
4617
2
{
4618
2
  LIMIT_FEATURE_UNDECODED(info, CS_MODE_M68K_CPU32);
4619
0
  build_init_op(info, M68K_INS_BGND, 0, 0);
4620
0
}
4621
4622
static void d68cpu32_tbl(m68k_info *info)
4623
383
{
4624
383
  uint16_t ext_word;
4625
383
  int is_signed, is_round, is_memory;
4626
383
  int dx, size_bits, size;
4627
383
  int insn;
4628
383
  cs_m68k *cs_ext;
4629
383
  cs_m68k_op *op0;
4630
383
  cs_m68k_op *op1;
4631
4632
383
  if (!m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
4633
383
    d68020_cpgen(info);
4634
383
    return;
4635
383
  }
4636
4637
0
  ext_word = (uint16_t)peek_imm_16(info);
4638
4639
0
  is_memory = (ext_word >> 8) & 1;
4640
0
  size_bits = (ext_word >> 6) & 3;
4641
4642
0
  if ((ext_word & 0x8200) || size_bits == 3 ||
4643
0
      (!is_memory && ((info->ir >> 3) & 7) != 0) ||
4644
0
      (is_memory && ((info->ir >> 3) & 7) < 2)) {
4645
0
    d68000_invalid(info);
4646
0
    return;
4647
0
  }
4648
4649
0
  ext_word = (uint16_t)read_imm_16(info);
4650
4651
0
  is_signed = (ext_word >> 11) & 1;
4652
0
  is_round = (ext_word >> 10) & 1;
4653
0
  is_memory = (ext_word >> 8) & 1;
4654
0
  dx = (ext_word >> 12) & 7;
4655
4656
0
  switch (size_bits) {
4657
0
  case 0:
4658
0
    size = 1;
4659
0
    break;
4660
0
  case 1:
4661
0
    size = 2;
4662
0
    break;
4663
0
  case 2:
4664
0
    size = 4;
4665
0
    break;
4666
0
  default:
4667
0
    d68000_invalid(info);
4668
0
    return;
4669
0
  }
4670
4671
0
  if (is_signed && is_round)
4672
0
    insn = M68K_INS_TBLSN;
4673
0
  else if (is_signed)
4674
0
    insn = M68K_INS_TBLS;
4675
0
  else if (is_round)
4676
0
    insn = M68K_INS_TBLUN;
4677
0
  else
4678
0
    insn = M68K_INS_TBLU;
4679
4680
0
  cs_ext = build_init_op(info, insn, 2, size);
4681
0
  op0 = &cs_ext->operands[0];
4682
0
  op1 = &cs_ext->operands[1];
4683
4684
0
  if (is_memory) {
4685
0
    if (!get_ea_mode_op(info, op0, info->ir, size)) {
4686
0
      invalid_insn(info);
4687
0
      return;
4688
0
    }
4689
0
  } else {
4690
0
    int dm = info->ir & 7;
4691
0
    int dn = ext_word & 7;
4692
4693
0
    op0->address_mode = M68K_AM_NONE;
4694
0
    op0->type = M68K_OP_REG_PAIR;
4695
0
    op0->reg_pair.reg_0 = M68K_REG_D0 + dm;
4696
0
    op0->reg_pair.reg_1 = M68K_REG_D0 + dn;
4697
0
  }
4698
4699
0
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
4700
0
  op1->reg = M68K_REG_D0 + dx;
4701
0
}
4702
4703
static int pmmu_valid_fc(int fc)
4704
0
{
4705
0
  return fc == 0 || fc == 1 || (fc & 0x18) == 0x08 || (fc & 0x10) != 0;
4706
0
}
4707
4708
static void pmmu_decode_fc(m68k_info *info, cs_m68k_op *op, int fc_source)
4709
0
{
4710
0
  if (fc_source == 0) {
4711
0
    op->address_mode = M68K_AM_NONE;
4712
0
    op->type = M68K_OP_REG;
4713
0
    op->reg = M68K_REG_SFC;
4714
0
  } else if (fc_source == 1) {
4715
0
    op->address_mode = M68K_AM_NONE;
4716
0
    op->type = M68K_OP_REG;
4717
0
    op->reg = M68K_REG_DFC;
4718
0
  } else if ((fc_source & 0x18) == 0x08) {
4719
0
    op->address_mode = M68K_AM_REG_DIRECT_DATA;
4720
0
    op->type = M68K_OP_REG;
4721
0
    op->reg = M68K_REG_D0 + (fc_source & 7);
4722
0
  } else {
4723
0
    op->type = M68K_OP_IMM;
4724
0
    op->address_mode = M68K_AM_IMMEDIATE;
4725
0
    op->imm = fc_source & 0xf;
4726
0
  }
4727
0
}
4728
4729
static void d68030_pmmu(m68k_info *info)
4730
0
{
4731
0
  uint16_t cmd;
4732
0
  int type;
4733
4734
0
  cmd = (uint16_t)peek_imm_16(info);
4735
0
  type = (cmd >> 13) & 7;
4736
4737
0
  switch (type) {
4738
0
  case 0: {
4739
0
    int preg = (cmd >> 10) & 7;
4740
0
    int direction;
4741
0
    m68k_reg pmmu_reg;
4742
0
    cs_m68k *ext;
4743
0
    cs_m68k_op *op0;
4744
0
    cs_m68k_op *op1;
4745
4746
0
    if ((preg != 2 && preg != 3) || (cmd & 0xff)) {
4747
0
      d68000_invalid(info);
4748
0
      return;
4749
0
    }
4750
4751
0
    read_imm_16(info);
4752
0
    direction = (cmd >> 9) & 1;
4753
0
    pmmu_reg = (preg == 2) ? M68K_REG_TT0 : M68K_REG_TT1;
4754
4755
0
    ext = build_init_op(info, M68K_INS_PMOVE, 2, 0);
4756
0
    op0 = &ext->operands[0];
4757
0
    op1 = &ext->operands[1];
4758
4759
0
    if (direction) {
4760
0
      op0->address_mode = M68K_AM_NONE;
4761
0
      op0->type = M68K_OP_REG;
4762
0
      op0->reg = pmmu_reg;
4763
0
      if (!get_ea_mode_op(info, op1, info->ir, 4)) {
4764
0
        invalid_insn(info);
4765
0
        return;
4766
0
      }
4767
0
    } else {
4768
0
      if (!get_ea_mode_op(info, op0, info->ir, 4)) {
4769
0
        invalid_insn(info);
4770
0
        return;
4771
0
      }
4772
0
      op1->address_mode = M68K_AM_NONE;
4773
0
      op1->type = M68K_OP_REG;
4774
0
      op1->reg = pmmu_reg;
4775
0
    }
4776
0
    break;
4777
0
  }
4778
4779
0
  case 1: {
4780
0
    int is_flush;
4781
4782
0
    if (cmd == 0x2400 &&
4783
0
        m68k_ea_field(info->ir) == M68K_EA_DATA_DIRECT_D0) {
4784
0
      read_imm_16(info);
4785
0
      build_init_op(info, M68K_INS_PFLUSHA, 0, 0);
4786
0
      break;
4787
0
    }
4788
4789
0
    is_flush = (cmd >> 12) & 1;
4790
4791
0
    if (is_flush) {
4792
0
      int fc = cmd & 0x1f;
4793
0
      int mask;
4794
0
      cs_m68k *ext;
4795
0
      cs_m68k_op *op0;
4796
0
      cs_m68k_op *op1;
4797
0
      cs_m68k_op *op2;
4798
4799
0
      if (!pmmu_valid_fc(fc)) {
4800
0
        d68000_invalid(info);
4801
0
        return;
4802
0
      }
4803
4804
0
      read_imm_16(info);
4805
0
      mask = (cmd >> 5) & 7;
4806
0
      ext = build_init_op(info, M68K_INS_PFLUSH, 3, 0);
4807
0
      op0 = &ext->operands[0];
4808
0
      op1 = &ext->operands[1];
4809
0
      op2 = &ext->operands[2];
4810
4811
0
      pmmu_decode_fc(info, op0, fc);
4812
4813
0
      op1->type = M68K_OP_IMM;
4814
0
      op1->address_mode = M68K_AM_IMMEDIATE;
4815
0
      op1->imm = mask;
4816
4817
0
      if (!get_ea_mode_op(info, op2, info->ir, 1)) {
4818
0
        invalid_insn(info);
4819
0
        return;
4820
0
      }
4821
0
    } else {
4822
0
      int fc_source = cmd & 0x1f;
4823
0
      int is_read;
4824
0
      int insn;
4825
0
      cs_m68k *ext;
4826
0
      cs_m68k_op *op0;
4827
0
      cs_m68k_op *op1;
4828
4829
0
      if (!pmmu_valid_fc(fc_source) || (cmd & 0xde0) != 0) {
4830
0
        d68000_invalid(info);
4831
0
        return;
4832
0
      }
4833
4834
0
      read_imm_16(info);
4835
0
      is_read = (cmd >> 9) & 1;
4836
0
      insn = is_read ? M68K_INS_PLOADR : M68K_INS_PLOADW;
4837
0
      ext = build_init_op(info, insn, 2, 0);
4838
0
      op0 = &ext->operands[0];
4839
0
      op1 = &ext->operands[1];
4840
4841
0
      pmmu_decode_fc(info, op0, fc_source);
4842
0
      if (!get_ea_mode_op(info, op1, info->ir, 1)) {
4843
0
        invalid_insn(info);
4844
0
        return;
4845
0
      }
4846
0
    }
4847
0
    break;
4848
0
  }
4849
4850
0
  case 2: {
4851
0
    int preg = (cmd >> 10) & 7;
4852
0
    int direction, fd, insn;
4853
0
    m68k_reg pmmu_reg;
4854
0
    cs_m68k *ext;
4855
0
    cs_m68k_op *op0;
4856
0
    cs_m68k_op *op1;
4857
4858
0
    if (cmd & 0xff) {
4859
0
      d68000_invalid(info);
4860
0
      return;
4861
0
    }
4862
4863
0
    switch (preg) {
4864
0
    case 0:
4865
0
      pmmu_reg = M68K_REG_TC;
4866
0
      break;
4867
0
    case 2:
4868
0
      pmmu_reg = M68K_REG_SRP;
4869
0
      break;
4870
0
    case 3:
4871
0
      pmmu_reg = M68K_REG_CRP;
4872
0
      break;
4873
0
    default:
4874
0
      d68000_invalid(info);
4875
0
      return;
4876
0
    }
4877
4878
0
    read_imm_16(info);
4879
0
    direction = (cmd >> 9) & 1;
4880
0
    fd = (cmd >> 8) & 1;
4881
0
    insn = fd ? M68K_INS_PMOVEFD : M68K_INS_PMOVE;
4882
4883
0
    ext = build_init_op(info, insn, 2, 0);
4884
0
    op0 = &ext->operands[0];
4885
0
    op1 = &ext->operands[1];
4886
4887
0
    if (direction) {
4888
0
      op0->address_mode = M68K_AM_NONE;
4889
0
      op0->type = M68K_OP_REG;
4890
0
      op0->reg = pmmu_reg;
4891
0
      if (!get_ea_mode_op(info, op1, info->ir, 4)) {
4892
0
        invalid_insn(info);
4893
0
        return;
4894
0
      }
4895
0
    } else {
4896
0
      if (!get_ea_mode_op(info, op0, info->ir, 4)) {
4897
0
        invalid_insn(info);
4898
0
        return;
4899
0
      }
4900
0
      op1->address_mode = M68K_AM_NONE;
4901
0
      op1->type = M68K_OP_REG;
4902
0
      op1->reg = pmmu_reg;
4903
0
    }
4904
0
    break;
4905
0
  }
4906
4907
0
  case 3: {
4908
0
    int direction;
4909
0
    cs_m68k *ext;
4910
0
    cs_m68k_op *op0;
4911
0
    cs_m68k_op *op1;
4912
4913
0
    if ((cmd & 0x1dff) != 0) {
4914
0
      d68000_invalid(info);
4915
0
      return;
4916
0
    }
4917
4918
0
    read_imm_16(info);
4919
0
    direction = (cmd >> 9) & 1;
4920
0
    ext = build_init_op(info, M68K_INS_PMOVE, 2, 0);
4921
0
    op0 = &ext->operands[0];
4922
0
    op1 = &ext->operands[1];
4923
4924
0
    if (direction) {
4925
0
      op0->address_mode = M68K_AM_NONE;
4926
0
      op0->type = M68K_OP_REG;
4927
0
      op0->reg = M68K_REG_MMUSR;
4928
0
      if (!get_ea_mode_op(info, op1, info->ir, 2)) {
4929
0
        invalid_insn(info);
4930
0
        return;
4931
0
      }
4932
0
    } else {
4933
0
      if (!get_ea_mode_op(info, op0, info->ir, 2)) {
4934
0
        invalid_insn(info);
4935
0
        return;
4936
0
      }
4937
0
      op1->address_mode = M68K_AM_NONE;
4938
0
      op1->type = M68K_OP_REG;
4939
0
      op1->reg = M68K_REG_MMUSR;
4940
0
    }
4941
0
    break;
4942
0
  }
4943
4944
0
  case 4: {
4945
0
    int fc_source = cmd & 0x1f;
4946
0
    int is_read, level, insn;
4947
0
    cs_m68k *ext;
4948
0
    cs_m68k_op *op0;
4949
0
    cs_m68k_op *op1;
4950
0
    cs_m68k_op *op2;
4951
4952
0
    if (!pmmu_valid_fc(fc_source) || (cmd & 0x1e0) != 0 ||
4953
0
        ((info->ir >> 3) & 7) == 0) {
4954
0
      d68000_invalid(info);
4955
0
      return;
4956
0
    }
4957
4958
0
    read_imm_16(info);
4959
0
    is_read = (cmd >> 9) & 1;
4960
0
    level = (cmd >> 10) & 7;
4961
0
    insn = is_read ? M68K_INS_PTESTR : M68K_INS_PTESTW;
4962
0
    ext = build_init_op(info, insn, 3, 0);
4963
0
    op0 = &ext->operands[0];
4964
0
    op1 = &ext->operands[1];
4965
0
    op2 = &ext->operands[2];
4966
4967
0
    pmmu_decode_fc(info, op0, fc_source);
4968
0
    if (!get_ea_mode_op(info, op1, info->ir, 1)) {
4969
0
      invalid_insn(info);
4970
0
      return;
4971
0
    }
4972
4973
0
    op2->type = M68K_OP_IMM;
4974
0
    op2->address_mode = M68K_AM_IMMEDIATE;
4975
0
    op2->imm = level;
4976
0
    break;
4977
0
  }
4978
4979
0
  default:
4980
0
    d68000_invalid(info);
4981
0
    return;
4982
0
  }
4983
0
}
4984
4985
static void d68060_lpstop(m68k_info *info)
4986
312
{
4987
312
  if (!m68k_has_feature(info, CS_MODE_M68K_CPU32 | CS_MODE_M68K_060)) {
4988
312
    d68020_cpgen(info);
4989
312
    return;
4990
312
  }
4991
4992
  /* LPSTOP extension word is 0x01c0. If it doesn't match,
4993
   * try TBL (CPU32) or fall through to cpgen.
4994
   */
4995
0
  if (peek_imm_16(info) != 0x01c0) {
4996
0
    if (m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
4997
0
      d68cpu32_tbl(info);
4998
0
    } else {
4999
0
      d68020_cpgen(info);
5000
0
    }
5001
0
    return;
5002
0
  }
5003
5004
0
  read_imm_16(info);
5005
0
  build_absolute_jump_with_immediate(info, M68K_INS_LPSTOP, 0,
5006
0
             read_imm_16(info));
5007
0
}
5008
5009
static void d68000_sub_er_8(m68k_info *info)
5010
1.33k
{
5011
1.33k
  build_er_1(info, M68K_INS_SUB, 1);
5012
1.33k
}
5013
5014
static void d68000_sub_er_16(m68k_info *info)
5015
1.05k
{
5016
1.05k
  build_er_1(info, M68K_INS_SUB, 2);
5017
1.05k
}
5018
5019
static void d68000_sub_er_32(m68k_info *info)
5020
2.50k
{
5021
2.50k
  build_er_1(info, M68K_INS_SUB, 4);
5022
2.50k
}
5023
5024
static void d68000_sub_re_8(m68k_info *info)
5025
401
{
5026
401
  build_re_1(info, M68K_INS_SUB, 1);
5027
401
}
5028
5029
static void d68000_sub_re_16(m68k_info *info)
5030
742
{
5031
742
  build_re_1(info, M68K_INS_SUB, 2);
5032
742
}
5033
5034
static void d68000_sub_re_32(m68k_info *info)
5035
2.38k
{
5036
2.38k
  build_re_1(info, M68K_INS_SUB, 4);
5037
2.38k
}
5038
5039
static void d68000_suba_16(m68k_info *info)
5040
666
{
5041
666
  build_ea_a(info, M68K_INS_SUBA, 2);
5042
666
}
5043
5044
static void d68000_suba_32(m68k_info *info)
5045
1.16k
{
5046
1.16k
  build_ea_a(info, M68K_INS_SUBA, 4);
5047
1.16k
}
5048
5049
static void d68000_subi_8(m68k_info *info)
5050
1.56k
{
5051
1.56k
  build_imm_ea(info, M68K_INS_SUBI, 1, read_imm_8(info));
5052
1.56k
}
5053
5054
static void d68000_subi_16(m68k_info *info)
5055
315
{
5056
315
  build_imm_ea(info, M68K_INS_SUBI, 2, read_imm_16(info));
5057
315
}
5058
5059
static void d68000_subi_32(m68k_info *info)
5060
224
{
5061
224
  build_imm_ea(info, M68K_INS_SUBI, 4, read_imm_32(info));
5062
224
}
5063
5064
static void d68000_subq_8(m68k_info *info)
5065
1.64k
{
5066
1.64k
  build_3bit_ea(info, M68K_INS_SUBQ, 1);
5067
1.64k
}
5068
5069
static void d68000_subq_16(m68k_info *info)
5070
2.61k
{
5071
2.61k
  build_3bit_ea(info, M68K_INS_SUBQ, 2);
5072
2.61k
}
5073
5074
static void d68000_subq_32(m68k_info *info)
5075
951
{
5076
951
  build_3bit_ea(info, M68K_INS_SUBQ, 4);
5077
951
}
5078
5079
static void d68000_subx_rr_8(m68k_info *info)
5080
800
{
5081
800
  build_rr(info, M68K_INS_SUBX, 1, 0);
5082
800
}
5083
5084
static void d68000_subx_rr_16(m68k_info *info)
5085
345
{
5086
345
  build_rr(info, M68K_INS_SUBX, 2, 0);
5087
345
}
5088
5089
static void d68000_subx_rr_32(m68k_info *info)
5090
1.09k
{
5091
1.09k
  build_rr(info, M68K_INS_SUBX, 4, 0);
5092
1.09k
}
5093
5094
static void d68000_subx_mm_8(m68k_info *info)
5095
247
{
5096
247
  build_mm(info, M68K_INS_SUBX, 1, 0);
5097
247
}
5098
5099
static void d68000_subx_mm_16(m68k_info *info)
5100
717
{
5101
717
  build_mm(info, M68K_INS_SUBX, 2, 0);
5102
717
}
5103
5104
static void d68000_subx_mm_32(m68k_info *info)
5105
195
{
5106
195
  build_mm(info, M68K_INS_SUBX, 4, 0);
5107
195
}
5108
5109
static void d68000_swap(m68k_info *info)
5110
200
{
5111
200
  build_d(info, M68K_INS_SWAP, 0);
5112
200
}
5113
5114
static void d68000_tas(m68k_info *info)
5115
410
{
5116
410
  build_ea(info, M68K_INS_TAS, 1);
5117
410
}
5118
5119
static void d68060_pulse(m68k_info *info)
5120
195
{
5121
195
  LIMIT_FEATURE(info, CS_MODE_M68K_060 | CS_MODE_M68K_CF_ISA_A);
5122
0
  build_init_op(info, M68K_INS_PULSE, 0, 0);
5123
0
}
5124
5125
static void d68000_trap(m68k_info *info)
5126
407
{
5127
407
  build_absolute_jump_with_immediate(info, M68K_INS_TRAP, 0,
5128
407
             info->ir & 0xf);
5129
407
}
5130
5131
static void d68020_trapcc_0(m68k_info *info)
5132
446
{
5133
446
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
5134
230
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE)) {
5135
0
    if (M68K_IR_CONDITION_NIBBLE(info) != M68K_CONDITION_FALSE) {
5136
0
      d68000_invalid(info);
5137
0
      return;
5138
0
    }
5139
0
    build_absolute_jump_with_immediate(info, M68K_INS_TPF, 0, 0);
5140
0
    info->extension.op_count = 0;
5141
0
    return;
5142
0
  }
5143
5144
230
  build_trap(info, 0, 0);
5145
5146
230
  info->extension.op_count = 0;
5147
230
}
5148
5149
static void d68020_trapcc_16(m68k_info *info)
5150
760
{
5151
760
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
5152
221
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE)) {
5153
0
    if (M68K_IR_CONDITION_NIBBLE(info) != M68K_CONDITION_FALSE) {
5154
0
      d68000_invalid(info);
5155
0
      return;
5156
0
    }
5157
0
    build_absolute_jump_with_immediate(info, M68K_INS_TPF, 2,
5158
0
               read_imm_16(info));
5159
0
    return;
5160
0
  }
5161
5162
221
  build_trap(info, 2, read_imm_16(info));
5163
221
}
5164
5165
static void d68020_trapcc_32(m68k_info *info)
5166
554
{
5167
554
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
5168
232
  if (m68k_has_feature(info, CS_MODE_M68K_COLDFIRE)) {
5169
0
    if (M68K_IR_CONDITION_NIBBLE(info) != M68K_CONDITION_FALSE) {
5170
0
      d68000_invalid(info);
5171
0
      return;
5172
0
    }
5173
0
    build_absolute_jump_with_immediate(info, M68K_INS_TPF, 4,
5174
0
               read_imm_32(info));
5175
0
    return;
5176
0
  }
5177
5178
232
  build_trap(info, 4, read_imm_32(info));
5179
232
}
5180
5181
static void d68000_trapv(m68k_info *info)
5182
1.09k
{
5183
1.09k
  MCInst_setOpcode(info->inst, M68K_INS_TRAPV);
5184
1.09k
}
5185
5186
static void d68000_tst_8(m68k_info *info)
5187
729
{
5188
729
  build_ea(info, M68K_INS_TST, 1);
5189
729
}
5190
5191
static void d68020_tst_pcdi_8(m68k_info *info)
5192
461
{
5193
461
  LIMIT_FEATURE(info, M68020_PLUS);
5194
254
  build_ea(info, M68K_INS_TST, 1);
5195
254
}
5196
5197
static void d68020_tst_pcix_8(m68k_info *info)
5198
404
{
5199
404
  LIMIT_FEATURE(info, M68020_PLUS);
5200
200
  build_ea(info, M68K_INS_TST, 1);
5201
200
}
5202
5203
static void d68020_tst_i_8(m68k_info *info)
5204
301
{
5205
301
  LIMIT_FEATURE(info, M68020_PLUS);
5206
223
  build_ea(info, M68K_INS_TST, 1);
5207
223
}
5208
5209
static void d68000_tst_16(m68k_info *info)
5210
415
{
5211
415
  build_ea(info, M68K_INS_TST, 2);
5212
415
}
5213
5214
static void d68020_tst_a_16(m68k_info *info)
5215
1.09k
{
5216
1.09k
  LIMIT_FEATURE(info, M68020_PLUS);
5217
783
  build_ea(info, M68K_INS_TST, 2);
5218
783
}
5219
5220
static void d68020_tst_pcdi_16(m68k_info *info)
5221
496
{
5222
496
  LIMIT_FEATURE(info, M68020_PLUS);
5223
298
  build_ea(info, M68K_INS_TST, 2);
5224
298
}
5225
5226
static void d68020_tst_pcix_16(m68k_info *info)
5227
557
{
5228
557
  LIMIT_FEATURE(info, M68020_PLUS);
5229
164
  build_ea(info, M68K_INS_TST, 2);
5230
164
}
5231
5232
static void d68020_tst_i_16(m68k_info *info)
5233
647
{
5234
647
  LIMIT_FEATURE(info, M68020_PLUS);
5235
197
  build_ea(info, M68K_INS_TST, 2);
5236
197
}
5237
5238
static void d68000_tst_32(m68k_info *info)
5239
386
{
5240
386
  build_ea(info, M68K_INS_TST, 4);
5241
386
}
5242
5243
static void d68020_tst_a_32(m68k_info *info)
5244
411
{
5245
411
  LIMIT_FEATURE(info, M68020_PLUS);
5246
209
  build_ea(info, M68K_INS_TST, 4);
5247
209
}
5248
5249
static void d68020_tst_pcdi_32(m68k_info *info)
5250
590
{
5251
590
  LIMIT_FEATURE(info, M68020_PLUS);
5252
198
  build_ea(info, M68K_INS_TST, 4);
5253
198
}
5254
5255
static void d68020_tst_pcix_32(m68k_info *info)
5256
424
{
5257
424
  LIMIT_FEATURE(info, M68020_PLUS);
5258
208
  build_ea(info, M68K_INS_TST, 4);
5259
208
}
5260
5261
static void d68020_tst_i_32(m68k_info *info)
5262
287
{
5263
287
  LIMIT_FEATURE(info, M68020_PLUS);
5264
66
  build_ea(info, M68K_INS_TST, 4);
5265
66
}
5266
5267
static void d68000_unlk(m68k_info *info)
5268
357
{
5269
357
  cs_m68k_op *op;
5270
357
  cs_m68k *ext = build_init_op(info, M68K_INS_UNLK, 1, 0);
5271
5272
357
  op = &ext->operands[0];
5273
5274
357
  op->address_mode = M68K_AM_REG_DIRECT_ADDR;
5275
357
  op->reg = M68K_REG_A0 + (info->ir & 7);
5276
357
}
5277
5278
static void d68020_unpk_rr(m68k_info *info)
5279
1.11k
{
5280
1.11k
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
5281
710
  build_rr(info, M68K_INS_UNPK, 0, read_imm_16(info));
5282
710
}
5283
5284
static void d68020_unpk_mm(m68k_info *info)
5285
890
{
5286
890
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
5287
646
  build_mm(info, M68K_INS_UNPK, 0, read_imm_16(info));
5288
646
}
5289
5290
/* This table is auto-generated. Look in contrib/m68k_instruction_tbl_gen for more info */
5291
#include "M68KInstructionTable.inc"
5292
5293
static int instruction_is_valid(m68k_info *info, const uint32_t word_check)
5294
312k
{
5295
312k
  const uint32_t instruction = info->ir;
5296
312k
  const instruction_struct *i = &g_instruction_table[instruction];
5297
5298
312k
  if ((i->word2_mask &&
5299
13.0k
       ((word_check & i->word2_mask) != i->word2_match)) ||
5300
311k
      (i->instruction == d68000_invalid)) {
5301
1.37k
    d68000_invalid(info);
5302
1.37k
    return 0;
5303
1.37k
  }
5304
5305
310k
  return 1;
5306
312k
}
5307
5308
static int exists_reg_list(const uint16_t *regs, uint8_t count, m68k_reg reg)
5309
389k
{
5310
389k
  uint8_t i;
5311
5312
559k
  for (i = 0; i < count; ++i) {
5313
177k
    if (regs[i] == (uint16_t)reg)
5314
8.01k
      return 1;
5315
177k
  }
5316
5317
381k
  return 0;
5318
389k
}
5319
5320
static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write)
5321
399k
{
5322
399k
  if (reg == M68K_REG_INVALID)
5323
9.54k
    return;
5324
5325
389k
  if (write) {
5326
209k
    if (exists_reg_list(info->regs_write, info->regs_write_count,
5327
209k
            reg))
5328
4.33k
      return;
5329
5330
205k
    info->regs_write[info->regs_write_count] = (uint16_t)reg;
5331
205k
    info->regs_write_count++;
5332
205k
  } else {
5333
180k
    if (exists_reg_list(info->regs_read, info->regs_read_count,
5334
180k
            reg))
5335
3.68k
      return;
5336
5337
176k
    info->regs_read[info->regs_read_count] = (uint16_t)reg;
5338
176k
    info->regs_read_count++;
5339
176k
  }
5340
389k
}
5341
5342
static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write)
5343
136k
{
5344
136k
  switch (op->address_mode) {
5345
0
  case M68K_AM_REG_DIRECT_ADDR:
5346
0
  case M68K_AM_REG_DIRECT_DATA:
5347
0
    add_reg_to_rw_list(info, op->reg, write);
5348
0
    break;
5349
5350
23.5k
  case M68K_AM_REGI_ADDR_POST_INC:
5351
57.9k
  case M68K_AM_REGI_ADDR_PRE_DEC:
5352
57.9k
    add_reg_to_rw_list(info, op->mem.base_reg, 1);
5353
57.9k
    break;
5354
5355
28.5k
  case M68K_AM_REGI_ADDR:
5356
45.5k
  case M68K_AM_REGI_ADDR_DISP:
5357
45.5k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5358
45.5k
    break;
5359
5360
11.7k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
5361
14.6k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
5362
16.7k
  case M68K_AM_MEMI_POST_INDEX:
5363
19.1k
  case M68K_AM_MEMI_PRE_INDEX:
5364
21.1k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
5365
21.6k
  case M68K_AM_PCI_INDEX_BASE_DISP:
5366
22.4k
  case M68K_AM_PC_MEMI_PRE_INDEX:
5367
23.1k
  case M68K_AM_PC_MEMI_POST_INDEX:
5368
23.1k
    add_reg_to_rw_list(info, op->mem.index_reg, 0);
5369
23.1k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5370
23.1k
    break;
5371
5372
  // no register(s) in the other addressing modes
5373
9.56k
  default:
5374
9.56k
    break;
5375
136k
  }
5376
136k
}
5377
5378
static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits,
5379
            int write)
5380
17.0k
{
5381
17.0k
  int i;
5382
5383
153k
  for (i = 0; i < 8; ++i) {
5384
136k
    if (bits & (1 << i)) {
5385
31.4k
      add_reg_to_rw_list(info, reg_start + i, write);
5386
31.4k
    }
5387
136k
  }
5388
17.0k
}
5389
5390
static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write)
5391
5.68k
{
5392
5.68k
  uint32_t bits = op->register_bits;
5393
5.68k
  update_bits_range(info, M68K_REG_D0, bits & 0xff, write);
5394
5.68k
  update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write);
5395
5.68k
  update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write);
5396
5.68k
}
5397
5398
static void update_op_reg_list(m68k_info *info, cs_m68k_op *op, int write)
5399
508k
{
5400
508k
  switch ((int)op->type) {
5401
208k
  case M68K_OP_REG:
5402
208k
    add_reg_to_rw_list(info, op->reg, write);
5403
208k
    break;
5404
5405
136k
  case M68K_OP_MEM:
5406
136k
    update_am_reg_list(info, op, write);
5407
136k
    break;
5408
5409
5.68k
  case M68K_OP_REG_BITS:
5410
5.68k
    update_reg_list_regbits(info, op, write);
5411
5.68k
    break;
5412
5413
4.71k
  case M68K_OP_REG_PAIR:
5414
4.71k
    add_reg_to_rw_list(info, op->reg_pair.reg_0, write);
5415
4.71k
    add_reg_to_rw_list(info, op->reg_pair.reg_1, write);
5416
4.71k
    break;
5417
153k
  default:
5418
153k
    break;
5419
508k
  }
5420
508k
}
5421
5422
static void build_regs_read_write_counts(m68k_info *info)
5423
309k
{
5424
309k
  int i;
5425
5426
309k
  if (!info->extension.op_count)
5427
3.50k
    return;
5428
305k
  if (MCInst_getOpcode(info->inst) == M68K_INS_FMOVE &&
5429
5.49k
      info->extension.op_size.type == M68K_SIZE_TYPE_FPU &&
5430
4.26k
      info->extension.op_size.fpu_size == M68K_FPU_SIZE_PACKED &&
5431
1.76k
      info->extension.op_count == 3) {
5432
    /* Packed register-to-memory FMOVE reads both the FP source and
5433
     * its static/dynamic k-factor; only the memory operand is a
5434
     * destination. */
5435
520
    update_op_reg_list(info, &info->extension.operands[0], 0);
5436
520
    update_op_reg_list(info, &info->extension.operands[1], 1);
5437
520
    update_op_reg_list(info, &info->extension.operands[2], 0);
5438
520
    return;
5439
520
  }
5440
305k
  if (info->inst->Opcode == M68K_INS_FMOVEM &&
5441
3.98k
      info->extension.op_count == 2 &&
5442
3.98k
      info->extension.operands[1].type == M68K_OP_REG) {
5443
862
    update_op_reg_list(info, &info->extension.operands[0], 0);
5444
862
    update_op_reg_list(info, &info->extension.operands[1], 0);
5445
862
    return;
5446
862
  }
5447
5448
304k
  if (MCInst_getOpcode(info->inst) == M68K_INS_BTST) {
5449
15.5k
    for (i = 0; i < info->extension.op_count; ++i)
5450
10.3k
      update_op_reg_list(info, &info->extension.operands[i],
5451
10.3k
             0);
5452
5.18k
    return;
5453
5.18k
  }
5454
5455
299k
  if (info->extension.op_count == 1) {
5456
107k
    update_op_reg_list(info, &info->extension.operands[0], 1);
5457
192k
  } else {
5458
    // first operand is always read
5459
192k
    update_op_reg_list(info, &info->extension.operands[0], 0);
5460
5461
    // remaining write
5462
388k
    for (i = 1; i < info->extension.op_count; ++i)
5463
195k
      update_op_reg_list(info, &info->extension.operands[i],
5464
195k
             1);
5465
192k
  }
5466
299k
}
5467
5468
static void m68k_setup_internals(m68k_info *info, MCInst *inst, uint32_t pc,
5469
         m68k_feature_mask features)
5470
310k
{
5471
310k
  info->inst = inst;
5472
310k
  info->pc = pc;
5473
310k
  info->ir = 0;
5474
310k
  info->features = features;
5475
310k
  if (m68k_has_feature(info, M68010_LESS))
5476
94.3k
    info->address_mask = 0x00ffffff;
5477
215k
  else
5478
215k
    info->address_mask = 0xffffffff;
5479
310k
}
5480
5481
/* ======================================================================== */
5482
/* ================================= API ================================== */
5483
/* ======================================================================== */
5484
5485
/* Disasemble one instruction at pc and store in str_buff */
5486
static uint32_t m68k_disassemble(m68k_info *info, uint32_t pc)
5487
310k
{
5488
310k
  MCInst *inst = info->inst;
5489
310k
  cs_m68k *ext = &info->extension;
5490
310k
  int i;
5491
310k
  uint32_t size;
5492
5493
310k
  inst->Opcode = M68K_INS_INVALID;
5494
5495
310k
  memset(ext, 0, sizeof(cs_m68k));
5496
310k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
5497
5498
2.17M
  for (i = 0; i < M68K_OPERAND_COUNT; ++i)
5499
1.86M
    ext->operands[i].type = M68K_OP_REG;
5500
5501
310k
  info->ir = peek_imm_16(info);
5502
310k
  if (instruction_is_valid(info, peek_imm_32(info) & 0xffff)) {
5503
309k
    info->ir = read_imm_16(info);
5504
309k
    g_instruction_table[info->ir].instruction(info);
5505
309k
  }
5506
5507
310k
  size = info->pc - pc;
5508
310k
  info->pc = pc;
5509
5510
310k
  return size;
5511
310k
}
5512
5513
bool M68K_getInstruction(csh ud, const uint8_t *code, size_t code_len,
5514
       MCInst *instr, uint16_t *size, uint64_t address,
5515
       void *inst_info)
5516
311k
{
5517
#ifdef M68K_DEBUG
5518
  SStream ss;
5519
#endif
5520
311k
  uint32_t sz = 0;
5521
311k
  m68k_feature_mask features = 0;
5522
311k
  cs_struct *handle = instr->csh;
5523
311k
  m68k_info *info = (m68k_info *)handle->printer_info;
5524
5525
  // code len has to be at least 2 bytes to be valid m68k
5526
5527
311k
  if (code_len < 2) {
5528
1.23k
    *size = 0;
5529
1.23k
    return false;
5530
1.23k
  }
5531
5532
310k
  if (instr->flat_insn->detail) {
5533
310k
    memset(instr->flat_insn->detail, 0,
5534
310k
           offsetof(cs_detail, m68k) + sizeof(cs_m68k));
5535
310k
  }
5536
5537
310k
  info->groups_count = 0;
5538
310k
  info->regs_read_count = 0;
5539
310k
  info->regs_write_count = 0;
5540
310k
  info->code = code;
5541
310k
  info->code_len = code_len;
5542
310k
  info->baseAddress = address;
5543
5544
310k
  features =
5545
310k
    (m68k_feature_mask)(handle->mode & CS_MODE_M68K_FEATURE_MASK);
5546
310k
  if (!features)
5547
94.3k
    features = CS_MODE_M68K_000;
5548
5549
310k
  m68k_setup_internals(info, instr, (uint32_t)address, features);
5550
310k
  sz = m68k_disassemble(info, (uint32_t)address);
5551
5552
310k
  if (sz == 0) {
5553
835
    *size = 2;
5554
835
    return false;
5555
835
  }
5556
5557
309k
  build_regs_read_write_counts(info);
5558
5559
#ifdef M68K_DEBUG
5560
  SStream_Init(&ss);
5561
  M68K_printInst(instr, &ss, info);
5562
#endif
5563
5564
  // Make sure we always stay within range
5565
309k
  if (sz > (uint32_t)code_len)
5566
1.28k
    *size = (uint16_t)code_len;
5567
307k
  else
5568
307k
    *size = sz;
5569
5570
  return true;
5571
310k
}