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
662k
{
56
662k
  const uint16_t v0 = info->code[addr + 0];
57
662k
  const uint16_t v1 = info->code[addr + 1];
58
662k
  return (v0 << 8) | v1;
59
662k
}
60
61
static unsigned int m68k_read_disassembler_32(const m68k_info *info,
62
                const uint64_t addr)
63
281k
{
64
281k
  const uint32_t v0 = info->code[addr + 0];
65
281k
  const uint32_t v1 = info->code[addr + 1];
66
281k
  const uint32_t v2 = info->code[addr + 2];
67
281k
  const uint32_t v3 = info->code[addr + 3];
68
281k
  return (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
69
281k
}
70
71
static uint64_t m68k_read_disassembler_64(const m68k_info *info,
72
            const uint64_t addr)
73
3.69k
{
74
3.69k
  const uint64_t v0 = info->code[addr + 0];
75
3.69k
  const uint64_t v1 = info->code[addr + 1];
76
3.69k
  const uint64_t v2 = info->code[addr + 2];
77
3.69k
  const uint64_t v3 = info->code[addr + 3];
78
3.69k
  const uint64_t v4 = info->code[addr + 4];
79
3.69k
  const uint64_t v5 = info->code[addr + 5];
80
3.69k
  const uint64_t v6 = info->code[addr + 6];
81
3.69k
  const uint64_t v7 = info->code[addr + 7];
82
3.69k
  return (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) |
83
3.69k
         (v5 << 16) | (v6 << 8) | v7;
84
3.69k
}
85
86
static unsigned int m68k_read_safe_16(const m68k_info *info,
87
              const uint64_t address)
88
663k
{
89
663k
  const uint64_t addr = (address - info->baseAddress) &
90
663k
            info->address_mask;
91
663k
  if (info->code_len < addr + 2) {
92
1.32k
    return 0xaaaa;
93
1.32k
  }
94
662k
  return m68k_read_disassembler_16(info, addr);
95
663k
}
96
97
static unsigned int m68k_read_safe_32(const m68k_info *info,
98
              const uint64_t address)
99
285k
{
100
285k
  const uint64_t addr = (address - info->baseAddress) &
101
285k
            info->address_mask;
102
285k
  if (info->code_len < addr + 4) {
103
3.88k
    return 0xaaaaaaaa;
104
3.88k
  }
105
281k
  return m68k_read_disassembler_32(info, addr);
106
285k
}
107
108
static uint64_t m68k_read_safe_64(const m68k_info *info, const uint64_t address)
109
3.71k
{
110
3.71k
  const uint64_t addr = (address - info->baseAddress) &
111
3.71k
            info->address_mask;
112
3.71k
  if (info->code_len < addr + 8) {
113
13
    return 0xaaaaaaaaaaaaaaaaLL;
114
13
  }
115
3.69k
  return m68k_read_disassembler_64(info, addr);
116
3.71k
}
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
16.5k
{
194
16.5k
  return (m68k_read_safe_16((info), (info)->pc) & 0xff);
195
16.5k
}
196
static unsigned int peek_imm_16(const m68k_info *info)
197
646k
{
198
646k
  return m68k_read_safe_16((info), (info)->pc);
199
646k
}
200
static unsigned int peek_imm_32(const m68k_info *info)
201
285k
{
202
285k
  return m68k_read_safe_32((info), (info)->pc);
203
285k
}
204
static unsigned long long peek_imm_64(const m68k_info *info)
205
3.71k
{
206
3.71k
  return m68k_read_safe_64((info), (info)->pc);
207
3.71k
}
208
209
static unsigned int read_imm_8(m68k_info *info)
210
16.5k
{
211
16.5k
  const unsigned int value = peek_imm_8(info);
212
16.5k
  (info)->pc += 2;
213
16.5k
  return value & 0xff;
214
16.5k
}
215
static unsigned int read_imm_16(m68k_info *info)
216
360k
{
217
360k
  const unsigned int value = peek_imm_16(info);
218
360k
  (info)->pc += 2;
219
360k
  return value & 0xffff;
220
360k
}
221
static unsigned int read_imm_32(m68k_info *info)
222
13.0k
{
223
13.0k
  const unsigned int value = peek_imm_32(info);
224
13.0k
  (info)->pc += 4;
225
13.0k
  return value & 0xffffffff;
226
13.0k
}
227
static unsigned long long read_imm_64(m68k_info *info)
228
3.71k
{
229
3.71k
  const unsigned long long value = peek_imm_64(info);
230
3.71k
  (info)->pc += 8;
231
3.71k
  return value & 0xffffffffffffffff;
232
3.71k
}
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
12.9k
{
270
12.9k
  return (value & 0x80) ? value | ~0xff : value & 0xff;
271
12.9k
}
272
273
static int make_int_16(int value)
274
4.89k
{
275
4.89k
  return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
276
4.89k
}
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
43.0k
{
641
43.0k
  info->groups[info->groups_count++] = (uint8_t)group;
642
43.0k
}
643
644
static cs_m68k *build_init_op(m68k_info *info, int opcode, int count, int size)
645
261k
{
646
261k
  cs_m68k *ext;
647
648
261k
  MCInst_setOpcode(info->inst, opcode);
649
650
261k
  ext = &info->extension;
651
652
261k
  ext->op_count = (uint8_t)count;
653
261k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
654
261k
  ext->op_size.cpu_size = size;
655
656
261k
  return ext;
657
261k
}
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
18.9k
{
695
18.9k
  build_re_gen_1(info, true, opcode, size);
696
18.9k
}
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
5.34k
{
734
5.34k
  cs_m68k_op *op0;
735
5.34k
  cs_m68k_op *op1;
736
5.34k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
737
738
5.34k
  op0 = &ext->operands[0];
739
5.34k
  op1 = &ext->operands[1];
740
741
5.34k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
742
5.34k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
743
744
5.34k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
745
5.34k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
746
747
5.34k
  if (imm > 0)
748
1.16k
    append_imm_operand(info, imm);
749
5.34k
}
750
751
static void build_r(m68k_info *info, int opcode, uint8_t size)
752
7.60k
{
753
7.60k
  cs_m68k_op *op0;
754
7.60k
  cs_m68k_op *op1;
755
7.60k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
756
757
7.60k
  op0 = &ext->operands[0];
758
7.60k
  op1 = &ext->operands[1];
759
760
7.60k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
761
7.60k
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
762
763
7.60k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
764
7.60k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
765
7.60k
}
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
7.37k
{
789
7.37k
  cs_m68k_op *op0;
790
7.37k
  cs_m68k_op *op1;
791
7.37k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
792
793
7.37k
  op0 = &ext->operands[0];
794
7.37k
  op1 = &ext->operands[1];
795
796
7.37k
  op0->type = M68K_OP_IMM;
797
7.37k
  op0->address_mode = M68K_AM_IMMEDIATE;
798
7.37k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
799
800
7.37k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
801
7.37k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
802
7.37k
}
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
4.04k
{
825
4.04k
  cs_m68k_op *op0;
826
4.04k
  cs_m68k_op *op1;
827
4.04k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
828
829
4.04k
  op0 = &ext->operands[0];
830
4.04k
  op1 = &ext->operands[1];
831
832
4.04k
  op0->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
833
4.04k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
834
835
4.04k
  op1->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
836
4.04k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
837
838
4.04k
  if (imm > 0)
839
1.12k
    append_imm_operand(info, imm);
840
4.04k
}
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
1.37k
{
892
1.37k
  cs_m68k_op *op0;
893
1.37k
  cs_m68k_op *op1;
894
1.37k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
895
896
1.37k
  op0 = &ext->operands[0];
897
1.37k
  op1 = &ext->operands[1];
898
899
1.37k
  op0->address_mode = M68K_AM_REGI_ADDR_POST_INC;
900
1.37k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
901
902
1.37k
  op1->address_mode = M68K_AM_REGI_ADDR_POST_INC;
903
1.37k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
904
1.37k
}
905
906
static void build_imm_special_reg(m68k_info *info, int opcode, uint32_t imm,
907
          int size, m68k_reg reg)
908
1.70k
{
909
1.70k
  cs_m68k_op *op0;
910
1.70k
  cs_m68k_op *op1;
911
1.70k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
912
913
1.70k
  op0 = &ext->operands[0];
914
1.70k
  op1 = &ext->operands[1];
915
916
1.70k
  op0->type = M68K_OP_IMM;
917
1.70k
  op0->address_mode = M68K_AM_IMMEDIATE;
918
1.70k
  op0->imm = imm;
919
920
1.70k
  op1->address_mode = M68K_AM_NONE;
921
1.70k
  op1->reg = reg;
922
1.70k
}
923
924
static void build_relative_branch(m68k_info *info, int opcode, int size,
925
          int displacement)
926
15.6k
{
927
15.6k
  cs_m68k_op *op;
928
15.6k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
929
930
15.6k
  op = &ext->operands[0];
931
932
15.6k
  op->type = M68K_OP_BR_DISP;
933
15.6k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
934
15.6k
  op->br_disp.disp = displacement;
935
15.6k
  op->br_disp.disp_size = size;
936
937
15.6k
  set_insn_group(info, M68K_GRP_JUMP);
938
15.6k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
939
15.6k
}
940
941
static void build_absolute_jump_with_immediate(m68k_info *info, int opcode,
942
                 int size, int immediate)
943
2.11k
{
944
2.11k
  cs_m68k_op *op;
945
2.11k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
946
947
2.11k
  op = &ext->operands[0];
948
949
2.11k
  op->type = M68K_OP_IMM;
950
2.11k
  op->address_mode = M68K_AM_IMMEDIATE;
951
2.11k
  op->imm = immediate;
952
953
2.11k
  set_insn_group(info, M68K_GRP_JUMP);
954
2.11k
}
955
956
static void build_bcc(m68k_info *info, int size, int displacement)
957
11.0k
{
958
11.0k
  build_relative_branch(info,
959
11.0k
            s_branch_lut[M68K_IR_CONDITION_NIBBLE(info)],
960
11.0k
            size, displacement);
961
11.0k
}
962
963
static void build_trap(m68k_info *info, int size, int immediate)
964
735
{
965
735
  build_absolute_jump_with_immediate(
966
735
    info, s_trap_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
967
735
    immediate);
968
735
}
969
970
static void build_dbxx(m68k_info *info, int opcode, int size, int displacement)
971
1.18k
{
972
1.18k
  cs_m68k_op *op0;
973
1.18k
  cs_m68k_op *op1;
974
1.18k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
975
976
1.18k
  op0 = &ext->operands[0];
977
1.18k
  op1 = &ext->operands[1];
978
979
1.18k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
980
1.18k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
981
982
1.18k
  op1->type = M68K_OP_BR_DISP;
983
1.18k
  op1->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
984
1.18k
  op1->br_disp.disp = displacement;
985
1.18k
  op1->br_disp.disp_size = M68K_OP_BR_DISP_SIZE_LONG;
986
987
1.18k
  set_insn_group(info, M68K_GRP_JUMP);
988
1.18k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
989
1.18k
}
990
991
static void build_dbcc(m68k_info *info, int size, int displacement)
992
436
{
993
436
  build_dbxx(info, s_dbcc_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
994
436
       displacement);
995
436
}
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
970
{
1061
970
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
1062
970
  cs_m68k_op *op;
1063
1064
970
  op = &ext->operands[0];
1065
1066
970
  op->address_mode = M68K_AM_REG_DIRECT_DATA;
1067
970
  op->reg = M68K_REG_D0 + (info->ir & 7);
1068
970
}
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
888
{
1166
888
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1167
888
  uint32_t s = 16 - 1; // extra shift needed at end
1168
1169
7.90k
  for (v >>= 1; v; v >>= 1) {
1170
7.01k
    r <<= 1;
1171
7.01k
    r |= v & 1;
1172
7.01k
    s--;
1173
7.01k
  }
1174
1175
888
  r <<= s; // shift when v's highest bits are zero
1176
888
  return r;
1177
888
}
1178
1179
static uint8_t reverse_bits_8(uint32_t v)
1180
2.42k
{
1181
2.42k
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1182
2.42k
  uint32_t s = 8 - 1; // extra shift needed at end
1183
1184
16.0k
  for (v >>= 1; v; v >>= 1) {
1185
13.6k
    r <<= 1;
1186
13.6k
    r |= v & 1;
1187
13.6k
    s--;
1188
13.6k
  }
1189
1190
2.42k
  r <<= s; // shift when v's highest bits are zero
1191
2.42k
  return r;
1192
2.42k
}
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
52.5k
{
1235
52.5k
  cs_m68k_op *op;
1236
52.5k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
1237
1238
52.5k
  MCInst_setOpcode(info->inst, opcode);
1239
1240
52.5k
  op = &ext->operands[0];
1241
1242
52.5k
  op->type = M68K_OP_IMM;
1243
52.5k
  op->address_mode = M68K_AM_IMMEDIATE;
1244
52.5k
  op->imm = data;
1245
52.5k
}
1246
1247
static void build_illegal(m68k_info *info, uint32_t data)
1248
195
{
1249
195
  build_imm(info, M68K_INS_ILLEGAL, data);
1250
195
}
1251
1252
static void build_invalid(m68k_info *info, uint32_t data)
1253
52.3k
{
1254
52.3k
  build_imm(info, M68K_INS_INVALID, data);
1255
52.3k
}
1256
1257
static void build_cas2(m68k_info *info, int size)
1258
799
{
1259
799
  uint32_t word3;
1260
799
  uint32_t extension;
1261
799
  cs_m68k_op *op0;
1262
799
  cs_m68k_op *op1;
1263
799
  cs_m68k_op *op2;
1264
799
  cs_m68k *ext = build_init_op(info, M68K_INS_CAS2, 3, size);
1265
799
  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
799
  word3 = peek_imm_32(info) & 0xffff;
1269
799
  if (!instruction_is_valid(info, word3))
1270
131
    return;
1271
1272
668
  op0 = &ext->operands[0];
1273
668
  op1 = &ext->operands[1];
1274
668
  op2 = &ext->operands[2];
1275
1276
668
  extension = read_imm_32(info);
1277
1278
668
  op0->address_mode = M68K_AM_NONE;
1279
668
  op0->type = M68K_OP_REG_PAIR;
1280
668
  op0->reg_pair.reg_0 = ((extension >> 16) & 7) + M68K_REG_D0;
1281
668
  op0->reg_pair.reg_1 = (extension & 7) + M68K_REG_D0;
1282
1283
668
  op1->address_mode = M68K_AM_NONE;
1284
668
  op1->type = M68K_OP_REG_PAIR;
1285
668
  op1->reg_pair.reg_0 = ((extension >> 22) & 7) + M68K_REG_D0;
1286
668
  op1->reg_pair.reg_1 = ((extension >> 6) & 7) + M68K_REG_D0;
1287
1288
668
  reg_0 = (extension >> 28) & 7;
1289
668
  reg_1 = (extension >> 12) & 7;
1290
1291
668
  op2->address_mode = M68K_AM_NONE;
1292
668
  op2->type = M68K_OP_REG_PAIR;
1293
668
  op2->reg_pair.reg_0 = reg_0 + (BIT_1F(extension) ? 8 : 0) + M68K_REG_D0;
1294
668
  op2->reg_pair.reg_1 = reg_1 + (BIT_F(extension) ? 8 : 0) + M68K_REG_D0;
1295
668
}
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
1.37k
{
1327
1.37k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE16, 2, 0);
1328
1.37k
  int i;
1329
1330
4.11k
  for (i = 0; i < 2; ++i) {
1331
2.74k
    cs_m68k_op *op = &ext->operands[i];
1332
2.74k
    const uint32_t d = data[i];
1333
2.74k
    const uint32_t m = modes[i];
1334
1335
2.74k
    op->type = M68K_OP_MEM;
1336
2.74k
    op->address_mode = m;
1337
1338
2.74k
    if (m == M68K_AM_REGI_ADDR_POST_INC || m == M68K_AM_REGI_ADDR)
1339
1.60k
      op->mem.base_reg = M68K_REG_A0 + d;
1340
1.13k
    else
1341
1.13k
      op->mem.address = d;
1342
2.74k
  }
1343
1.37k
}
1344
1345
static void build_link(m68k_info *info, int disp, int size)
1346
599
{
1347
599
  cs_m68k_op *op0;
1348
599
  cs_m68k_op *op1;
1349
599
  cs_m68k *ext = build_init_op(info, M68K_INS_LINK, 2, size);
1350
1351
599
  op0 = &ext->operands[0];
1352
599
  op1 = &ext->operands[1];
1353
1354
599
  op0->address_mode = M68K_AM_NONE;
1355
599
  op0->reg = M68K_REG_A0 + (info->ir & 7);
1356
1357
599
  op1->address_mode = M68K_AM_IMMEDIATE;
1358
599
  op1->type = M68K_OP_IMM;
1359
599
  op1->imm = disp;
1360
599
}
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
650
{
1400
650
  cs_m68k_op *op0;
1401
650
  cs_m68k_op *op1;
1402
650
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1403
1404
650
  op0 = &ext->operands[0];
1405
650
  op1 = &ext->operands[1];
1406
1407
650
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1408
1409
650
  op1->address_mode = M68K_AM_REGI_ADDR_DISP;
1410
650
  op1->type = M68K_OP_MEM;
1411
650
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1412
650
  op1->mem.disp = (int16_t)read_imm_16(info);
1413
650
}
1414
1415
static void build_movep_er(m68k_info *info, int size)
1416
1.06k
{
1417
1.06k
  cs_m68k_op *op0;
1418
1.06k
  cs_m68k_op *op1;
1419
1.06k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1420
1421
1.06k
  op0 = &ext->operands[0];
1422
1.06k
  op1 = &ext->operands[1];
1423
1424
1.06k
  op0->address_mode = M68K_AM_REGI_ADDR_DISP;
1425
1.06k
  op0->type = M68K_OP_MEM;
1426
1.06k
  op0->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1427
1.06k
  op0->mem.disp = (int16_t)read_imm_16(info);
1428
1429
1.06k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1430
1.06k
}
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
18.0k
{
1461
18.0k
  build_er_gen_1(info, true, opcode, size);
1462
18.0k
}
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
52.3k
{
1504
52.3k
  build_invalid(info, info->ir);
1505
52.3k
}
1506
1507
static void d68000_illegal(m68k_info *info)
1508
195
{
1509
195
  build_illegal(info, info->ir);
1510
195
}
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
447
{
2136
447
  build_rr(info, M68K_INS_ABCD, 1, 0);
2137
447
}
2138
2139
static void d68000_abcd_mm(m68k_info *info)
2140
242
{
2141
242
  build_mm(info, M68K_INS_ABCD, 1, 0);
2142
242
}
2143
2144
static void d68000_add_er_8(m68k_info *info)
2145
461
{
2146
461
  build_er_1(info, M68K_INS_ADD, 1);
2147
461
}
2148
2149
static void d68000_add_er_16(m68k_info *info)
2150
369
{
2151
369
  build_er_1(info, M68K_INS_ADD, 2);
2152
369
}
2153
2154
static void d68000_add_er_32(m68k_info *info)
2155
507
{
2156
507
  build_er_1(info, M68K_INS_ADD, 4);
2157
507
}
2158
2159
static void d68000_add_re_8(m68k_info *info)
2160
711
{
2161
711
  build_re_1(info, M68K_INS_ADD, 1);
2162
711
}
2163
2164
static void d68000_add_re_16(m68k_info *info)
2165
295
{
2166
295
  build_re_1(info, M68K_INS_ADD, 2);
2167
295
}
2168
2169
static void d68000_add_re_32(m68k_info *info)
2170
530
{
2171
530
  build_re_1(info, M68K_INS_ADD, 4);
2172
530
}
2173
2174
static void d68000_adda_16(m68k_info *info)
2175
1.61k
{
2176
1.61k
  build_ea_a(info, M68K_INS_ADDA, 2);
2177
1.61k
}
2178
2179
static void d68000_adda_32(m68k_info *info)
2180
1.92k
{
2181
1.92k
  build_ea_a(info, M68K_INS_ADDA, 4);
2182
1.92k
}
2183
2184
static void d68000_addi_8(m68k_info *info)
2185
313
{
2186
313
  build_imm_ea(info, M68K_INS_ADDI, 1, read_imm_8(info));
2187
313
}
2188
2189
static void d68000_addi_16(m68k_info *info)
2190
263
{
2191
263
  build_imm_ea(info, M68K_INS_ADDI, 2, read_imm_16(info));
2192
263
}
2193
2194
static void d68000_addi_32(m68k_info *info)
2195
303
{
2196
303
  build_imm_ea(info, M68K_INS_ADDI, 4, read_imm_32(info));
2197
303
}
2198
2199
static void d68000_addq_8(m68k_info *info)
2200
892
{
2201
892
  build_3bit_ea(info, M68K_INS_ADDQ, 1);
2202
892
}
2203
2204
static void d68000_addq_16(m68k_info *info)
2205
2.14k
{
2206
2.14k
  build_3bit_ea(info, M68K_INS_ADDQ, 2);
2207
2.14k
}
2208
2209
static void d68000_addq_32(m68k_info *info)
2210
300
{
2211
300
  build_3bit_ea(info, M68K_INS_ADDQ, 4);
2212
300
}
2213
2214
static void d68000_addx_rr_8(m68k_info *info)
2215
463
{
2216
463
  build_rr(info, M68K_INS_ADDX, 1, 0);
2217
463
}
2218
2219
static void d68000_addx_rr_16(m68k_info *info)
2220
328
{
2221
328
  build_rr(info, M68K_INS_ADDX, 2, 0);
2222
328
}
2223
2224
static void d68000_addx_rr_32(m68k_info *info)
2225
224
{
2226
224
  build_rr(info, M68K_INS_ADDX, 4, 0);
2227
224
}
2228
2229
static void d68000_addx_mm_8(m68k_info *info)
2230
259
{
2231
259
  build_mm(info, M68K_INS_ADDX, 1, 0);
2232
259
}
2233
2234
static void d68000_addx_mm_16(m68k_info *info)
2235
240
{
2236
240
  build_mm(info, M68K_INS_ADDX, 2, 0);
2237
240
}
2238
2239
static void d68000_addx_mm_32(m68k_info *info)
2240
284
{
2241
284
  build_mm(info, M68K_INS_ADDX, 4, 0);
2242
284
}
2243
2244
static void d68000_and_er_8(m68k_info *info)
2245
481
{
2246
481
  build_er_1(info, M68K_INS_AND, 1);
2247
481
}
2248
2249
static void d68000_and_er_16(m68k_info *info)
2250
859
{
2251
859
  build_er_1(info, M68K_INS_AND, 2);
2252
859
}
2253
2254
static void d68000_and_er_32(m68k_info *info)
2255
554
{
2256
554
  build_er_1(info, M68K_INS_AND, 4);
2257
554
}
2258
2259
static void d68000_and_re_8(m68k_info *info)
2260
255
{
2261
255
  build_re_1(info, M68K_INS_AND, 1);
2262
255
}
2263
2264
static void d68000_and_re_16(m68k_info *info)
2265
509
{
2266
509
  build_re_1(info, M68K_INS_AND, 2);
2267
509
}
2268
2269
static void d68000_and_re_32(m68k_info *info)
2270
436
{
2271
436
  build_re_1(info, M68K_INS_AND, 4);
2272
436
}
2273
2274
static void d68000_andi_8(m68k_info *info)
2275
471
{
2276
471
  build_imm_ea(info, M68K_INS_ANDI, 1, read_imm_8(info));
2277
471
}
2278
2279
static void d68000_andi_16(m68k_info *info)
2280
324
{
2281
324
  build_imm_ea(info, M68K_INS_ANDI, 2, read_imm_16(info));
2282
324
}
2283
2284
static void d68000_andi_32(m68k_info *info)
2285
391
{
2286
391
  build_imm_ea(info, M68K_INS_ANDI, 4, read_imm_32(info));
2287
391
}
2288
2289
static void d68000_andi_to_ccr(m68k_info *info)
2290
460
{
2291
460
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_8(info), 1,
2292
460
            M68K_REG_CCR);
