Coverage Report

Created: 2026-08-31 06:58

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