Coverage Report

Created: 2026-08-14 06:51

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
671k
{
56
671k
  const uint16_t v0 = info->code[addr + 0];
57
671k
  const uint16_t v1 = info->code[addr + 1];
58
671k
  return (v0 << 8) | v1;
59
671k
}
60
61
static unsigned int m68k_read_disassembler_32(const m68k_info *info,
62
                const uint64_t addr)
63
296k
{
64
296k
  const uint32_t v0 = info->code[addr + 0];
65
296k
  const uint32_t v1 = info->code[addr + 1];
66
296k
  const uint32_t v2 = info->code[addr + 2];
67
296k
  const uint32_t v3 = info->code[addr + 3];
68
296k
  return (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
69
296k
}
70
71
static uint64_t m68k_read_disassembler_64(const m68k_info *info,
72
            const uint64_t addr)
73
286
{
74
286
  const uint64_t v0 = info->code[addr + 0];
75
286
  const uint64_t v1 = info->code[addr + 1];
76
286
  const uint64_t v2 = info->code[addr + 2];
77
286
  const uint64_t v3 = info->code[addr + 3];
78
286
  const uint64_t v4 = info->code[addr + 4];
79
286
  const uint64_t v5 = info->code[addr + 5];
80
286
  const uint64_t v6 = info->code[addr + 6];
81
286
  const uint64_t v7 = info->code[addr + 7];
82
286
  return (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) |
83
286
         (v5 << 16) | (v6 << 8) | v7;
84
286
}
85
86
static unsigned int m68k_read_safe_16(const m68k_info *info,
87
              const uint64_t address)
88
671k
{
89
671k
  const uint64_t addr = (address - info->baseAddress) &
90
671k
            info->address_mask;
91
671k
  if (info->code_len < addr + 2) {
92
640
    return 0xaaaa;
93
640
  }
94
671k
  return m68k_read_disassembler_16(info, addr);
95
671k
}
96
97
static unsigned int m68k_read_safe_32(const m68k_info *info,
98
              const uint64_t address)
99
298k
{
100
298k
  const uint64_t addr = (address - info->baseAddress) &
101
298k
            info->address_mask;
102
298k
  if (info->code_len < addr + 4) {
103
1.79k
    return 0xaaaaaaaa;
104
1.79k
  }
105
296k
  return m68k_read_disassembler_32(info, addr);
106
298k
}
107
108
static uint64_t m68k_read_safe_64(const m68k_info *info, const uint64_t address)
109
288
{
110
288
  const uint64_t addr = (address - info->baseAddress) &
111
288
            info->address_mask;
112
288
  if (info->code_len < addr + 8) {
113
2
    return 0xaaaaaaaaaaaaaaaaLL;
114
2
  }
115
286
  return m68k_read_disassembler_64(info, addr);
116
288
}
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
18.0k
{
194
18.0k
  return (m68k_read_safe_16((info), (info)->pc) & 0xff);
195
18.0k
}
196
static unsigned int peek_imm_16(const m68k_info *info)
197
653k
{
198
653k
  return m68k_read_safe_16((info), (info)->pc);
199
653k
}
200
static unsigned int peek_imm_32(const m68k_info *info)
201
298k
{
202
298k
  return m68k_read_safe_32((info), (info)->pc);
203
298k
}
204
static unsigned long long peek_imm_64(const m68k_info *info)
205
288
{
206
288
  return m68k_read_safe_64((info), (info)->pc);
207
288
}
208
209
static unsigned int read_imm_8(m68k_info *info)
210
18.0k
{
211
18.0k
  const unsigned int value = peek_imm_8(info);
212
18.0k
  (info)->pc += 2;
213
18.0k
  return value & 0xff;
214
18.0k
}
215
static unsigned int read_imm_16(m68k_info *info)
216
361k
{
217
361k
  const unsigned int value = peek_imm_16(info);
218
361k
  (info)->pc += 2;
219
361k
  return value & 0xffff;
220
361k
}
221
static unsigned int read_imm_32(m68k_info *info)
222
14.1k
{
223
14.1k
  const unsigned int value = peek_imm_32(info);
224
14.1k
  (info)->pc += 4;
225
14.1k
  return value & 0xffffffff;
226
14.1k
}
227
static unsigned long long read_imm_64(m68k_info *info)
228
288
{
229
288
  const unsigned long long value = peek_imm_64(info);
230
288
  (info)->pc += 8;
231
288
  return value & 0xffffffffffffffff;
232
288
}
233
234
/* 100% portable signed int generators */
235
static int make_int_8(int value)
236
19.1k
{
237
19.1k
  return (value & 0x80) ? value | ~0xff : value & 0xff;
238
19.1k
}
239
240
static int make_int_16(int value)
241
4.26k
{
242
4.26k
  return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
243
4.26k
}
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
52.1k
{
608
52.1k
  info->groups[info->groups_count++] = (uint8_t)group;
609
52.1k
}
610
611
static cs_m68k *build_init_op(m68k_info *info, int opcode, int count, int size)
612
279k
{
613
279k
  cs_m68k *ext;
614
615
279k
  MCInst_setOpcode(info->inst, opcode);
616
617
279k
  ext = &info->extension;
618
619
279k
  ext->op_count = (uint8_t)count;
620
279k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
621
279k
  ext->op_size.cpu_size = size;
622
623
279k
  return ext;
624
279k
}
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
21.1k
{
662
21.1k
  build_re_gen_1(info, true, opcode, size);
663
21.1k
}
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
4.46k
{
701
4.46k
  cs_m68k_op *op0;
702
4.46k
  cs_m68k_op *op1;
703
4.46k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
704
705
4.46k
  op0 = &ext->operands[0];
706
4.46k
  op1 = &ext->operands[1];
707
708
4.46k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
709
4.46k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
710
711
4.46k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
712
4.46k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
713
714
4.46k
  if (imm > 0)
715
1.02k
    append_imm_operand(info, imm);
716
4.46k
}
717
718
static void build_r(m68k_info *info, int opcode, uint8_t size)
719
6.15k
{
720
6.15k
  cs_m68k_op *op0;
721
6.15k
  cs_m68k_op *op1;
722
6.15k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
723
724
6.15k
  op0 = &ext->operands[0];
725
6.15k
  op1 = &ext->operands[1];
726
727
6.15k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
728
6.15k
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
729
730
6.15k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
731
6.15k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
732
6.15k
}
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
6.90k
{
756
6.90k
  cs_m68k_op *op0;
757
6.90k
  cs_m68k_op *op1;
758
6.90k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
759
760
6.90k
  op0 = &ext->operands[0];
761
6.90k
  op1 = &ext->operands[1];
762
763
6.90k
  op0->type = M68K_OP_IMM;
764
6.90k
  op0->address_mode = M68K_AM_IMMEDIATE;
765
6.90k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
766
767
6.90k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
768
6.90k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
769
6.90k
}
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
3.69k
{
792
3.69k
  cs_m68k_op *op0;
793
3.69k
  cs_m68k_op *op1;
794
3.69k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
795
796
3.69k
  op0 = &ext->operands[0];
797
3.69k
  op1 = &ext->operands[1];
798
799
3.69k
  op0->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
800
3.69k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
801
802
3.69k
  op1->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
803
3.69k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
804
805
3.69k
  if (imm > 0)
806
875
    append_imm_operand(info, imm);
807
3.69k
}
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
466
{
859
466
  cs_m68k_op *op0;
860
466
  cs_m68k_op *op1;
861
466
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
862
863
466
  op0 = &ext->operands[0];
864
466
  op1 = &ext->operands[1];
865
866
466
  op0->address_mode = M68K_AM_REGI_ADDR_POST_INC;
867
466
  op0->reg = M68K_REG_A0 + (info->ir & 7);
868
869
466
  op1->address_mode = M68K_AM_REGI_ADDR_POST_INC;
870
466
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
871
466
}
872
873
static void build_imm_special_reg(m68k_info *info, int opcode, uint32_t imm,
874
          int size, m68k_reg reg)
875
1.42k
{
876
1.42k
  cs_m68k_op *op0;
877
1.42k
  cs_m68k_op *op1;
878
1.42k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
879
880
1.42k
  op0 = &ext->operands[0];
881
1.42k
  op1 = &ext->operands[1];
882
883
1.42k
  op0->type = M68K_OP_IMM;
884
1.42k
  op0->address_mode = M68K_AM_IMMEDIATE;
885
1.42k
  op0->imm = imm;
886
887
1.42k
  op1->address_mode = M68K_AM_NONE;
888
1.42k
  op1->reg = reg;
889
1.42k
}
890
891
static void build_relative_branch(m68k_info *info, int opcode, int size,
892
          int displacement)
893
21.6k
{
894
21.6k
  cs_m68k_op *op;
895
21.6k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
896
897
21.6k
  op = &ext->operands[0];
898
899
21.6k
  op->type = M68K_OP_BR_DISP;
900
21.6k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
901
21.6k
  op->br_disp.disp = displacement;
902
21.6k
  op->br_disp.disp_size = size;
903
904
21.6k
  set_insn_group(info, M68K_GRP_JUMP);
905
21.6k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
906
21.6k
}
907
908
static void build_absolute_jump_with_immediate(m68k_info *info, int opcode,
909
                 int size, int immediate)
910
1.76k
{
911
1.76k
  cs_m68k_op *op;
912
1.76k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
913
914
1.76k
  op = &ext->operands[0];
915
916
1.76k
  op->type = M68K_OP_IMM;
917
1.76k
  op->address_mode = M68K_AM_IMMEDIATE;
918
1.76k
  op->imm = immediate;
919
920
1.76k
  set_insn_group(info, M68K_GRP_JUMP);
921
1.76k
}
922
923
static void build_bcc(m68k_info *info, int size, int displacement)
924
15.3k
{
925
15.3k
  build_relative_branch(info,
926
15.3k
            s_branch_lut[M68K_IR_CONDITION_NIBBLE(info)],
927
15.3k
            size, displacement);
928
15.3k
}
929
930
static void build_trap(m68k_info *info, int size, int immediate)
931
465
{
932
465
  build_absolute_jump_with_immediate(
933
465
    info, s_trap_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
934
465
    immediate);
935
465
}
936
937
static void build_dbxx(m68k_info *info, int opcode, int size, int displacement)
938
1.06k
{
939
1.06k
  cs_m68k_op *op0;
940
1.06k
  cs_m68k_op *op1;
941
1.06k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
942
943
1.06k
  op0 = &ext->operands[0];
944
1.06k
  op1 = &ext->operands[1];
945
946
1.06k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
947
1.06k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
948
949
1.06k
  op1->type = M68K_OP_BR_DISP;
950
1.06k
  op1->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
951
1.06k
  op1->br_disp.disp = displacement;
952
1.06k
  op1->br_disp.disp_size = M68K_OP_BR_DISP_SIZE_LONG;
953
954
1.06k
  set_insn_group(info, M68K_GRP_JUMP);
955
1.06k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
956
1.06k
}
957
958
static void build_dbcc(m68k_info *info, int size, int displacement)
959
492
{
960
492
  build_dbxx(info, s_dbcc_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
961
492
       displacement);
962
492
}
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.25k
{
1028
1.25k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
1029
1.25k
  cs_m68k_op *op;
1030
1031
1.25k
  op = &ext->operands[0];
1032
1033
1.25k
  op->address_mode = M68K_AM_REG_DIRECT_DATA;
1034
1.25k
  op->reg = M68K_REG_D0 + (info->ir & 7);
1035
1.25k
}
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
562
{
1133
562
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1134
562
  uint32_t s = 16 - 1; // extra shift needed at end
1135
1136
6.53k
  for (v >>= 1; v; v >>= 1) {
1137
5.97k
    r <<= 1;
1138
5.97k
    r |= v & 1;
1139
5.97k
    s--;
1140
5.97k
  }
1141
1142
562
  r <<= s; // shift when v's highest bits are zero
1143
562
  return r;
1144
562
}
1145
1146
static uint8_t reverse_bits_8(uint32_t v)
1147
1.93k
{
1148
1.93k
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1149
1.93k
  uint32_t s = 8 - 1; // extra shift needed at end
1150
1151
13.4k
  for (v >>= 1; v; v >>= 1) {
1152
11.5k
    r <<= 1;
1153
11.5k
    r |= v & 1;
1154
11.5k
    s--;
1155
11.5k
  }
1156
1157
1.93k
  r <<= s; // shift when v's highest bits are zero
1158
1.93k
  return r;
1159
1.93k
}
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
57.0k
{
1202
57.0k
  cs_m68k_op *op;
1203
57.0k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
1204
1205
57.0k
  MCInst_setOpcode(info->inst, opcode);
1206
1207
57.0k
  op = &ext->operands[0];
1208
1209
57.0k
  op->type = M68K_OP_IMM;
1210
57.0k
  op->address_mode = M68K_AM_IMMEDIATE;
1211
57.0k
  op->imm = data;
1212
57.0k
}
1213
1214
static void build_illegal(m68k_info *info, uint32_t data)
1215
87
{
1216
87
  build_imm(info, M68K_INS_ILLEGAL, data);
1217
87
}
1218
1219
static void build_invalid(m68k_info *info, uint32_t data)
1220
57.0k
{
1221
57.0k
  build_imm(info, M68K_INS_INVALID, data);
1222
57.0k
}
1223
1224
static void build_cas2(m68k_info *info, int size)
1225
782
{
1226
782
  uint32_t word3;
1227
782
  uint32_t extension;
1228
782
  cs_m68k_op *op0;
1229
782
  cs_m68k_op *op1;
1230
782
  cs_m68k_op *op2;
1231
782
  cs_m68k *ext = build_init_op(info, M68K_INS_CAS2, 3, size);
1232
782
  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
782
  word3 = peek_imm_32(info) & 0xffff;
1236
782
  if (!instruction_is_valid(info, word3))
1237
376
    return;
1238
1239
406
  op0 = &ext->operands[0];
1240
406
  op1 = &ext->operands[1];
1241
406
  op2 = &ext->operands[2];
1242
1243
406
  extension = read_imm_32(info);
1244
1245
406
  op0->address_mode = M68K_AM_NONE;
1246
406
  op0->type = M68K_OP_REG_PAIR;
1247
406
  op0->reg_pair.reg_0 = ((extension >> 16) & 7) + M68K_REG_D0;
1248
406
  op0->reg_pair.reg_1 = (extension & 7) + M68K_REG_D0;
1249
1250
406
  op1->address_mode = M68K_AM_NONE;
1251
406
  op1->type = M68K_OP_REG_PAIR;
1252
406
  op1->reg_pair.reg_0 = ((extension >> 22) & 7) + M68K_REG_D0;
1253
406
  op1->reg_pair.reg_1 = ((extension >> 6) & 7) + M68K_REG_D0;
1254
1255
406
  reg_0 = (extension >> 28) & 7;
1256
406
  reg_1 = (extension >> 12) & 7;
1257
1258
406
  op2->address_mode = M68K_AM_NONE;
1259
406
  op2->type = M68K_OP_REG_PAIR;
1260
406
  op2->reg_pair.reg_0 = reg_0 + (BIT_1F(extension) ? 8 : 0) + M68K_REG_D0;
1261
406
  op2->reg_pair.reg_1 = reg_1 + (BIT_F(extension) ? 8 : 0) + M68K_REG_D0;
1262
406
}
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.02k
{
1294
2.02k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE16, 2, 0);
1295
2.02k
  int i;
1296
1297
6.06k
  for (i = 0; i < 2; ++i) {
1298
4.04k
    cs_m68k_op *op = &ext->operands[i];
1299
4.04k
    const uint32_t d = data[i];
1300
4.04k
    const uint32_t m = modes[i];
1301
1302
4.04k
    op->type = M68K_OP_MEM;
1303
4.04k
    op->address_mode = m;
1304
1305
4.04k
    if (m == M68K_AM_REGI_ADDR_POST_INC || m == M68K_AM_REGI_ADDR)
1306
3.12k
      op->mem.base_reg = M68K_REG_A0 + d;
1307
922
    else
1308
922
      op->mem.address = d;
1309
4.04k
  }
1310
2.02k
}
1311
1312
static void build_link(m68k_info *info, int disp, int size)
1313
444
{
1314
444
  cs_m68k_op *op0;
1315
444
  cs_m68k_op *op1;
1316
444
  cs_m68k *ext = build_init_op(info, M68K_INS_LINK, 2, size);
1317
1318
444
  op0 = &ext->operands[0];
1319
444
  op1 = &ext->operands[1];
1320
1321
444
  op0->address_mode = M68K_AM_NONE;
1322
444
  op0->reg = M68K_REG_A0 + (info->ir & 7);
1323
1324
444
  op1->address_mode = M68K_AM_IMMEDIATE;
1325
444
  op1->type = M68K_OP_IMM;
1326
444
  op1->imm = disp;
1327
444
}
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.18k
{
1367
1.18k
  cs_m68k_op *op0;
1368
1.18k
  cs_m68k_op *op1;
1369
1.18k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1370
1371
1.18k
  op0 = &ext->operands[0];
1372
1.18k
  op1 = &ext->operands[1];
1373
1374
1.18k
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1375
1376
1.18k
  op1->address_mode = M68K_AM_REGI_ADDR_DISP;
1377
1.18k
  op1->type = M68K_OP_MEM;
1378
1.18k
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1379
1.18k
  op1->mem.disp = (int16_t)read_imm_16(info);
1380
1.18k
}
1381
1382
static void build_movep_er(m68k_info *info, int size)
1383
924
{
1384
924
  cs_m68k_op *op0;
1385
924
  cs_m68k_op *op1;
1386
924
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1387
1388
924
  op0 = &ext->operands[0];
1389
924
  op1 = &ext->operands[1];
1390
1391
924
  op0->address_mode = M68K_AM_REGI_ADDR_DISP;
1392
924
  op0->type = M68K_OP_MEM;
1393
924
  op0->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1394
924
  op0->mem.disp = (int16_t)read_imm_16(info);
1395
1396
924
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1397
924
}
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
26.1k
{
1428
26.1k
  build_er_gen_1(info, true, opcode, size);
1429
26.1k
}
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
57.0k
{
1471
57.0k
  build_invalid(info, info->ir);
1472
57.0k
}
1473
1474
static void d68000_illegal(m68k_info *info)
1475
87
{
1476
87
  build_illegal(info, info->ir);
1477
87
}
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
416
{
2103
416
  build_rr(info, M68K_INS_ABCD, 1, 0);
2104
416
}
2105
2106
static void d68000_abcd_mm(m68k_info *info)
2107
343
{
2108
343
  build_mm(info, M68K_INS_ABCD, 1, 0);
2109
343
}
2110
2111
static void d68000_add_er_8(m68k_info *info)
2112
1.04k
{
2113
1.04k
  build_er_1(info, M68K_INS_ADD, 1);
2114
1.04k
}
2115
2116
static void d68000_add_er_16(m68k_info *info)
2117
628
{
2118
628
  build_er_1(info, M68K_INS_ADD, 2);
2119
628
}
2120
2121
static void d68000_add_er_32(m68k_info *info)
2122
485
{
2123
485
  build_er_1(info, M68K_INS_ADD, 4);
2124
485
}
2125
2126
static void d68000_add_re_8(m68k_info *info)
2127
452
{
2128
452
  build_re_1(info, M68K_INS_ADD, 1);
2129
452
}
2130
2131
static void d68000_add_re_16(m68k_info *info)
2132
300
{
2133
300
  build_re_1(info, M68K_INS_ADD, 2);
2134
300
}
2135
2136
static void d68000_add_re_32(m68k_info *info)
2137
774
{
2138
774
  build_re_1(info, M68K_INS_ADD, 4);
2139
774
}
2140
2141
static void d68000_adda_16(m68k_info *info)
2142
2.64k
{
2143
2.64k
  build_ea_a(info, M68K_INS_ADDA, 2);
2144
2.64k
}
2145
2146
static void d68000_adda_32(m68k_info *info)
2147
1.54k
{
2148
1.54k
  build_ea_a(info, M68K_INS_ADDA, 4);
2149
1.54k
}
2150
2151
static void d68000_addi_8(m68k_info *info)
2152
370
{
2153
370
  build_imm_ea(info, M68K_INS_ADDI, 1, read_imm_8(info));
2154
370
}
2155
2156
static void d68000_addi_16(m68k_info *info)
2157
277
{
2158
277
  build_imm_ea(info, M68K_INS_ADDI, 2, read_imm_16(info));
2159
277
}
2160
2161
static void d68000_addi_32(m68k_info *info)
2162
423
{
2163
423
  build_imm_ea(info, M68K_INS_ADDI, 4, read_imm_32(info));
2164
423
}
2165
2166
static void d68000_addq_8(m68k_info *info)
2167
1.02k
{
2168
1.02k
  build_3bit_ea(info, M68K_INS_ADDQ, 1);
2169
1.02k
}
2170
2171
static void d68000_addq_16(m68k_info *info)
2172
3.77k
{
2173
3.77k
  build_3bit_ea(info, M68K_INS_ADDQ, 2);
2174
3.77k
}
2175
2176
static void d68000_addq_32(m68k_info *info)
2177
403
{
2178
403
  build_3bit_ea(info, M68K_INS_ADDQ, 4);
2179
403
}
2180
2181
static void d68000_addx_rr_8(m68k_info *info)
2182
379
{
2183
379
  build_rr(info, M68K_INS_ADDX, 1, 0);
2184
379
}
2185
2186
static void d68000_addx_rr_16(m68k_info *info)
2187
107
{
2188
107
  build_rr(info, M68K_INS_ADDX, 2, 0);
2189
107
}
2190
2191
static void d68000_addx_rr_32(m68k_info *info)
2192
268
{
2193
268
  build_rr(info, M68K_INS_ADDX, 4, 0);
2194
268
}
2195
2196
static void d68000_addx_mm_8(m68k_info *info)
2197
349
{
2198
349
  build_mm(info, M68K_INS_ADDX, 1, 0);
2199
349
}
2200
2201
static void d68000_addx_mm_16(m68k_info *info)
2202
505
{
2203
505
  build_mm(info, M68K_INS_ADDX, 2, 0);
2204
505
}
2205
2206
static void d68000_addx_mm_32(m68k_info *info)
2207
323
{
2208
323
  build_mm(info, M68K_INS_ADDX, 4, 0);
2209
323
}
2210
2211
static void d68000_and_er_8(m68k_info *info)
2212
892
{
2213
892
  build_er_1(info, M68K_INS_AND, 1);
2214
892
}
2215
2216
static void d68000_and_er_16(m68k_info *info)
2217
859
{
2218
859
  build_er_1(info, M68K_INS_AND, 2);
2219
859
}
2220
2221
static void d68000_and_er_32(m68k_info *info)
2222
505
{
2223
505
  build_er_1(info, M68K_INS_AND, 4);
2224
505
}
2225
2226
static void d68000_and_re_8(m68k_info *info)
2227
518
{
2228
518
  build_re_1(info, M68K_INS_AND, 1);
2229
518
}
2230
2231
static void d68000_and_re_16(m68k_info *info)
2232
1.10k
{
2233
1.10k
  build_re_1(info, M68K_INS_AND, 2);
2234
1.10k
}
2235
2236
static void d68000_and_re_32(m68k_info *info)
2237
778
{
2238
778
  build_re_1(info, M68K_INS_AND, 4);
2239
778
}
2240
2241
static void d68000_andi_8(m68k_info *info)
2242
331
{
2243
331
  build_imm_ea(info, M68K_INS_ANDI, 1, read_imm_8(info));
2244
331
}
2245
2246
static void d68000_andi_16(m68k_info *info)
2247
254
{
2248
254
  build_imm_ea(info, M68K_INS_ANDI, 2, read_imm_16(info));
2249
254
}
2250
2251
static void d68000_andi_32(m68k_info *info)
2252
146
{
2253
146
  build_imm_ea(info, M68K_INS_ANDI, 4, read_imm_32(info));
2254
146
}
2255
2256
static void d68000_andi_to_ccr(m68k_info *info)
2257
230
{
2258
230
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_8(info), 1,
2259
230
            M68K_REG_CCR);
