Coverage Report

Created: 2026-07-16 06:55

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