Coverage Report

Created: 2026-08-13 06:59

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