2293
460
}
2294
2295
static void d68000_andi_to_sr(m68k_info *info)
2296
309
{
2297
309
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_16(info), 2,
2298
309
            M68K_REG_SR);
2299
309
}
2300
2301
static void d68000_asr_s_8(m68k_info *info)
2302
635
{
2303
635
  build_3bit_d(info, M68K_INS_ASR, 1);
2304
635
}
2305
2306
static void d68000_asr_s_16(m68k_info *info)
2307
211
{
2308
211
  build_3bit_d(info, M68K_INS_ASR, 2);
2309
211
}
2310
2311
static void d68000_asr_s_32(m68k_info *info)
2312
236
{
2313
236
  build_3bit_d(info, M68K_INS_ASR, 4);
2314
236
}
2315
2316
static void d68000_asr_r_8(m68k_info *info)
2317
517
{
2318
517
  build_r(info, M68K_INS_ASR, 1);
2319
517
}
2320
2321
static void d68000_asr_r_16(m68k_info *info)
2322
534
{
2323
534
  build_r(info, M68K_INS_ASR, 2);
2324
534
}
2325
2326
static void d68000_asr_r_32(m68k_info *info)
2327
205
{
2328
205
  build_r(info, M68K_INS_ASR, 4);
2329
205
}
2330
2331
static void d68000_asr_ea(m68k_info *info)
2332
334
{
2333
334
  build_ea(info, M68K_INS_ASR, 2);
2334
334
}
2335
2336
static void d68000_asl_s_8(m68k_info *info)
2337
508
{
2338
508
  build_3bit_d(info, M68K_INS_ASL, 1);
2339
508
}
2340
2341
static void d68000_asl_s_16(m68k_info *info)
2342
233
{
2343
233
  build_3bit_d(info, M68K_INS_ASL, 2);
2344
233
}
2345
2346
static void d68000_asl_s_32(m68k_info *info)
2347
276
{
2348
276
  build_3bit_d(info, M68K_INS_ASL, 4);
2349
276
}
2350
2351
static void d68000_asl_r_8(m68k_info *info)
2352
332
{
2353
332
  build_r(info, M68K_INS_ASL, 1);
2354
332
}
2355
2356
static void d68000_asl_r_16(m68k_info *info)
2357
335
{
2358
335
  build_r(info, M68K_INS_ASL, 2);
2359
335
}
2360
2361
static void d68000_asl_r_32(m68k_info *info)
2362
217
{
2363
217
  build_r(info, M68K_INS_ASL, 4);
2364
217
}
2365
2366
static void d68000_asl_ea(m68k_info *info)
2367
301
{
2368
301
  build_ea(info, M68K_INS_ASL, 2);
2369
301
}
2370
2371
static void d68000_bcc_8(m68k_info *info)
2372
10.1k
{
2373
10.1k
  build_bcc(info, 1, make_int_8(info->ir));
2374
10.1k
}
2375
2376
static void d68000_bcc_16(m68k_info *info)
2377
654
{
2378
654
  build_bcc(info, 2, make_int_16(read_imm_16(info)));
2379
654
}
2380
2381
static void d68020_bcc_32(m68k_info *info)
2382
531
{
2383
531
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2384
531
            CS_MODE_M68K_CF_ISA_C);
