Coverage Report

Created: 2026-09-28 06:34

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