2260
230
}
2261
2262
static void d68000_andi_to_sr(m68k_info *info)
2263
317
{
2264
317
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_16(info), 2,
2265
317
            M68K_REG_SR);
2266
317
}
2267
2268
static void d68000_asr_s_8(m68k_info *info)
2269
386
{
2270
386
  build_3bit_d(info, M68K_INS_ASR, 1);
2271
386
}
2272
2273
static void d68000_asr_s_16(m68k_info *info)
2274
368
{
2275
368
  build_3bit_d(info, M68K_INS_ASR, 2);
2276
368
}
2277
2278
static void d68000_asr_s_32(m68k_info *info)
2279
91
{
2280
91
  build_3bit_d(info, M68K_INS_ASR, 4);
2281
91
}
2282
2283
static void d68000_asr_r_8(m68k_info *info)
2284
456
{
2285
456
  build_r(info, M68K_INS_ASR, 1);
2286
456
}
2287
2288
static void d68000_asr_r_16(m68k_info *info)
2289
258
{
2290
258
  build_r(info, M68K_INS_ASR, 2);
2291
258
}
2292
2293
static void d68000_asr_r_32(m68k_info *info)
2294
327
{
2295
327
  build_r(info, M68K_INS_ASR, 4);
2296
327
}
2297
2298
static void d68000_asr_ea(m68k_info *info)
2299
384
{
2300
384
  build_ea(info, M68K_INS_ASR, 2);
2301
384
}
2302
2303
static void d68000_asl_s_8(m68k_info *info)
2304
1.02k
{
2305
1.02k
  build_3bit_d(info, M68K_INS_ASL, 1);
2306
1.02k
}
2307
2308
static void d68000_asl_s_16(m68k_info *info)
2309
128
{
2310
128
  build_3bit_d(info, M68K_INS_ASL, 2);
2311
128
}
2312
2313
static void d68000_asl_s_32(m68k_info *info)
2314
79
{
2315
79
  build_3bit_d(info, M68K_INS_ASL, 4);
2316
79
}
2317
2318
static void d68000_asl_r_8(m68k_info *info)
2319
495
{
2320
495
  build_r(info, M68K_INS_ASL, 1);
2321
495
}
2322
2323
static void d68000_asl_r_16(m68k_info *info)
2324
676
{
2325
676
  build_r(info, M68K_INS_ASL, 2);
2326
676
}
2327
2328
static void d68000_asl_r_32(m68k_info *info)
2329
201
{
2330
201
  build_r(info, M68K_INS_ASL, 4);
2331
201
}
2332
2333
static void d68000_asl_ea(m68k_info *info)
2334
537
{
2335
537
  build_ea(info, M68K_INS_ASL, 2);
2336
537
}
2337
2338
static void d68000_bcc_8(m68k_info *info)
2339
14.1k
{
2340
14.1k
  build_bcc(info, 1, make_int_8(info->ir));
2341
14.1k
}
2342
2343
static void d68000_bcc_16(m68k_info *info)
2344
677
{
2345
677
  build_bcc(info, 2, make_int_16(read_imm_16(info)));
2346
677
}
2347
2348
static void d68020_bcc_32(m68k_info *info)
2349
774
{
2350
774
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2351
774
            CS_MODE_M68K_CF_ISA_C);