2385
231
  build_bcc(info, 4, read_imm_32(info));
2386
231
}
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
1.79k
{
2398
1.79k
  build_re_1(info, M68K_INS_BCHG, bit_op_size(info));
2399
1.79k
}
2400
2401
static void d68000_bchg_s(m68k_info *info)
2402
250
{
2403
250
  build_imm_ea(info, M68K_INS_BCHG, bit_op_size(info), read_imm_8(info));
2404
250
}
2405
2406
static void d68000_bclr_r(m68k_info *info)
2407
1.41k
{
2408
1.41k
  build_re_1(info, M68K_INS_BCLR, bit_op_size(info));
2409
1.41k
}
2410
2411
static void d68000_bclr_s(m68k_info *info)
2412
263
{
2413
263
  build_imm_ea(info, M68K_INS_BCLR, bit_op_size(info), read_imm_8(info));
2414
263
}
2415
2416
static void d68010_bkpt(m68k_info *info)
2417
555
{
2418
555
  LIMIT_FEATURE(info, M68010_PLUS);
2419
338
  build_absolute_jump_with_immediate(info, M68K_INS_BKPT, 0,
2420
338
             info->ir & 7);
2421
338
}
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
1.44k
{
2484
1.44k
  build_relative_branch(info, M68K_INS_BRA, 1, make_int_8(info->ir));
2485
1.44k
}
2486
2487
static void d68000_bra_16(m68k_info *info)
2488
553
{
2489
553
  build_relative_branch(info, M68K_INS_BRA, 2,
2490
553
            make_int_16(read_imm_16(info)));
2491
553
}
2492
2493
static void d68020_bra_32(m68k_info *info)
2494
404
{
2495
404
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2496
404
            CS_MODE_M68K_CF_ISA_C);
