Coverage Report

Created: 2026-08-31 06:58

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