Coverage Report

Created: 2026-06-15 06:41

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