2497
209
  build_relative_branch(info, M68K_INS_BRA, 4, read_imm_32(info));
2498
209
}
2499
2500
static void d68000_bset_r(m68k_info *info)
2501
1.56k
{
2502
1.56k
  build_re_1(info, M68K_INS_BSET, bit_op_size(info));
2503
1.56k
}
2504
2505
static void d68000_bset_s(m68k_info *info)
2506
276
{
2507
276
  build_imm_ea(info, M68K_INS_BSET, bit_op_size(info), read_imm_8(info));
2508
276
}
2509
2510
static void d68000_bsr_8(m68k_info *info)
2511
1.39k
{
2512
1.39k
  build_relative_branch(info, M68K_INS_BSR, 1, make_int_8(info->ir));
2513
1.39k
}
2514
2515
static void d68000_bsr_16(m68k_info *info)
2516
809
{
2517
809
  build_relative_branch(info, M68K_INS_BSR, 2,
2518
809
            make_int_16(read_imm_16(info)));
2519
809
}
2520
2521
static void d68020_bsr_32(m68k_info *info)
2522
406
{
2523
406
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2524
406
            CS_MODE_M68K_CF_ISA_C);
2525
209
  build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info));
2526
209
}
2527
2528
static void d68000_btst_r(m68k_info *info)
2529
3.99k
{
2530
  // Size 2 reads a #imm destination as its full extension word.
2531
3.99k
  build_re_1(info, M68K_INS_BTST, 2);
2532
3.99k
  ISIZE = bit_op_size(info);
2533
3.99k
}
2534
2535
static void d68000_btst_s(m68k_info *info)
2536
318
{
2537
318
  build_imm_ea(info, M68K_INS_BTST, bit_op_size(info), read_imm_8(info));
2538
318
}
2539
2540
static void d68020_callm(m68k_info *info)
2541
436
{
2542
436
  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
424
{
2583
424
  build_er_1(info, M68K_INS_CHK, 2);
2584
424
}
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
583
{
2594
583
  LIMIT_FEATURE(info, M68020_PLUS);
2595
292
  build_chk2_cmp2(info, 1);
2596
292
}
2597
2598
static void d68020_chk2_cmp2_16(m68k_info *info)
2599
410
{
2600
410
  LIMIT_FEATURE(info, M68020_PLUS);
2601
212
  build_chk2_cmp2(info, 2);
2602
212
}
2603
2604
static void d68020_chk2_cmp2_32(m68k_info *info)
2605
295
{
2606
295
  LIMIT_FEATURE(info, M68020_PLUS);
2607
222
  build_chk2_cmp2(info, 4);
2608
222
}
2609
2610
static void d68040_cinv(m68k_info *info)
2611
959
{
2612
959
  LIMIT_FEATURE(info, M68040_PLUS);
2613
641
  build_cpush_cinv(info, M68K_INS_CINVL);
2614
641
}
2615
2616
static void d68000_clr_8(m68k_info *info)
2617
223
{
2618
223
  build_ea(info, M68K_INS_CLR, 1);
2619
223
}
2620
2621
static void d68000_clr_16(m68k_info *info)
2622
484
{
2623
484
  build_ea(info, M68K_INS_CLR, 2);
2624
484
}
2625
2626
static void d68000_clr_32(m68k_info *info)
2627
219
{
2628
219
  build_ea(info, M68K_INS_CLR, 4);
2629
219
}
2630
2631
static void d68000_cmp_8(m68k_info *info)
2632
860
{
2633
860
  build_er_1(info, M68K_INS_CMP, 1);
2634
860
}
2635
2636
static void d68000_cmp_16(m68k_info *info)
2637
426
{
2638
426
  build_er_1(info, M68K_INS_CMP, 2);
2639
426
}
2640
2641
static void d68000_cmp_32(m68k_info *info)
2642
1.58k
{
2643
1.58k
  build_er_1(info, M68K_INS_CMP, 4);
2644
1.58k
}
2645
2646
static void d68000_cmpa_16(m68k_info *info)
2647
817
{
2648
817
  build_ea_a(info, M68K_INS_CMPA, 2);
2649
817
}
2650
2651
static void d68000_cmpa_32(m68k_info *info)
2652
361
{
2653
361
  build_ea_a(info, M68K_INS_CMPA, 4);
2654
361
}
2655
2656
static void d68000_cmpi_8(m68k_info *info)
2657
625
{
2658
625
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2659
625
}
2660
2661
static void d68020_cmpi_pcdi_8(m68k_info *info)
2662
410
{
2663
410
  LIMIT_FEATURE(info, M68010_PLUS);
2664
205
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2665
205
}
2666
2667
static void d68020_cmpi_pcix_8(m68k_info *info)
2668
492
{
2669
492
  LIMIT_FEATURE(info, M68010_PLUS);
2670
206
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2671
206
}
2672
2673
static void d68000_cmpi_16(m68k_info *info)
2674
303
{
2675
303
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2676
303
}
2677
2678
static void d68020_cmpi_pcdi_16(m68k_info *info)
2679
543
{
2680
543
  LIMIT_FEATURE(info, M68010_PLUS);
2681
308
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2682
308
}
2683
2684
static void d68020_cmpi_pcix_16(m68k_info *info)
2685
534
{
2686
534
  LIMIT_FEATURE(info, M68010_PLUS);
2687
338
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2688
338
}
2689
2690
static void d68000_cmpi_32(m68k_info *info)
2691
110
{
2692
110
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2693
110
}
2694
2695
static void d68020_cmpi_pcdi_32(m68k_info *info)
2696
403
{
2697
403
  LIMIT_FEATURE(info, M68010_PLUS);
2698
206
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2699
206
}
2700
2701
static void d68020_cmpi_pcix_32(m68k_info *info)
2702
810
{
2703
810
  LIMIT_FEATURE(info, M68010_PLUS);
2704
219
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2705
219
}
2706
2707
static void d68000_cmpm_8(m68k_info *info)
2708
267
{
2709
267
  build_pi_pi(info, M68K_INS_CMPM, 1);
2710
267
}
2711
2712
static void d68000_cmpm_16(m68k_info *info)
2713
663
{
2714
663
  build_pi_pi(info, M68K_INS_CMPM, 2);
2715
663
}
2716
2717
static void d68000_cmpm_32(m68k_info *info)
2718
443
{
2719
443
  build_pi_pi(info, M68K_INS_CMPM, 4);
2720
443
}
2721
2722
static void make_cpbcc_operand(cs_m68k_op *op, int size, int displacement)
2723
2.61k
{
2724
2.61k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
2725
2.61k
  op->type = M68K_OP_BR_DISP;
2726
2.61k
  op->br_disp.disp = displacement;
2727
2.61k
  op->br_disp.disp_size = size;
2728
2.61k
}
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
752
{
3446
752
  build_dbxx(info, M68K_INS_DBRA, 0, make_int_16(read_imm_16(info)));
3447
752
}
3448
3449
static void d68000_dbcc(m68k_info *info)
3450
436
{
3451
436
  build_dbcc(info, 0, make_int_16(read_imm_16(info)));
3452
436
}
3453
3454
static void d68000_divs(m68k_info *info)
3455
829
{
3456
829
  build_er_1(info, M68K_INS_DIVS, 2);
3457
829
}
3458
3459
static void d68000_divu(m68k_info *info)
3460
462
{
3461
462
  build_er_1(info, M68K_INS_DIVU, 2);
3462
462
}
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
507
{
3514
507
  build_re_1(info, M68K_INS_EOR, 1);
3515
507
}
3516
3517
static void d68000_eor_16(m68k_info *info)
3518
532
{
3519
532
  build_re_1(info, M68K_INS_EOR, 2);
3520
532
}
3521
3522
static void d68000_eor_32(m68k_info *info)
3523
643
{
3524
643
  build_re_1(info, M68K_INS_EOR, 4);
3525
643
}
3526
3527
static void d68000_eori_8(m68k_info *info)
3528
351
{
3529
351
  build_imm_ea(info, M68K_INS_EORI, 1, read_imm_8(info));
3530
351
}
3531
3532
static void d68000_eori_16(m68k_info *info)
3533
252
{
3534
252
  build_imm_ea(info, M68K_INS_EORI, 2, read_imm_16(info));
3535
252
}
3536
3537
static void d68000_eori_32(m68k_info *info)
3538
219
{
3539
219
  build_imm_ea(info, M68K_INS_EORI, 4, read_imm_32(info));
3540
219
}
3541
3542
static void d68000_eori_to_ccr(m68k_info *info)
3543
217
{
3544
217
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_8(info), 1,
3545
217
            M68K_REG_CCR);
3546
217
}
3547
3548
static void d68000_eori_to_sr(m68k_info *info)
3549
234
{
3550
234
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_16(info), 2,
3551
234
            M68K_REG_SR);
