Coverage Report

Created: 2026-09-01 07:20

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