Coverage Report

Created: 2026-10-17 07:17

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