3552
234
}
3553
3554
static void d68000_exg_dd(m68k_info *info)
3555
495
{
3556
495
  build_r(info, M68K_INS_EXG, 4);
3557
495
}
3558
3559
static void d68000_exg_aa(m68k_info *info)
3560
425
{
3561
425
  cs_m68k_op *op0;
3562
425
  cs_m68k_op *op1;
3563
425
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3564
3565
425
  op0 = &ext->operands[0];
3566
425
  op1 = &ext->operands[1];
3567
3568
425
  op0->address_mode = M68K_AM_NONE;
3569
425
  op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
3570
3571
425
  op1->address_mode = M68K_AM_NONE;
3572
425
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3573
425
}
3574
3575
static void d68000_exg_da(m68k_info *info)
3576
206
{
3577
206
  cs_m68k_op *op0;
3578
206
  cs_m68k_op *op1;
3579
206
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3580
3581
206
  op0 = &ext->operands[0];
3582
206
  op1 = &ext->operands[1];
3583
3584
206
  op0->address_mode = M68K_AM_NONE;
3585
206
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3586
3587
206
  op1->address_mode = M68K_AM_NONE;
3588
206
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3589
206
}
3590
3591
static void d68000_ext_16(m68k_info *info)
3592
221
{
3593
221
  build_d(info, M68K_INS_EXT, 2);
3594
221
}
3595
3596
static void d68000_ext_32(m68k_info *info)
3597
470
{
3598
470
  build_d(info, M68K_INS_EXT, 4);
3599
470
}
3600
3601
static void d68020_extb_32(m68k_info *info)
3602
393
{
3603
393
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
3604
198
  build_d(info, M68K_INS_EXTB, 4);
3605
198
}
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.30k
{
3629
1.30k
  build_ea_a(info, M68K_INS_LEA, 4);
3630
1.30k
}
3631
3632
static void d68000_link_16(m68k_info *info)
3633
259
{
3634
259
  build_link(info, read_imm_16(info), 2);
3635
259
}
3636
3637
static void d68020_link_32(m68k_info *info)
3638
569
{
3639
569
  LIMIT_FEATURE(info, M68020_PLUS);
3640
340
  build_link(info, read_imm_32(info), 4);
3641
340
}
3642
3643
static void d68000_lsr_s_8(m68k_info *info)
3644
254
{
3645
254
  build_3bit_d(info, M68K_INS_LSR, 1);
3646
254
}
3647
3648
static void d68000_lsr_s_16(m68k_info *info)
3649
283
{
3650
283
  build_3bit_d(info, M68K_INS_LSR, 2);
3651
283
}
3652
3653
static void d68000_lsr_s_32(m68k_info *info)
3654
281
{
3655
281
  build_3bit_d(info, M68K_INS_LSR, 4);
3656
281
}
3657
3658
static void d68000_lsr_r_8(m68k_info *info)
3659
500
{
3660
500
  build_r(info, M68K_INS_LSR, 1);
3661
500
}
3662
3663
static void d68000_lsr_r_16(m68k_info *info)
3664
235
{
3665
235
  build_r(info, M68K_INS_LSR, 2);
3666
235
}
3667
3668
static void d68000_lsr_r_32(m68k_info *info)
3669
200
{
3670
200
  build_r(info, M68K_INS_LSR, 4);
3671
200
}
3672
3673
static void d68000_lsr_ea(m68k_info *info)
3674
827
{
3675
827
  build_ea(info, M68K_INS_LSR, 2);
3676
827
}
3677
3678
static void d68000_lsl_s_8(m68k_info *info)
3679
480
{
3680
480
  build_3bit_d(info, M68K_INS_LSL, 1);
3681
480
}
3682
3683
static void d68000_lsl_s_16(m68k_info *info)
3684
452
{
3685
452
  build_3bit_d(info, M68K_INS_LSL, 2);
3686
452
}
3687
3688
static void d68000_lsl_s_32(m68k_info *info)
3689
222
{
3690
222
  build_3bit_d(info, M68K_INS_LSL, 4);
3691
222
}
3692
3693
static void d68000_lsl_r_8(m68k_info *info)
3694
250
{
3695
250
  build_r(info, M68K_INS_LSL, 1);
3696
250
}
3697
3698
static void d68000_lsl_r_16(m68k_info *info)
3699
267
{
3700
267
  build_r(info, M68K_INS_LSL, 2);
3701
267
}
3702
3703
static void d68000_lsl_r_32(m68k_info *info)
3704
325
{
3705
325
  build_r(info, M68K_INS_LSL, 4);
3706
325
}
3707
3708
static void d68000_lsl_ea(m68k_info *info)
3709
502
{
3710
502
  build_ea(info, M68K_INS_LSL, 2);
3711
502
}
3712
3713
static void d68000_move_8(m68k_info *info)
3714
5.68k
{
3715
5.68k
  build_ea_ea(info, M68K_INS_MOVE, 1);
3716
5.68k
}
3717
3718
static void d68000_move_16(m68k_info *info)
3719
9.11k
{
3720
9.11k
  build_ea_ea(info, M68K_INS_MOVE, 2);
3721
9.11k
}
3722
3723
static void d68000_move_32(m68k_info *info)
3724
13.9k
{
3725
13.9k
  build_ea_ea(info, M68K_INS_MOVE, 4);
3726
13.9k
}
3727
3728
static void d68000_movea_16(m68k_info *info)
3729
2.07k
{
3730
2.07k
  build_ea_a(info, M68K_INS_MOVEA, 2);
3731
2.07k
}
3732
3733
static void d68000_movea_32(m68k_info *info)
3734
1.79k
{
3735
1.79k
  build_ea_a(info, M68K_INS_MOVEA, 4);
3736
1.79k
}
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
653
{
3969
653
  build_movem_re(info, M68K_INS_MOVEM, 2);
3970
653
}
3971
3972
static void d68000_movem_pd_32(m68k_info *info)
3973
235
{
3974
235
  build_movem_re(info, M68K_INS_MOVEM, 4);
3975
235
}
3976
3977
static void d68000_movem_er_16(m68k_info *info)
3978
301
{
3979
301
  build_movem_er(info, M68K_INS_MOVEM, 2);
3980
301
}
3981
3982
static void d68000_movem_er_32(m68k_info *info)
3983
826
{
3984
826
  build_movem_er(info, M68K_INS_MOVEM, 4);
3985
826
}
3986
3987
static void d68000_movem_re_16(m68k_info *info)
3988
513
{
3989
513
  build_movem_re(info, M68K_INS_MOVEM, 2);
3990
513
}
3991
3992
static void d68000_movem_re_32(m68k_info *info)
3993
445
{
3994
445
  build_movem_re(info, M68K_INS_MOVEM, 4);
3995
445
}
3996
3997
static void d68000_movep_re_16(m68k_info *info)
3998
433
{
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
433
  build_movep_re(info, 2);
4004
433
}
4005
4006
static void d68000_movep_re_32(m68k_info *info)
4007
217
{
4008
217
  build_movep_re(info, 4);
4009
217
}
4010
4011
static void d68000_movep_er_16(m68k_info *info)
4012
624
{
4013
624
  build_movep_er(info, 2);
4014
624
}
4015
4016
static void d68000_movep_er_32(m68k_info *info)
4017
439
{
4018
439
  build_movep_er(info, 4);
4019
439
}
4020
4021
static void d68010_moves_8(m68k_info *info)
4022
763
{
4023
763
  LIMIT_FEATURE(info, M68010_PLUS);
4024
321
  build_moves(info, 1);
4025
321
}
4026
4027
static void d68010_moves_16(m68k_info *info)
4028
465
{
4029
  //uint32_t extension;
4030
465
  LIMIT_FEATURE(info, M68010_PLUS);
4031
179
  build_moves(info, 2);
4032
179
}
4033
4034
static void d68010_moves_32(m68k_info *info)
4035
135
{
4036
135
  LIMIT_FEATURE(info, M68010_PLUS);
4037
67
  build_moves(info, 4);
4038
67
}
4039
4040
static void d68000_moveq(m68k_info *info)
4041
6.51k
{
4042
6.51k
  cs_m68k_op *op0;
4043
6.51k
  cs_m68k_op *op1;
4044
4045
6.51k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEQ, 2, 0);
4046
4047
6.51k
  op0 = &ext->operands[0];
