Coverage Report

Created: 2026-09-03 07:09

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