2352
436
  build_bcc(info, 4, read_imm_32(info));
2353
436
}
2354
2355
static void d68000_bchg_r(m68k_info *info)
2356
1.95k
{
2357
1.95k
  build_re_1(info, M68K_INS_BCHG, 1);
2358
1.95k
}
2359
2360
static void d68000_bchg_s(m68k_info *info)
2361
200
{
2362
200
  build_imm_ea(info, M68K_INS_BCHG, 1, read_imm_8(info));
2363
200
}
2364
2365
static void d68000_bclr_r(m68k_info *info)
2366
1.11k
{
2367
1.11k
  build_re_1(info, M68K_INS_BCLR, 1);
2368
1.11k
}
2369
2370
static void d68000_bclr_s(m68k_info *info)
2371
697
{
2372
697
  build_imm_ea(info, M68K_INS_BCLR, 1, read_imm_8(info));
2373
697
}
2374
2375
static void d68010_bkpt(m68k_info *info)
2376
941
{
2377
941
  LIMIT_FEATURE(info, M68010_PLUS);
2378
782
  build_absolute_jump_with_immediate(info, M68K_INS_BKPT, 0,
2379
782
             info->ir & 7);
2380
782
}
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
1.32k
{
2443
1.32k
  build_relative_branch(info, M68K_INS_BRA, 1, make_int_8(info->ir));
2444
1.32k
}
2445
2446
static void d68000_bra_16(m68k_info *info)
2447
772
{
2448
772
  build_relative_branch(info, M68K_INS_BRA, 2,
2449
772
            make_int_16(read_imm_16(info)));
2450
772
}
2451
2452
static void d68020_bra_32(m68k_info *info)
2453
173
{
2454
173
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2455
173
            CS_MODE_M68K_CF_ISA_C);
