Coverage Report

Created: 2026-08-14 06:51

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