Coverage Report

Created: 2026-11-12 06:22

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