4048
6.51k
  op1 = &ext->operands[1];
4049
4050
6.51k
  op0->type = M68K_OP_IMM;
4051
6.51k
  op0->address_mode = M68K_AM_IMMEDIATE;
4052
6.51k
  op0->imm = (info->ir & 0xff);
4053
4054
6.51k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
4055
6.51k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
4056
6.51k
}
4057
4058
static void d68040_move16_pi_pi(m68k_info *info)
4059
307
{
4060
307
  uint32_t data[] = { info->ir & 7, (read_imm_16(info) >> 12) & 7 };
4061
307
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
4062
307
           M68K_AM_REGI_ADDR_POST_INC };
4063
4064
307
  LIMIT_FEATURE(info, M68040_PLUS);
4065
4066
232
  build_move16(info, data, modes);
4067
232
}
4068
4069
static void d68040_move16_pi_al(m68k_info *info)
4070
711
{
4071
711
  uint32_t data[2];
4072
711
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
4073
711
           M68K_AM_ABSOLUTE_DATA_LONG };
4074
4075
711
  LIMIT_FEATURE(info, M68040_PLUS);
4076
4077
335
  data[0] = info->ir & 7;
4078
335
  data[1] = read_imm_32(info);
4079
335
  build_move16(info, data, modes);
4080
335
}
4081
4082
static void d68040_move16_al_pi(m68k_info *info)
4083
467
{
4084
467
  uint32_t data[2];
4085
467
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG,
4086
467
           M68K_AM_REGI_ADDR_POST_INC };
4087
4088
467
  LIMIT_FEATURE(info, M68040_PLUS);
4089
4090
245
  data[0] = read_imm_32(info);
4091
245
  data[1] = info->ir & 7;
4092
245
  build_move16(info, data, modes);
4093
245
}
4094
4095
static void d68040_move16_ai_al(m68k_info *info)
4096
536
{
4097
536
  uint32_t data[2];
4098
536
  uint32_t modes[] = { M68K_AM_REGI_ADDR, M68K_AM_ABSOLUTE_DATA_LONG };
4099
4100
536
  LIMIT_FEATURE(info, M68040_PLUS);
4101
4102
310
  data[0] = info->ir & 7;
4103
310
  data[1] = read_imm_32(info);
4104
310
  build_move16(info, data, modes);
4105
310
}
4106
4107
static void d68040_move16_al_ai(m68k_info *info)
4108
443
{
4109
443
  uint32_t data[2];
4110
443
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REGI_ADDR };
4111
4112
443
  LIMIT_FEATURE(info, M68040_PLUS);
4113
4114
249
  data[0] = read_imm_32(info);
4115
249
  data[1] = info->ir & 7;
4116
249
  build_move16(info, data, modes);
4117
249
}
4118
4119
static void d68000_muls(m68k_info *info)
4120
1.49k
{
4121
1.49k
  build_er_1(info, M68K_INS_MULS, 2);
4122
1.49k
}
4123
4124
static void d68000_mulu(m68k_info *info)
4125
1.38k
{
4126
1.38k
  build_er_1(info, M68K_INS_MULU, 2);
4127
1.38k
}
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
466
{
4174
466
  build_ea(info, M68K_INS_NBCD, 1);
4175
466
}
4176
4177
static void d68000_neg_8(m68k_info *info)
4178
225
{
4179
225
  build_ea(info, M68K_INS_NEG, 1);
4180
225
}
4181
4182
static void d68000_neg_16(m68k_info *info)
4183
315
{
4184
315
  build_ea(info, M68K_INS_NEG, 2);
4185
315
}
4186
4187
static void d68000_neg_32(m68k_info *info)
4188
220
{
4189
220
  build_ea(info, M68K_INS_NEG, 4);
4190
220
}
4191
4192
static void d68000_negx_8(m68k_info *info)
4193
382
{
4194
382
  build_ea(info, M68K_INS_NEGX, 1);
4195
382
}
4196
4197
static void d68000_negx_16(m68k_info *info)
4198
296
{
4199
296
  build_ea(info, M68K_INS_NEGX, 2);
4200
296
}
4201
4202
static void d68000_negx_32(m68k_info *info)
4203
576
{
4204
576
  build_ea(info, M68K_INS_NEGX, 4);
4205
576
}
4206
4207
static void d68000_nop(m68k_info *info)
4208
282
{
4209
282
  MCInst_setOpcode(info->inst, M68K_INS_NOP);
4210
282
}
4211
4212
static void d68000_not_8(m68k_info *info)
4213
250
{
4214
250
  build_ea(info, M68K_INS_NOT, 1);
4215
250
}
4216
4217
static void d68000_not_16(m68k_info *info)
4218
415
{
4219
415
  build_ea(info, M68K_INS_NOT, 2);
4220
415
}
4221
4222
static void d68000_not_32(m68k_info *info)
4223
347
{
4224
347
  build_ea(info, M68K_INS_NOT, 4);
4225
347
}
4226
4227
static void d68000_or_er_8(m68k_info *info)
4228
967
{
4229
967
  build_er_1(info, M68K_INS_OR, 1);
4230
967
}
4231
4232
static void d68000_or_er_16(m68k_info *info)
4233
580
{
4234
580
  build_er_1(info, M68K_INS_OR, 2);
4235
580
}
4236
4237
static void d68000_or_er_32(m68k_info *info)
4238
950
{
4239
950
  build_er_1(info, M68K_INS_OR, 4);
4240
950
}
4241
4242
static void d68000_or_re_8(m68k_info *info)
4243
685
{
4244
685
  build_re_1(info, M68K_INS_OR, 1);
4245
685
}
4246
4247
static void d68000_or_re_16(m68k_info *info)
4248
1.11k
{
4249
1.11k
  build_re_1(info, M68K_INS_OR, 2);
4250
1.11k
}
4251
4252
static void d68000_or_re_32(m68k_info *info)
4253
815
{
4254
815
  build_re_1(info, M68K_INS_OR, 4);
4255
815
}
4256
4257
static void d68000_ori_8(m68k_info *info)
4258
11.1k
{
4259
11.1k
  build_imm_ea(info, M68K_INS_ORI, 1, read_imm_8(info));
4260
11.1k
}
4261
4262
static void d68000_ori_16(m68k_info *info)
4263
1.33k
{
4264
1.33k
  build_imm_ea(info, M68K_INS_ORI, 2, read_imm_16(info));
4265
1.33k
}
4266
4267
static void d68000_ori_32(m68k_info *info)
4268
1.43k
{
4269
1.43k
  build_imm_ea(info, M68K_INS_ORI, 4, read_imm_32(info));
4270
1.43k
}
4271
4272
static void d68000_ori_to_ccr(m68k_info *info)
4273
238
{
4274
238
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_8(info), 1,
4275
238
            M68K_REG_CCR);
4276
238
}
4277
4278
static void d68000_ori_to_sr(m68k_info *info)
4279
242
{
4280
242
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_16(info), 2,
4281
242
            M68K_REG_SR);