2456
98
  build_relative_branch(info, M68K_INS_BRA, 4, read_imm_32(info));
2457
98
}
2458
2459
static void d68000_bset_r(m68k_info *info)
2460
1.30k
{
2461
1.30k
  build_re_1(info, M68K_INS_BSET, 1);
2462
1.30k
}
2463
2464
static void d68000_bset_s(m68k_info *info)
2465
305
{
2466
305
  build_imm_ea(info, M68K_INS_BSET, 1, read_imm_8(info));
2467
305
}
2468
2469
static void d68000_bsr_8(m68k_info *info)
2470
3.66k
{
2471
3.66k
  build_relative_branch(info, M68K_INS_BSR, 1, make_int_8(info->ir));
2472
3.66k
}
2473
2474
static void d68000_bsr_16(m68k_info *info)
2475
406
{
2476
406
  build_relative_branch(info, M68K_INS_BSR, 2,
2477
406
            make_int_16(read_imm_16(info)));
2478
406
}
2479
2480
static void d68020_bsr_32(m68k_info *info)
2481
567
{
2482
567
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2483
567
            CS_MODE_M68K_CF_ISA_C);
2484
112
  build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info));
2485
112
}
2486
2487
static void d68000_btst_r(m68k_info *info)
2488
4.34k
{
2489
4.34k
  build_re_1(info, M68K_INS_BTST, 2);
2490
4.34k
  ISIZE = 1;
2491
4.34k
}
2492
2493
static void d68000_btst_s(m68k_info *info)
2494
351
{
2495
351
  build_imm_ea(info, M68K_INS_BTST, 1, read_imm_8(info));
2496
351
}
2497
2498
static void d68020_callm(m68k_info *info)
2499
76
{
2500
76
  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
400
{
2541
400
  build_er_1(info, M68K_INS_CHK, 2);
2542
400
}
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
284
{
2552
284
  LIMIT_FEATURE(info, M68020_PLUS);
2553
237
  build_chk2_cmp2(info, 1);
2554
237
}
2555
2556
static void d68020_chk2_cmp2_16(m68k_info *info)
2557
90
{
2558
90
  LIMIT_FEATURE(info, M68020_PLUS);
2559
30
  build_chk2_cmp2(info, 2);
2560
30
}
2561
2562
static void d68020_chk2_cmp2_32(m68k_info *info)
2563
210
{
2564
210
  LIMIT_FEATURE(info, M68020_PLUS);
2565
146
  build_chk2_cmp2(info, 4);
2566
146
}
2567
2568
static void d68040_cinv(m68k_info *info)
2569
787
{
2570
787
  LIMIT_FEATURE(info, M68040_PLUS);
2571
741
  build_cpush_cinv(info, M68K_INS_CINVL);
2572
741
}
2573
2574
static void d68000_clr_8(m68k_info *info)
2575
157
{
2576
157
  build_ea(info, M68K_INS_CLR, 1);
2577
157
}
2578
2579
static void d68000_clr_16(m68k_info *info)
2580
602
{
2581
602
  build_ea(info, M68K_INS_CLR, 2);
2582
602
}
2583
2584
static void d68000_clr_32(m68k_info *info)
2585
112
{
2586
112
  build_ea(info, M68K_INS_CLR, 4);
2587
112
}
2588
2589
static void d68000_cmp_8(m68k_info *info)
2590
1.28k
{
2591
1.28k
  build_er_1(info, M68K_INS_CMP, 1);
2592
1.28k
}
2593
2594
static void d68000_cmp_16(m68k_info *info)
2595
847
{
2596
847
  build_er_1(info, M68K_INS_CMP, 2);
2597
847
}
2598
2599
static void d68000_cmp_32(m68k_info *info)
2600
1.71k
{
2601
1.71k
  build_er_1(info, M68K_INS_CMP, 4);
2602
1.71k
}
2603
2604
static void d68000_cmpa_16(m68k_info *info)
2605
563
{
2606
563
  build_ea_a(info, M68K_INS_CMPA, 2);
2607
563
}
2608
2609
static void d68000_cmpa_32(m68k_info *info)
2610
801
{
2611
801
  build_ea_a(info, M68K_INS_CMPA, 4);
2612
801
}
2613
2614
static void d68000_cmpi_8(m68k_info *info)
2615
371
{
2616
371
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2617
371
}
2618
2619
static void d68020_cmpi_pcdi_8(m68k_info *info)
2620
158
{
2621
158
  LIMIT_FEATURE(info, M68010_PLUS);
2622
94
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2623
94
}
2624
2625
static void d68020_cmpi_pcix_8(m68k_info *info)
2626
490
{
2627
490
  LIMIT_FEATURE(info, M68010_PLUS);
2628
315
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2629
315
}
2630
2631
static void d68000_cmpi_16(m68k_info *info)
2632
124
{
2633
124
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2634
124
}
2635
2636
static void d68020_cmpi_pcdi_16(m68k_info *info)
2637
223
{
2638
223
  LIMIT_FEATURE(info, M68010_PLUS);
2639
192
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2640
192
}
2641
2642
static void d68020_cmpi_pcix_16(m68k_info *info)
2643
232
{
2644
232
  LIMIT_FEATURE(info, M68010_PLUS);
2645
166
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2646
166
}
2647
2648
static void d68000_cmpi_32(m68k_info *info)
2649
288
{
2650
288
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2651
288
}
2652
2653
static void d68020_cmpi_pcdi_32(m68k_info *info)
2654
490
{
2655
490
  LIMIT_FEATURE(info, M68010_PLUS);
2656
236
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2657
236
}
2658
2659
static void d68020_cmpi_pcix_32(m68k_info *info)
2660
272
{
2661
272
  LIMIT_FEATURE(info, M68010_PLUS);
2662
253
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2663
253
}
2664
2665
static void d68000_cmpm_8(m68k_info *info)
2666
179
{
2667
179
  build_pi_pi(info, M68K_INS_CMPM, 1);
2668
179
}
2669
2670
static void d68000_cmpm_16(m68k_info *info)
2671
187
{
2672
187
  build_pi_pi(info, M68K_INS_CMPM, 2);
2673
187
}
2674
2675
static void d68000_cmpm_32(m68k_info *info)
2676
100
{
2677
100
  build_pi_pi(info, M68K_INS_CMPM, 4);
2678
100
}
2679
2680
static void make_cpbcc_operand(cs_m68k_op *op, int size, int displacement)
2681
2.06k
{
2682
2.06k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
2683
2.06k
  op->type = M68K_OP_BR_DISP;
2684
2.06k
  op->br_disp.disp = displacement;
2685
2.06k
  op->br_disp.disp_size = size;
2686
2.06k
}
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
574
{
3343
574
  build_dbxx(info, M68K_INS_DBRA, 0, make_int_16(read_imm_16(info)));
3344
574
}
3345
3346
static void d68000_dbcc(m68k_info *info)
3347
492
{
3348
492
  build_dbcc(info, 0, make_int_16(read_imm_16(info)));
3349
492
}
3350
3351
static void d68000_divs(m68k_info *info)
3352
1.20k
{
3353
1.20k
  build_er_1(info, M68K_INS_DIVS, 2);
3354
1.20k
}
3355
3356
static void d68000_divu(m68k_info *info)
3357
1.81k
{
3358
1.81k
  build_er_1(info, M68K_INS_DIVU, 2);
3359
1.81k
}
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
478
{
3411
478
  build_re_1(info, M68K_INS_EOR, 1);
3412
478
}
3413
3414
static void d68000_eor_16(m68k_info *info)
3415
577
{
3416
577
  build_re_1(info, M68K_INS_EOR, 2);
3417
577
}
3418
3419
static void d68000_eor_32(m68k_info *info)
3420
760
{
3421
760
  build_re_1(info, M68K_INS_EOR, 4);
3422
760
}
3423
3424
static void d68000_eori_8(m68k_info *info)
3425
262
{
3426
262
  build_imm_ea(info, M68K_INS_EORI, 1, read_imm_8(info));
3427
262
}
3428
3429
static void d68000_eori_16(m68k_info *info)
3430
171
{
3431
171
  build_imm_ea(info, M68K_INS_EORI, 2, read_imm_16(info));
3432
171
}
3433
3434
static void d68000_eori_32(m68k_info *info)
3435
134
{
3436
134
  build_imm_ea(info, M68K_INS_EORI, 4, read_imm_32(info));
3437
134
}
3438
3439
static void d68000_eori_to_ccr(m68k_info *info)
3440
78
{
3441
78
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_8(info), 1,
3442
78
            M68K_REG_CCR);
3443
78
}
3444
3445
static void d68000_eori_to_sr(m68k_info *info)
3446
60
{
3447
60
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_16(info), 2,
3448
60
            M68K_REG_SR);
