Coverage Report

Created: 2026-09-01 07:20

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