Coverage Report

Created: 2026-09-28 06:34

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