3449
60
}
3450
3451
static void d68000_exg_dd(m68k_info *info)
3452
592
{
3453
592
  build_r(info, M68K_INS_EXG, 4);
3454
592
}
3455
3456
static void d68000_exg_aa(m68k_info *info)
3457
381
{
3458
381
  cs_m68k_op *op0;
3459
381
  cs_m68k_op *op1;
3460
381
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3461
3462
381
  op0 = &ext->operands[0];
3463
381
  op1 = &ext->operands[1];
3464
3465
381
  op0->address_mode = M68K_AM_NONE;
3466
381
  op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
3467
3468
381
  op1->address_mode = M68K_AM_NONE;
3469
381
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3470
381
}
3471
3472
static void d68000_exg_da(m68k_info *info)
3473
714
{
3474
714
  cs_m68k_op *op0;
3475
714
  cs_m68k_op *op1;
3476
714
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3477
3478
714
  op0 = &ext->operands[0];
3479
714
  op1 = &ext->operands[1];
3480
3481
714
  op0->address_mode = M68K_AM_NONE;
3482
714
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3483
3484
714
  op1->address_mode = M68K_AM_NONE;
3485
714
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3486
714
}
3487
3488
static void d68000_ext_16(m68k_info *info)
3489
481
{
3490
481
  build_d(info, M68K_INS_EXT, 2);
3491
481
}
3492
3493
static void d68000_ext_32(m68k_info *info)
3494
563
{
3495
563
  build_d(info, M68K_INS_EXT, 4);
3496
563
}
3497
3498
static void d68020_extb_32(m68k_info *info)
3499
249
{
3500
249
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
3501
150
  build_d(info, M68K_INS_EXTB, 4);
3502
150
}
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
515
{
3526
515
  build_ea_a(info, M68K_INS_LEA, 4);
3527
515
}
3528
3529
static void d68000_link_16(m68k_info *info)
3530
97
{
3531
97
  build_link(info, read_imm_16(info), 2);
3532
97
}
3533
3534
static void d68020_link_32(m68k_info *info)
3535
525
{
3536
525
  LIMIT_FEATURE(info, M68020_PLUS);
3537
347
  build_link(info, read_imm_32(info), 4);
3538
347
}
3539
3540
static void d68000_lsr_s_8(m68k_info *info)
3541
272
{
3542
272
  build_3bit_d(info, M68K_INS_LSR, 1);
3543
272
}
3544
3545
static void d68000_lsr_s_16(m68k_info *info)
3546
204
{
3547
204
  build_3bit_d(info, M68K_INS_LSR, 2);
3548
204
}
3549
3550
static void d68000_lsr_s_32(m68k_info *info)
3551
370
{
3552
370
  build_3bit_d(info, M68K_INS_LSR, 4);
3553
370
}
3554
3555
static void d68000_lsr_r_8(m68k_info *info)
3556
181
{
3557
181
  build_r(info, M68K_INS_LSR, 1);
3558
181
}
3559
3560
static void d68000_lsr_r_16(m68k_info *info)
3561
368
{
3562
368
  build_r(info, M68K_INS_LSR, 2);
3563
368
}
3564
3565
static void d68000_lsr_r_32(m68k_info *info)
3566
123
{
3567
123
  build_r(info, M68K_INS_LSR, 4);
3568
123
}
3569
3570
static void d68000_lsr_ea(m68k_info *info)
3571
625
{
3572
625
  build_ea(info, M68K_INS_LSR, 2);
3573
625
}
3574
3575
static void d68000_lsl_s_8(m68k_info *info)
3576
124
{
3577
124
  build_3bit_d(info, M68K_INS_LSL, 1);
3578
124
}
3579
3580
static void d68000_lsl_s_16(m68k_info *info)
3581
556
{
3582
556
  build_3bit_d(info, M68K_INS_LSL, 2);
3583
556
}
3584
3585
static void d68000_lsl_s_32(m68k_info *info)
3586
26
{
3587
26
  build_3bit_d(info, M68K_INS_LSL, 4);
3588
26
}
3589
3590
static void d68000_lsl_r_8(m68k_info *info)
3591
96
{
3592
96
  build_r(info, M68K_INS_LSL, 1);
3593
96
}
3594
3595
static void d68000_lsl_r_16(m68k_info *info)
3596
263
{
3597
263
  build_r(info, M68K_INS_LSL, 2);
3598
263
}
3599
3600
static void d68000_lsl_r_32(m68k_info *info)
3601
107
{
3602
107
  build_r(info, M68K_INS_LSL, 4);
3603
107
}
3604
3605
static void d68000_lsl_ea(m68k_info *info)
3606
448
{
3607
448
  build_ea(info, M68K_INS_LSL, 2);
3608
448
}
3609
3610
static void d68000_move_8(m68k_info *info)
3611
6.11k
{
3612
6.11k
  build_ea_ea(info, M68K_INS_MOVE, 1);
3613
6.11k
}
3614
3615
static void d68000_move_16(m68k_info *info)
3616
9.13k
{
3617
9.13k
  build_ea_ea(info, M68K_INS_MOVE, 2);
3618
9.13k
}
3619
3620
static void d68000_move_32(m68k_info *info)
3621
14.9k
{
3622
14.9k
  build_ea_ea(info, M68K_INS_MOVE, 4);
3623
14.9k
}
3624
3625
static void d68000_movea_16(m68k_info *info)
3626
2.03k
{
3627
2.03k
  build_ea_a(info, M68K_INS_MOVEA, 2);
3628
2.03k
}
3629
3630
static void d68000_movea_32(m68k_info *info)
3631
2.03k
{
3632
2.03k
  build_ea_a(info, M68K_INS_MOVEA, 4);
3633
2.03k
}
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
468
{
3866
468
  build_movem_re(info, M68K_INS_MOVEM, 2);
3867
468
}
3868
3869
static void d68000_movem_pd_32(m68k_info *info)
3870
94
{
3871
94
  build_movem_re(info, M68K_INS_MOVEM, 4);
3872
94
}
3873
3874
static void d68000_movem_er_16(m68k_info *info)
3875
831
{
3876
831
  build_movem_er(info, M68K_INS_MOVEM, 2);
3877
831
}
3878
3879
static void d68000_movem_er_32(m68k_info *info)
3880
435
{
3881
435
  build_movem_er(info, M68K_INS_MOVEM, 4);
3882
435
}
3883
3884
static void d68000_movem_re_16(m68k_info *info)
3885
348
{
3886
348
  build_movem_re(info, M68K_INS_MOVEM, 2);
3887
348
}
3888
3889
static void d68000_movem_re_32(m68k_info *info)
3890
567
{
3891
567
  build_movem_re(info, M68K_INS_MOVEM, 4);
3892
567
}
3893
3894
static void d68000_movep_re_16(m68k_info *info)
3895
434
{
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
434
  build_movep_re(info, 2);
3901
434
}
3902
3903
static void d68000_movep_re_32(m68k_info *info)
3904
749
{
3905
749
  build_movep_re(info, 4);
3906
749
}
3907
3908
static void d68000_movep_er_16(m68k_info *info)
3909
621
{
3910
621
  build_movep_er(info, 2);
3911
621
}
3912
3913
static void d68000_movep_er_32(m68k_info *info)
3914
303
{
3915
303
  build_movep_er(info, 4);
3916
303
}
3917
3918
static void d68010_moves_8(m68k_info *info)
3919
520
{
3920
520
  LIMIT_FEATURE(info, M68010_PLUS);
3921
253
  build_moves(info, 1);
3922
253
}
3923
3924
static void d68010_moves_16(m68k_info *info)
3925
304
{
3926
  //uint32_t extension;
3927
304
  LIMIT_FEATURE(info, M68010_PLUS);
3928
175
  build_moves(info, 2);
3929
175
}
3930
3931
static void d68010_moves_32(m68k_info *info)
3932
75
{
3933
75
  LIMIT_FEATURE(info, M68010_PLUS);
3934
57
  build_moves(info, 4);
3935
57
}
3936
3937
static void d68000_moveq(m68k_info *info)
3938
8.80k
{
3939
8.80k
  cs_m68k_op *op0;
3940
8.80k
  cs_m68k_op *op1;
3941
3942
8.80k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEQ, 2, 0);
3943
3944
8.80k
  op0 = &ext->operands[0];