4282
242
}
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
315
{
4298
315
  build_ea(info, M68K_INS_PEA, 4);
4299
315
}
4300
4301
static void d68000_reset(m68k_info *info)
4302
505
{
4303
505
  MCInst_setOpcode(info->inst, M68K_INS_RESET);
4304
505
}
4305
4306
static void d68000_ror_s_8(m68k_info *info)
4307
222
{
4308
222
  build_3bit_d(info, M68K_INS_ROR, 1);
4309
222
}
4310
4311
static void d68000_ror_s_16(m68k_info *info)
4312
456
{
4313
456
  build_3bit_d(info, M68K_INS_ROR, 2);
4314
456
}
4315
4316
static void d68000_ror_s_32(m68k_info *info)
4317
209
{
4318
209
  build_3bit_d(info, M68K_INS_ROR, 4);
4319
209
}
4320
4321
static void d68000_ror_r_8(m68k_info *info)
4322
240
{
4323
240
  build_r(info, M68K_INS_ROR, 1);
4324
240
}
4325
4326
static void d68000_ror_r_16(m68k_info *info)
4327
261
{
4328
261
  build_r(info, M68K_INS_ROR, 2);
4329
261
}
4330
4331
static void d68000_ror_r_32(m68k_info *info)
4332
254
{
4333
254
  build_r(info, M68K_INS_ROR, 4);
4334
254
}
4335
4336
static void d68000_ror_ea(m68k_info *info)
4337
734
{
4338
734
  build_ea(info, M68K_INS_ROR, 2);
4339
734
}
4340
4341
static void d68000_rol_s_8(m68k_info *info)
4342
210
{
4343
210
  build_3bit_d(info, M68K_INS_ROL, 1);
4344
210
}
4345
4346
static void d68000_rol_s_16(m68k_info *info)
4347
490
{
4348
490
  build_3bit_d(info, M68K_INS_ROL, 2);
4349
490
}
4350
4351
static void d68000_rol_s_32(m68k_info *info)
4352
234
{
4353
234
  build_3bit_d(info, M68K_INS_ROL, 4);
4354
234
}
4355
4356
static void d68000_rol_r_8(m68k_info *info)
4357
253
{
4358
253
  build_r(info, M68K_INS_ROL, 1);
4359
253
}
4360
4361
static void d68000_rol_r_16(m68k_info *info)
4362
417
{
4363
417
  build_r(info, M68K_INS_ROL, 2);
4364
417
}
4365
4366
static void d68000_rol_r_32(m68k_info *info)
4367
319
{
4368
319
  build_r(info, M68K_INS_ROL, 4);
4369
319
}
4370
4371
static void d68000_rol_ea(m68k_info *info)
4372
1.11k
{
4373
1.11k
  build_ea(info, M68K_INS_ROL, 2);
4374
1.11k
}
4375
4376
static void d68000_roxr_s_8(m68k_info *info)
4377
247
{
4378
247
  build_3bit_d(info, M68K_INS_ROXR, 1);
4379
247
}
4380
4381
static void d68000_roxr_s_16(m68k_info *info)
4382
208
{
4383
208
  build_3bit_d(info, M68K_INS_ROXR, 2);
4384
208
}
4385
4386
static void d68000_roxr_s_32(m68k_info *info)
4387
267
{
4388
267
  build_3bit_d(info, M68K_INS_ROXR, 4);
4389
267
}
4390
4391
static void d68000_roxr_r_8(m68k_info *info)
4392
224
{
4393
224
  build_r(info, M68K_INS_ROXR, 1);
4394
224
}
4395
4396
static void d68000_roxr_r_16(m68k_info *info)
4397
253
{
4398
253
  build_r(info, M68K_INS_ROXR, 2);
4399
253
}
4400
4401
static void d68000_roxr_r_32(m68k_info *info)
4402
216
{
4403
216
  build_r(info, M68K_INS_ROXR, 4);
4404
216
}
4405
4406
static void d68000_roxr_ea(m68k_info *info)
4407
278
{
4408
278
  build_ea(info, M68K_INS_ROXR, 2);
4409
278
}
4410
4411
static void d68000_roxl_s_8(m68k_info *info)
4412
307
{
4413
307
  build_3bit_d(info, M68K_INS_ROXL, 1);
4414
307
}
4415
4416
static void d68000_roxl_s_16(m68k_info *info)
4417
218
{
4418
218
  build_3bit_d(info, M68K_INS_ROXL, 2);
4419
218
}
4420
4421
static void d68000_roxl_s_32(m68k_info *info)
4422
235
{
4423
235
  build_3bit_d(info, M68K_INS_ROXL, 4);
4424
235
}
4425
4426
static void d68000_roxl_r_8(m68k_info *info)
4427
257
{
4428
257
  build_r(info, M68K_INS_ROXL, 1);
4429
257
}
4430
4431
static void d68000_roxl_r_16(m68k_info *info)
4432
291
{
4433
291
  build_r(info, M68K_INS_ROXL, 2);
4434
291
}
4435
4436
static void d68000_roxl_r_32(m68k_info *info)
4437
212
{
4438
212
  build_r(info, M68K_INS_ROXL, 4);
4439
212
}
4440
4441
static void d68000_roxl_ea(m68k_info *info)
4442
303
{
4443
303
  build_ea(info, M68K_INS_ROXL, 2);
4444
303
}
4445
4446
static void d68010_rtd(m68k_info *info)
4447
521
{
4448
521
  set_insn_group(info, M68K_GRP_RET);
4449
521
  LIMIT_FEATURE(info, M68010_PLUS);
4450
259
  build_absolute_jump_with_immediate(info, M68K_INS_RTD, 0,
4451
259
             read_imm_16(info));
4452
259
}
4453
4454
static void d68000_rte(m68k_info *info)
4455
233
{
4456
233
  set_insn_group(info, M68K_GRP_IRET);
4457
233
  MCInst_setOpcode(info->inst, M68K_INS_RTE);
4458
233
}
4459
4460
static void d68020_rtm(m68k_info *info)
4461
200
{
4462
200
  cs_m68k *ext;
4463
200
  cs_m68k_op *op;
4464
4465
200
  set_insn_group(info, M68K_GRP_RET);
4466
4467
200
  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
199
{
4486
199
  set_insn_group(info, M68K_GRP_RET);
4487
199
  MCInst_setOpcode(info->inst, M68K_INS_RTR);
4488
199
}
4489
4490
static void d68000_rts(m68k_info *info)
4491
223
{
4492
223
  set_insn_group(info, M68K_GRP_RET);
4493
223
  MCInst_setOpcode(info->inst, M68K_INS_RTS);
4494
223
}
4495
4496
static void d68000_sbcd_rr(m68k_info *info)
4497
660
{
4498
660
  build_rr(info, M68K_INS_SBCD, 1, 0);
4499
660
}
4500
4501
static void d68000_sbcd_mm(m68k_info *info)
4502
560
{
4503
560
  build_mm(info, M68K_INS_SBCD, 1, 0);
4504
560
}
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
200
{
4518
200
  build_absolute_jump_with_immediate(info, M68K_INS_STOP, 0,
4519
200
             read_imm_16(info));
4520
200
}
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
572
{
5011
572
  build_er_1(info, M68K_INS_SUB, 1);
5012
572
}
5013
5014
static void d68000_sub_er_16(m68k_info *info)
5015
1.34k
{
5016
1.34k
  build_er_1(info, M68K_INS_SUB, 2);
5017
1.34k
}
5018
5019
static void d68000_sub_er_32(m68k_info *info)
5020
1.93k
{
5021
1.93k
  build_er_1(info, M68K_INS_SUB, 4);
5022
1.93k
}
5023
5024
static void d68000_sub_re_8(m68k_info *info)
5025
440
{
5026
440
  build_re_1(info, M68K_INS_SUB, 1);
5027
440
}
5028
5029
static void d68000_sub_re_16(m68k_info *info)
5030
374
{
5031
374
  build_re_1(info, M68K_INS_SUB, 2);
5032
374
}
5033
5034
static void d68000_sub_re_32(m68k_info *info)
5035
2.37k
{
5036
2.37k
  build_re_1(info, M68K_INS_SUB, 4);
5037
2.37k
}
5038
5039
static void d68000_suba_16(m68k_info *info)
5040
396
{
5041
396
  build_ea_a(info, M68K_INS_SUBA, 2);
5042
396
}
5043
5044
static void d68000_suba_32(m68k_info *info)
5045
639
{
5046
639
  build_ea_a(info, M68K_INS_SUBA, 4);
5047
639
}
5048
5049
static void d68000_subi_8(m68k_info *info)
5050
883
{
5051
883
  build_imm_ea(info, M68K_INS_SUBI, 1, read_imm_8(info));
5052
883
}
5053
5054
static void d68000_subi_16(m68k_info *info)
5055
275
{
5056
275
  build_imm_ea(info, M68K_INS_SUBI, 2, read_imm_16(info));
5057
275
}
5058
5059
static void d68000_subi_32(m68k_info *info)
5060
254
{
5061
254
  build_imm_ea(info, M68K_INS_SUBI, 4, read_imm_32(info));
5062
254
}
5063
5064
static void d68000_subq_8(m68k_info *info)
5065
1.40k
{
5066
1.40k
  build_3bit_ea(info, M68K_INS_SUBQ, 1);
5067
1.40k
}
5068
5069
static void d68000_subq_16(m68k_info *info)
5070
2.72k
{
5071
2.72k
  build_3bit_ea(info, M68K_INS_SUBQ, 2);
5072
2.72k
}
5073
5074
static void d68000_subq_32(m68k_info *info)
5075
705
{
5076
705
  build_3bit_ea(info, M68K_INS_SUBQ, 4);
5077
705
}
5078
5079
static void d68000_subx_rr_8(m68k_info *info)
5080
619
{
5081
619
  build_rr(info, M68K_INS_SUBX, 1, 0);
5082
619
}
5083
5084
static void d68000_subx_rr_16(m68k_info *info)
5085
168
{
5086
168
  build_rr(info, M68K_INS_SUBX, 2, 0);
5087
168
}
5088
5089
static void d68000_subx_rr_32(m68k_info *info)
5090
743
{
5091
743
  build_rr(info, M68K_INS_SUBX, 4, 0);
5092
743
}
5093
5094
static void d68000_subx_mm_8(m68k_info *info)
5095
272
{
5096
272
  build_mm(info, M68K_INS_SUBX, 1, 0);
5097
272
}
5098
5099
static void d68000_subx_mm_16(m68k_info *info)
5100
439
{
5101
439
  build_mm(info, M68K_INS_SUBX, 2, 0);
5102
439
}
5103
5104
static void d68000_subx_mm_32(m68k_info *info)
5105
212
{
5106
212
  build_mm(info, M68K_INS_SUBX, 4, 0);
5107
212
}
5108
5109
static void d68000_swap(m68k_info *info)
5110
81
{
5111
81
  build_d(info, M68K_INS_SWAP, 0);
5112
81
}
5113
5114
static void d68000_tas(m68k_info *info)
5115
374
{
5116
374
  build_ea(info, M68K_INS_TAS, 1);
5117
374
}
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
579
{
5127
579
  build_absolute_jump_with_immediate(info, M68K_INS_TRAP, 0,
5128
579
             info->ir & 0xf);
5129
579
}
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
203
{
5183
203
  MCInst_setOpcode(info->inst, M68K_INS_TRAPV);
5184
203
}
5185
5186
static void d68000_tst_8(m68k_info *info)
5187
754
{
5188
754
  build_ea(info, M68K_INS_TST, 1);
5189
754
}
5190
5191
static void d68020_tst_pcdi_8(m68k_info *info)
5192
433
{
5193
433
  LIMIT_FEATURE(info, M68020_PLUS);
5194
210
  build_ea(info, M68K_INS_TST, 1);
5195
210
}
5196
5197
static void d68020_tst_pcix_8(m68k_info *info)
5198
530
{
5199
530
  LIMIT_FEATURE(info, M68020_PLUS);
5200
333
  build_ea(info, M68K_INS_TST, 1);
5201
333
}
5202
5203
static void d68020_tst_i_8(m68k_info *info)
5204
431
{
5205
431
  LIMIT_FEATURE(info, M68020_PLUS);
5206
216
  build_ea(info, M68K_INS_TST, 1);
5207
216
}
5208
5209
static void d68000_tst_16(m68k_info *info)
5210
469
{
5211
469
  build_ea(info, M68K_INS_TST, 2);
5212
469
}
5213
5214
static void d68020_tst_a_16(m68k_info *info)
5215
1.37k
{
5216
1.37k
  LIMIT_FEATURE(info, M68020_PLUS);
5217
1.12k
  build_ea(info, M68K_INS_TST, 2);
5218
1.12k
}
5219
5220
static void d68020_tst_pcdi_16(m68k_info *info)
5221
475
{
5222
475
  LIMIT_FEATURE(info, M68020_PLUS);
5223
265
  build_ea(info, M68K_INS_TST, 2);
5224
265
}
5225
5226
static void d68020_tst_pcix_16(m68k_info *info)
5227
559
{
5228
559
  LIMIT_FEATURE(info, M68020_PLUS);
5229
222
  build_ea(info, M68K_INS_TST, 2);
5230
222
}
5231
5232
static void d68020_tst_i_16(m68k_info *info)
5233
400
{
5234
400
  LIMIT_FEATURE(info, M68020_PLUS);
5235
203
  build_ea(info, M68K_INS_TST, 2);
5236
203
}
5237
5238
static void d68000_tst_32(m68k_info *info)
5239
422
{
5240
422
  build_ea(info, M68K_INS_TST, 4);
5241
422
}
5242
5243
static void d68020_tst_a_32(m68k_info *info)
5244
589
{
5245
589
  LIMIT_FEATURE(info, M68020_PLUS);
5246
378
  build_ea(info, M68K_INS_TST, 4);
5247
378
}
5248
5249
static void d68020_tst_pcdi_32(m68k_info *info)
5250
412
{
5251
412
  LIMIT_FEATURE(info, M68020_PLUS);
5252
208
  build_ea(info, M68K_INS_TST, 4);
5253
208
}
5254
5255
static void d68020_tst_pcix_32(m68k_info *info)
5256
414
{
5257
414
  LIMIT_FEATURE(info, M68020_PLUS);
5258
208
  build_ea(info, M68K_INS_TST, 4);
5259
208
}
5260
5261
static void d68020_tst_i_32(m68k_info *info)
5262
272
{
5263
272
  LIMIT_FEATURE(info, M68020_PLUS);
5264
75
  build_ea(info, M68K_INS_TST, 4);
5265
75
}
5266
5267
static void d68000_unlk(m68k_info *info)
5268
275
{
5269
275
  cs_m68k_op *op;
5270
275
  cs_m68k *ext = build_init_op(info, M68K_INS_UNLK, 1, 0);
5271
5272
275
  op = &ext->operands[0];
5273
5274
275
  op->address_mode = M68K_AM_REG_DIRECT_ADDR;
5275
275
  op->reg = M68K_REG_A0 + (info->ir & 7);
5276
275
}
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
272k
{
5295
272k
  const uint32_t instruction = info->ir;
5296
272k
  const instruction_struct *i = &g_instruction_table[instruction];
5297
5298
272k
  if ((i->word2_mask &&
5299
12.0k
       ((word_check & i->word2_mask) != i->word2_match)) ||
5300
271k
      (i->instruction == d68000_invalid)) {
5301
814
    d68000_invalid(info);
5302
814
    return 0;
5303
814
  }
5304
5305
271k
  return 1;
5306
272k
}
5307
5308
static int exists_reg_list(const uint16_t *regs, uint8_t count, m68k_reg reg)
5309
349k
{
5310
349k
  uint8_t i;
5311
5312
515k
  for (i = 0; i < count; ++i) {
5313
171k
    if (regs[i] == (uint16_t)reg)
5314
5.62k
      return 1;
5315
171k
  }
5316
5317
343k
  return 0;
5318
349k
}
5319
5320
static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write)
5321
357k
{
5322
357k
  if (reg == M68K_REG_INVALID)
5323
8.27k
    return;
5324
5325
349k
  if (write) {
5326
188k
    if (exists_reg_list(info->regs_write, info->regs_write_count,
5327
188k
            reg))
5328
2.75k
      return;
5329
5330
185k
    info->regs_write[info->regs_write_count] = (uint16_t)reg;
5331
185k
    info->regs_write_count++;
5332
185k
  } else {
5333
160k
    if (exists_reg_list(info->regs_read, info->regs_read_count,
5334
160k
            reg))
5335
2.86k
      return;
5336
5337
157k
    info->regs_read[info->regs_read_count] = (uint16_t)reg;
5338
157k
    info->regs_read_count++;
5339
157k
  }
5340
349k
}
5341
5342
static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write)
5343
119k
{
5344
119k
  switch (op->address_mode) {
5345
0
  case M68K_AM_REG_DIRECT_ADDR:
5346
0
  case M68K_AM_REG_DIRECT_DATA:
5347
0
    add_reg_to_rw_list(info, op->reg, write);
5348
0
    break;
5349
5350
19.9k
  case M68K_AM_REGI_ADDR_POST_INC:
5351
51.8k
  case M68K_AM_REGI_ADDR_PRE_DEC:
5352
51.8k
    add_reg_to_rw_list(info, op->mem.base_reg, 1);
5353
51.8k
    break;
5354
5355
24.8k
  case M68K_AM_REGI_ADDR:
5356
41.0k
  case M68K_AM_REGI_ADDR_DISP:
5357
41.0k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5358
41.0k
    break;
5359
5360
9.33k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
5361
11.9k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
5362
13.7k
  case M68K_AM_MEMI_POST_INDEX:
5363
16.0k
  case M68K_AM_MEMI_PRE_INDEX:
5364
17.5k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
5365
17.8k
  case M68K_AM_PCI_INDEX_BASE_DISP:
5366
18.4k
  case M68K_AM_PC_MEMI_PRE_INDEX:
5367
19.0k
  case M68K_AM_PC_MEMI_POST_INDEX:
5368
19.0k
    add_reg_to_rw_list(info, op->mem.index_reg, 0);
5369
19.0k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5370
19.0k
    break;
5371
5372
  // no register(s) in the other addressing modes
5373
7.75k
  default:
5374
7.75k
    break;
5375
119k
  }
5376
119k
}
5377
5378
static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits,
5379
            int write)