3945
8.80k
  op1 = &ext->operands[1];
3946
3947
8.80k
  op0->type = M68K_OP_IMM;
3948
8.80k
  op0->address_mode = M68K_AM_IMMEDIATE;
3949
8.80k
  op0->imm = (info->ir & 0xff);
3950
3951
8.80k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
3952
8.80k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3953
8.80k
}
3954
3955
static void d68040_move16_pi_pi(m68k_info *info)
3956
1.14k
{
3957
1.14k
  uint32_t data[] = { info->ir & 7, (read_imm_16(info) >> 12) & 7 };
3958
1.14k
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
3959
1.14k
           M68K_AM_REGI_ADDR_POST_INC };
3960
3961
1.14k
  LIMIT_FEATURE(info, M68040_PLUS);
3962
3963
1.09k
  build_move16(info, data, modes);
3964
1.09k
}
3965
3966
static void d68040_move16_pi_al(m68k_info *info)
3967
202
{
3968
202
  uint32_t data[2];
3969
202
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
3970
202
           M68K_AM_ABSOLUTE_DATA_LONG };
3971
3972
202
  LIMIT_FEATURE(info, M68040_PLUS);
3973
3974
92
  data[0] = info->ir & 7;
3975
92
  data[1] = read_imm_32(info);
3976
92
  build_move16(info, data, modes);
3977
92
}
3978
3979
static void d68040_move16_al_pi(m68k_info *info)
3980
479
{
3981
479
  uint32_t data[2];
3982
479
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG,
3983
479
           M68K_AM_REGI_ADDR_POST_INC };
3984
3985
479
  LIMIT_FEATURE(info, M68040_PLUS);
3986
3987
273
  data[0] = read_imm_32(info);
3988
273
  data[1] = info->ir & 7;
3989
273
  build_move16(info, data, modes);
3990
273
}
3991
3992
static void d68040_move16_ai_al(m68k_info *info)
3993
735
{
3994
735
  uint32_t data[2];
3995
735
  uint32_t modes[] = { M68K_AM_REGI_ADDR, M68K_AM_ABSOLUTE_DATA_LONG };
3996
3997
735
  LIMIT_FEATURE(info, M68040_PLUS);
3998
3999
343
  data[0] = info->ir & 7;
4000
343
  data[1] = read_imm_32(info);
4001
343
  build_move16(info, data, modes);
4002
343
}
4003
4004
static void d68040_move16_al_ai(m68k_info *info)
4005
408
{
4006
408
  uint32_t data[2];
4007
408
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REGI_ADDR };
4008
4009
408
  LIMIT_FEATURE(info, M68040_PLUS);
4010
4011
214
  data[0] = read_imm_32(info);
4012
214
  data[1] = info->ir & 7;
4013
214
  build_move16(info, data, modes);
4014
214
}
4015
4016
static void d68000_muls(m68k_info *info)
4017
4.25k
{
4018
4.25k
  build_er_1(info, M68K_INS_MULS, 2);
4019
4.25k
}
4020
4021
static void d68000_mulu(m68k_info *info)
4022
1.53k
{
4023
1.53k
  build_er_1(info, M68K_INS_MULU, 2);
4024
1.53k
}
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
201
{
4071
201
  build_ea(info, M68K_INS_NBCD, 1);
4072
201
}
4073
4074
static void d68000_neg_8(m68k_info *info)
4075
219
{
4076
219
  build_ea(info, M68K_INS_NEG, 1);
4077
219
}
4078
4079
static void d68000_neg_16(m68k_info *info)
4080
739
{
4081
739
  build_ea(info, M68K_INS_NEG, 2);
4082
739
}
4083
4084
static void d68000_neg_32(m68k_info *info)
4085
335
{
4086
335
  build_ea(info, M68K_INS_NEG, 4);
4087
335
}
4088
4089
static void d68000_negx_8(m68k_info *info)
4090
842
{
4091
842
  build_ea(info, M68K_INS_NEGX, 1);
4092
842
}
4093
4094
static void d68000_negx_16(m68k_info *info)
4095
436
{
4096
436
  build_ea(info, M68K_INS_NEGX, 2);
4097
436
}
4098
4099
static void d68000_negx_32(m68k_info *info)
4100
577
{
4101
577
  build_ea(info, M68K_INS_NEGX, 4);
4102
577
}
4103
4104
static void d68000_nop(m68k_info *info)
4105
74
{
4106
74
  MCInst_setOpcode(info->inst, M68K_INS_NOP);
4107
74
}
4108
4109
static void d68000_not_8(m68k_info *info)
4110
294
{
4111
294
  build_ea(info, M68K_INS_NOT, 1);
4112
294
}
4113
4114
static void d68000_not_16(m68k_info *info)
4115
524
{
4116
524
  build_ea(info, M68K_INS_NOT, 2);
4117
524
}
4118
4119
static void d68000_not_32(m68k_info *info)
4120
609
{
4121
609
  build_ea(info, M68K_INS_NOT, 4);
4122
609
}
4123
4124
static void d68000_or_er_8(m68k_info *info)
4125
1.15k
{
4126
1.15k
  build_er_1(info, M68K_INS_OR, 1);
4127
1.15k
}
4128
4129
static void d68000_or_er_16(m68k_info *info)
4130
570
{
4131
570
  build_er_1(info, M68K_INS_OR, 2);
4132
570
}
4133
4134
static void d68000_or_er_32(m68k_info *info)
4135
945
{
4136
945
  build_er_1(info, M68K_INS_OR, 4);
4137
945
}
4138
4139
static void d68000_or_re_8(m68k_info *info)
4140
918
{
4141
918
  build_re_1(info, M68K_INS_OR, 1);
4142
918
}
4143
4144
static void d68000_or_re_16(m68k_info *info)
4145
1.53k
{
4146
1.53k
  build_re_1(info, M68K_INS_OR, 2);
4147
1.53k
}
4148
4149
static void d68000_or_re_32(m68k_info *info)
4150
596
{
4151
596
  build_re_1(info, M68K_INS_OR, 4);
4152
596
}
4153
4154
static void d68000_ori_8(m68k_info *info)
4155
12.2k
{
4156
12.2k
  build_imm_ea(info, M68K_INS_ORI, 1, read_imm_8(info));
4157
12.2k
}
4158
4159
static void d68000_ori_16(m68k_info *info)
4160
1.32k
{
4161
1.32k
  build_imm_ea(info, M68K_INS_ORI, 2, read_imm_16(info));
4162
1.32k
}
4163
4164
static void d68000_ori_32(m68k_info *info)
4165
1.08k
{
4166
1.08k
  build_imm_ea(info, M68K_INS_ORI, 4, read_imm_32(info));
4167
1.08k
}
4168
4169
static void d68000_ori_to_ccr(m68k_info *info)
4170
503
{
4171
503
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_8(info), 1,
4172
503
            M68K_REG_CCR);
4173
503
}
4174
4175
static void d68000_ori_to_sr(m68k_info *info)
4176
236
{
4177
236
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_16(info), 2,
4178
236
            M68K_REG_SR);
4179
236
}
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
117
{
4195
117
  build_ea(info, M68K_INS_PEA, 4);
4196
117
}
4197
4198
static void d68000_reset(m68k_info *info)
4199
27
{
4200
27
  MCInst_setOpcode(info->inst, M68K_INS_RESET);
4201
27
}
4202
4203
static void d68000_ror_s_8(m68k_info *info)
4204
682
{
4205
682
  build_3bit_d(info, M68K_INS_ROR, 1);
4206
682
}
4207
4208
static void d68000_ror_s_16(m68k_info *info)
4209
164
{
4210
164
  build_3bit_d(info, M68K_INS_ROR, 2);
4211
164
}
4212
4213
static void d68000_ror_s_32(m68k_info *info)
4214
295
{
4215
295
  build_3bit_d(info, M68K_INS_ROR, 4);
4216
295
}
4217
4218
static void d68000_ror_r_8(m68k_info *info)
4219
74
{
4220
74
  build_r(info, M68K_INS_ROR, 1);
4221
74
}
4222
4223
static void d68000_ror_r_16(m68k_info *info)
4224
208
{
4225
208
  build_r(info, M68K_INS_ROR, 2);
4226
208
}
4227
4228
static void d68000_ror_r_32(m68k_info *info)
4229
106
{
4230
106
  build_r(info, M68K_INS_ROR, 4);
4231
106
}
4232
4233
static void d68000_ror_ea(m68k_info *info)
4234
444
{
4235
444
  build_ea(info, M68K_INS_ROR, 2);
4236
444
}
4237
4238
static void d68000_rol_s_8(m68k_info *info)
4239
998
{
4240
998
  build_3bit_d(info, M68K_INS_ROL, 1);
4241
998
}
4242
4243
static void d68000_rol_s_16(m68k_info *info)
4244
122
{
4245
122
  build_3bit_d(info, M68K_INS_ROL, 2);
4246
122
}
4247
4248
static void d68000_rol_s_32(m68k_info *info)
4249
245
{
4250
245
  build_3bit_d(info, M68K_INS_ROL, 4);
4251
245
}
4252
4253
static void d68000_rol_r_8(m68k_info *info)
4254
91
{
4255
91
  build_r(info, M68K_INS_ROL, 1);
4256
91
}
4257
4258
static void d68000_rol_r_16(m68k_info *info)
4259
540
{
4260
540
  build_r(info, M68K_INS_ROL, 2);
4261
540
}
4262
4263
static void d68000_rol_r_32(m68k_info *info)
4264
119
{
4265
119
  build_r(info, M68K_INS_ROL, 4);
4266
119
}
4267
4268
static void d68000_rol_ea(m68k_info *info)
4269
654
{
4270
654
  build_ea(info, M68K_INS_ROL, 2);
4271
654
}
4272
4273
static void d68000_roxr_s_8(m68k_info *info)
4274
192
{
4275
192
  build_3bit_d(info, M68K_INS_ROXR, 1);
4276
192
}
4277
4278
static void d68000_roxr_s_16(m68k_info *info)
4279
80
{
4280
80
  build_3bit_d(info, M68K_INS_ROXR, 2);
4281
80
}
4282
4283
static void d68000_roxr_s_32(m68k_info *info)
4284
36
{
4285
36
  build_3bit_d(info, M68K_INS_ROXR, 4);
4286
36
}
4287
4288
static void d68000_roxr_r_8(m68k_info *info)
4289
118
{
4290
118
  build_r(info, M68K_INS_ROXR, 1);
4291
118
}
4292
4293
static void d68000_roxr_r_16(m68k_info *info)
4294
113
{
4295
113
  build_r(info, M68K_INS_ROXR, 2);
4296
113
}
4297
4298
static void d68000_roxr_r_32(m68k_info *info)
4299
121
{
4300
121
  build_r(info, M68K_INS_ROXR, 4);
4301
121
}
4302
4303
static void d68000_roxr_ea(m68k_info *info)
4304
242
{
4305
242
  build_ea(info, M68K_INS_ROXR, 2);
4306
242
}
4307
4308
static void d68000_roxl_s_8(m68k_info *info)
4309
332
{
4310
332
  build_3bit_d(info, M68K_INS_ROXL, 1);
4311
332
}
4312
4313
static void d68000_roxl_s_16(m68k_info *info)
4314
88
{
4315
88
  build_3bit_d(info, M68K_INS_ROXL, 2);
4316
88
}
4317
4318
static void d68000_roxl_s_32(m68k_info *info)
4319
43
{
4320
43
  build_3bit_d(info, M68K_INS_ROXL, 4);
4321
43
}
4322
4323
static void d68000_roxl_r_8(m68k_info *info)
4324
133
{
4325
133
  build_r(info, M68K_INS_ROXL, 1);
4326
133
}
4327
4328
static void d68000_roxl_r_16(m68k_info *info)
4329
334
{
4330
334
  build_r(info, M68K_INS_ROXL, 2);
4331
334
}
4332
4333
static void d68000_roxl_r_32(m68k_info *info)
4334
51
{
4335
51
  build_r(info, M68K_INS_ROXL, 4);
4336
51
}
4337
4338
static void d68000_roxl_ea(m68k_info *info)
4339
426
{
4340
426
  build_ea(info, M68K_INS_ROXL, 2);
4341
426
}
4342
4343
static void d68010_rtd(m68k_info *info)
4344
197
{
4345
197
  set_insn_group(info, M68K_GRP_RET);
4346
197
  LIMIT_FEATURE(info, M68010_PLUS);
4347
109
  build_absolute_jump_with_immediate(info, M68K_INS_RTD, 0,
4348
109
             read_imm_16(info));
4349
109
}
4350
4351
static void d68000_rte(m68k_info *info)
4352
78
{
4353
78
  set_insn_group(info, M68K_GRP_IRET);
4354
78
  MCInst_setOpcode(info->inst, M68K_INS_RTE);
4355
78
}
4356
4357
static void d68020_rtm(m68k_info *info)
4358
59
{
4359
59
  cs_m68k *ext;
4360
59
  cs_m68k_op *op;
4361
4362
59
  set_insn_group(info, M68K_GRP_RET);
4363
4364
59
  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
36
{
4383
36
  set_insn_group(info, M68K_GRP_RET);
4384
36
  MCInst_setOpcode(info->inst, M68K_INS_RTR);
4385
36
}
4386
4387
static void d68000_rts(m68k_info *info)
4388
67
{
4389
67
  set_insn_group(info, M68K_GRP_RET);
4390
67
  MCInst_setOpcode(info->inst, M68K_INS_RTS);
4391
67
}
4392
4393
static void d68000_sbcd_rr(m68k_info *info)
4394
401
{
4395
401
  build_rr(info, M68K_INS_SBCD, 1, 0);
4396
401
}
4397
4398
static void d68000_sbcd_mm(m68k_info *info)
4399
709
{
4400
709
  build_mm(info, M68K_INS_SBCD, 1, 0);
4401
709
}
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
98
{
4415
98
  build_absolute_jump_with_immediate(info, M68K_INS_STOP, 0,
4416
98
             read_imm_16(info));
4417
98
}
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
769
{
4908
769
  build_er_1(info, M68K_INS_SUB, 1);
4909
769
}
4910
4911
static void d68000_sub_er_16(m68k_info *info)
4912
753
{
4913
753
  build_er_1(info, M68K_INS_SUB, 2);
4914
753
}
4915
4916
static void d68000_sub_er_32(m68k_info *info)
4917
3.88k
{
4918
3.88k
  build_er_1(info, M68K_INS_SUB, 4);
4919
3.88k
}
4920
4921
static void d68000_sub_re_8(m68k_info *info)
4922
432
{
4923
432
  build_re_1(info, M68K_INS_SUB, 1);
4924
432
}
4925
4926
static void d68000_sub_re_16(m68k_info *info)
4927
842
{
4928
842
  build_re_1(info, M68K_INS_SUB, 2);
4929
842
}
4930
4931
static void d68000_sub_re_32(m68k_info *info)
4932
2.32k
{
4933
2.32k
  build_re_1(info, M68K_INS_SUB, 4);
4934
2.32k
}
4935
4936
static void d68000_suba_16(m68k_info *info)
4937
1.60k
{
4938
1.60k
  build_ea_a(info, M68K_INS_SUBA, 2);
4939
1.60k
}
4940
4941
static void d68000_suba_32(m68k_info *info)
4942
807
{
4943
807
  build_ea_a(info, M68K_INS_SUBA, 4);
4944
807
}
4945
4946
static void d68000_subi_8(m68k_info *info)
4947
1.17k
{
4948
1.17k
  build_imm_ea(info, M68K_INS_SUBI, 1, read_imm_8(info));
4949
1.17k
}
4950
4951
static void d68000_subi_16(m68k_info *info)
4952
103
{
4953
103
  build_imm_ea(info, M68K_INS_SUBI, 2, read_imm_16(info));
4954
103
}
4955
4956
static void d68000_subi_32(m68k_info *info)
4957
198
{
4958
198
  build_imm_ea(info, M68K_INS_SUBI, 4, read_imm_32(info));
4959
198
}
4960
4961
static void d68000_subq_8(m68k_info *info)
4962
1.40k
{
4963
1.40k
  build_3bit_ea(info, M68K_INS_SUBQ, 1);
4964
1.40k
}
4965
4966
static void d68000_subq_16(m68k_info *info)
4967
2.68k
{
4968
2.68k
  build_3bit_ea(info, M68K_INS_SUBQ, 2);
4969
2.68k
}
4970
4971
static void d68000_subq_32(m68k_info *info)
4972
959
{
4973
959
  build_3bit_ea(info, M68K_INS_SUBQ, 4);
4974
959
}
4975
4976
static void d68000_subx_rr_8(m68k_info *info)
4977
474
{
4978
474
  build_rr(info, M68K_INS_SUBX, 1, 0);
4979
474
}
4980
4981
static void d68000_subx_rr_16(m68k_info *info)
4982
123
{
4983
123
  build_rr(info, M68K_INS_SUBX, 2, 0);
4984
123
}
4985
4986
static void d68000_subx_rr_32(m68k_info *info)
4987
882
{
4988
882
  build_rr(info, M68K_INS_SUBX, 4, 0);
4989
882
}
4990
4991
static void d68000_subx_mm_8(m68k_info *info)
4992
173
{
4993
173
  build_mm(info, M68K_INS_SUBX, 1, 0);
4994
173
}
4995
4996
static void d68000_subx_mm_16(m68k_info *info)
4997
180
{
4998
180
  build_mm(info, M68K_INS_SUBX, 2, 0);
4999
180
}
5000
5001
static void d68000_subx_mm_32(m68k_info *info)
5002
107
{
5003
107
  build_mm(info, M68K_INS_SUBX, 4, 0);
5004
107
}
5005
5006
static void d68000_swap(m68k_info *info)
5007
59
{
5008
59
  build_d(info, M68K_INS_SWAP, 0);
5009
59
}
5010
5011
static void d68000_tas(m68k_info *info)
5012
190
{
5013
190
  build_ea(info, M68K_INS_TAS, 1);
5014
190
}
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
306
{
5024
306
  build_absolute_jump_with_immediate(info, M68K_INS_TRAP, 0,
5025
306
             info->ir & 0xf);
5026
306
}
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
193
{
5080
193
  MCInst_setOpcode(info->inst, M68K_INS_TRAPV);
5081
193
}
5082
5083
static void d68000_tst_8(m68k_info *info)
5084
753
{
5085
753
  build_ea(info, M68K_INS_TST, 1);
5086
753
}
5087
5088
static void d68020_tst_pcdi_8(m68k_info *info)
5089
304
{
5090
304
  LIMIT_FEATURE(info, M68020_PLUS);
5091
85
  build_ea(info, M68K_INS_TST, 1);
5092
85
}
5093
5094
static void d68020_tst_pcix_8(m68k_info *info)
5095
607
{
5096
607
  LIMIT_FEATURE(info, M68020_PLUS);
5097
349
  build_ea(info, M68K_INS_TST, 1);
5098
349
}
5099
5100
static void d68020_tst_i_8(m68k_info *info)
5101
352
{
5102
352
  LIMIT_FEATURE(info, M68020_PLUS);
5103
221
  build_ea(info, M68K_INS_TST, 1);
5104
221
}
5105
5106
static void d68000_tst_16(m68k_info *info)
5107
234
{
5108
234
  build_ea(info, M68K_INS_TST, 2);
5109
234
}
5110
5111
static void d68020_tst_a_16(m68k_info *info)
5112
1.59k
{
5113
1.59k
  LIMIT_FEATURE(info, M68020_PLUS);
5114
1.15k
  build_ea(info, M68K_INS_TST, 2);
5115
1.15k
}
5116
5117
static void d68020_tst_pcdi_16(m68k_info *info)
5118
214
{
5119
214
  LIMIT_FEATURE(info, M68020_PLUS);
5120
142
  build_ea(info, M68K_INS_TST, 2);
5121
142
}
5122
5123
static void d68020_tst_pcix_16(m68k_info *info)
5124
341
{
5125
341
  LIMIT_FEATURE(info, M68020_PLUS);
5126
214
  build_ea(info, M68K_INS_TST, 2);
5127
214
}
5128
5129
static void d68020_tst_i_16(m68k_info *info)
5130
613
{
5131
613
  LIMIT_FEATURE(info, M68020_PLUS);
5132
88
  build_ea(info, M68K_INS_TST, 2);
5133
88
}
5134
5135
static void d68000_tst_32(m68k_info *info)
5136
440
{
5137
440
  build_ea(info, M68K_INS_TST, 4);
5138
440
}
5139
5140
static void d68020_tst_a_32(m68k_info *info)
5141
722
{
5142
722
  LIMIT_FEATURE(info, M68020_PLUS);
5143
555
  build_ea(info, M68K_INS_TST, 4);
5144
555
}
5145
5146
static void d68020_tst_pcdi_32(m68k_info *info)
5147
240
{
5148
240
  LIMIT_FEATURE(info, M68020_PLUS);
5149
152
  build_ea(info, M68K_INS_TST, 4);
5150
152
}
5151
5152
static void d68020_tst_pcix_32(m68k_info *info)
5153
87
{
5154
87
  LIMIT_FEATURE(info, M68020_PLUS);
5155
12
  build_ea(info, M68K_INS_TST, 4);
5156
12
}
5157
5158
static void d68020_tst_i_32(m68k_info *info)
5159
95
{
5160
95
  LIMIT_FEATURE(info, M68020_PLUS);
5161
58
  build_ea(info, M68K_INS_TST, 4);
5162
58
}
5163
5164
static void d68000_unlk(m68k_info *info)
5165
167
{
5166
167
  cs_m68k_op *op;
5167
167
  cs_m68k *ext = build_init_op(info, M68K_INS_UNLK, 1, 0);
5168
5169
167
  op = &ext->operands[0];
5170
5171
167
  op->address_mode = M68K_AM_REG_DIRECT_ADDR;
5172
167
  op->reg = M68K_REG_A0 + (info->ir & 7);
5173
167
}
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
284k
{
5192
284k
  const uint32_t instruction = info->ir;
5193
284k
  const instruction_struct *i = &g_instruction_table[instruction];
5194
5195
284k
  if ((i->word2_mask &&
5196
8.77k
       ((word_check & i->word2_mask) != i->word2_match)) ||
5197
283k
      (i->instruction == d68000_invalid)) {
5198
1.29k
    d68000_invalid(info);
5199
1.29k
    return 0;
5200
1.29k
  }
5201
5202
282k
  return 1;
5203
284k
}
5204
5205
static int exists_reg_list(const uint16_t *regs, uint8_t count, m68k_reg reg)
5206
355k
{
5207
355k
  uint8_t i;
5208
5209
530k
  for (i = 0; i < count; ++i) {
5210
179k
    if (regs[i] == (uint16_t)reg)
5211
4.64k
      return 1;
5212
179k
  }
5213
5214
351k
  return 0;
5215
355k
}
5216
5217
static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write)
5218
366k
{
5219
366k
  if (reg == M68K_REG_INVALID)
5220
10.5k
    return;
5221
5222
355k
  if (write) {
5223
195k
    if (exists_reg_list(info->regs_write, info->regs_write_count,
5224
195k
            reg))
5225
2.49k
      return;
5226
5227
192k
    info->regs_write[info->regs_write_count] = (uint16_t)reg;
5228
192k
    info->regs_write_count++;
5229
192k
  } else {
5230
160k
    if (exists_reg_list(info->regs_read, info->regs_read_count,
5231
160k
            reg))
5232
2.15k
      return;
5233
5234
158k
    info->regs_read[info->regs_read_count] = (uint16_t)reg;
5235
158k
    info->regs_read_count++;
5236
158k
  }
5237
355k
}
5238
5239
static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write)
5240
131k
{
5241
131k
  switch (op->address_mode) {
5242
0
  case M68K_AM_REG_DIRECT_ADDR:
5243
0
  case M68K_AM_REG_DIRECT_DATA:
5244
0
    add_reg_to_rw_list(info, op->reg, write);
5245
0
    break;
5246
5247
24.5k
  case M68K_AM_REGI_ADDR_POST_INC:
5248
57.0k
  case M68K_AM_REGI_ADDR_PRE_DEC:
5249
57.0k
    add_reg_to_rw_list(info, op->mem.base_reg, 1);
5250
57.0k
    break;
5251
5252
25.7k
  case M68K_AM_REGI_ADDR:
5253
43.7k
  case M68K_AM_REGI_ADDR_DISP:
5254
43.7k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5255
43.7k
    break;
5256
5257
12.1k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
5258
15.1k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
5259
17.7k
  case M68K_AM_MEMI_POST_INDEX:
5260
20.0k
  case M68K_AM_MEMI_PRE_INDEX:
5261
21.5k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
5262
21.9k
  case M68K_AM_PCI_INDEX_BASE_DISP:
5263
22.5k
  case M68K_AM_PC_MEMI_PRE_INDEX:
5264
22.9k
  case M68K_AM_PC_MEMI_POST_INDEX:
5265
22.9k
    add_reg_to_rw_list(info, op->mem.index_reg, 0);
5266
22.9k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5267
22.9k
    break;
5268
5269
  // no register(s) in the other addressing modes
5270
7.38k
  default:
5271
7.38k
    break;
5272
131k
  }
5273
131k
}
5274
5275
static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits,
5276
            int write)