5380
16.8k
{
5381
16.8k
  int i;
5382
5383
151k
  for (i = 0; i < 8; ++i) {
5384
134k
    if (bits & (1 << i)) {
5385
31.8k
      add_reg_to_rw_list(info, reg_start + i, write);
5386
31.8k
    }
5387
134k
  }
5388
16.8k
}
5389
5390
static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write)
5391
5.60k
{
5392
5.60k
  uint32_t bits = op->register_bits;
5393
5.60k
  update_bits_range(info, M68K_REG_D0, bits & 0xff, write);
5394
5.60k
  update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write);
5395
5.60k
  update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write);
5396
5.60k
}
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
271k
{
5488
271k
  MCInst *inst = info->inst;
5489
271k
  cs_m68k *ext = &info->extension;
5490
271k
  int i;
5491
271k
  uint32_t size;
5492
5493
271k
  inst->Opcode = M68K_INS_INVALID;
5494
5495
271k
  memset(ext, 0, sizeof(cs_m68k));
5496
271k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
5497
5498
1.89M
  for (i = 0; i < M68K_OPERAND_COUNT; ++i)
5499
1.62M
    ext->operands[i].type = M68K_OP_REG;
5500
5501
271k
  info->ir = peek_imm_16(info);
5502
271k
  if (instruction_is_valid(info, peek_imm_32(info) & 0xffff)) {
5503
270k
    info->ir = read_imm_16(info);
5504
270k
    g_instruction_table[info->ir].instruction(info);
5505
270k
  }
5506
5507
271k
  size = info->pc - pc;
5508
271k
  info->pc = pc;
5509
5510
271k
  return size;
5511
271k
}
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
}