5277
14.2k
{
5278
14.2k
  int i;
5279
5280
127k
  for (i = 0; i < 8; ++i) {
5281
113k
    if (bits & (1 << i)) {
5282
30.4k
      add_reg_to_rw_list(info, reg_start + i, write);
5283
30.4k
    }
5284
113k
  }
5285
14.2k
}
5286
5287
static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write)
5288
4.73k
{
5289
4.73k
  uint32_t bits = op->register_bits;
5290
4.73k
  update_bits_range(info, M68K_REG_D0, bits & 0xff, write);
5291
4.73k
  update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write);
5292
4.73k
  update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write);
5293
4.73k
}
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
283k
{
5366
283k
  MCInst *inst = info->inst;
5367
283k
  cs_m68k *ext = &info->extension;
5368
283k
  int i;
5369
283k
  uint32_t size;
5370
5371
283k
  inst->Opcode = M68K_INS_INVALID;
5372
5373
283k
  memset(ext, 0, sizeof(cs_m68k));
5374
283k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
5375
5376
1.98M
  for (i = 0; i < M68K_OPERAND_COUNT; ++i)
5377
1.70M
    ext->operands[i].type = M68K_OP_REG;
5378
5379
283k
  info->ir = peek_imm_16(info);
5380
283k
  if (instruction_is_valid(info, peek_imm_32(info) & 0xffff)) {
5381
282k
    info->ir = read_imm_16(info);
5382
282k
    g_instruction_table[info->ir].instruction(info);
5383
282k
  }
5384
5385
283k
  size = info->pc - pc;
5386
283k
  info->pc = pc;
5387
5388
283k
  return size;
5389
283k
}
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
}