Coverage Report

Created: 2026-05-30 06:22

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
457k
{
56
457k
  const uint16_t v0 = info->code[addr + 0];
57
457k
  const uint16_t v1 = info->code[addr + 1];
58
457k
  return (v0 << 8) | v1;
59
457k
}
60
61
static unsigned int m68k_read_disassembler_32(const m68k_info *info,
62
                const uint64_t addr)
63
200k
{
64
200k
  const uint32_t v0 = info->code[addr + 0];
65
200k
  const uint32_t v1 = info->code[addr + 1];
66
200k
  const uint32_t v2 = info->code[addr + 2];
67
200k
  const uint32_t v3 = info->code[addr + 3];
68
200k
  return (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
69
200k
}
70
71
static uint64_t m68k_read_disassembler_64(const m68k_info *info,
72
            const uint64_t addr)
73
156
{
74
156
  const uint64_t v0 = info->code[addr + 0];
75
156
  const uint64_t v1 = info->code[addr + 1];
76
156
  const uint64_t v2 = info->code[addr + 2];
77
156
  const uint64_t v3 = info->code[addr + 3];
78
156
  const uint64_t v4 = info->code[addr + 4];
79
156
  const uint64_t v5 = info->code[addr + 5];
80
156
  const uint64_t v6 = info->code[addr + 6];
81
156
  const uint64_t v7 = info->code[addr + 7];
82
156
  return (v0 << 56) | (v1 << 48) | (v2 << 40) | (v3 << 32) | (v4 << 24) |
83
156
         (v5 << 16) | (v6 << 8) | v7;
84
156
}
85
86
static unsigned int m68k_read_safe_16(const m68k_info *info,
87
              const uint64_t address)
88
457k
{
89
457k
  const uint64_t addr = (address - info->baseAddress) &
90
457k
            info->address_mask;
91
457k
  if (info->code_len < addr + 2) {
92
535
    return 0xaaaa;
93
535
  }
94
457k
  return m68k_read_disassembler_16(info, addr);
95
457k
}
96
97
static unsigned int m68k_read_safe_32(const m68k_info *info,
98
              const uint64_t address)
99
202k
{
100
202k
  const uint64_t addr = (address - info->baseAddress) &
101
202k
            info->address_mask;
102
202k
  if (info->code_len < addr + 4) {
103
1.53k
    return 0xaaaaaaaa;
104
1.53k
  }
105
200k
  return m68k_read_disassembler_32(info, addr);
106
202k
}
107
108
static uint64_t m68k_read_safe_64(const m68k_info *info, const uint64_t address)
109
157
{
110
157
  const uint64_t addr = (address - info->baseAddress) &
111
157
            info->address_mask;
112
157
  if (info->code_len < addr + 8) {
113
1
    return 0xaaaaaaaaaaaaaaaaLL;
114
1
  }
115
156
  return m68k_read_disassembler_64(info, addr);
116
157
}
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
14.7k
{
188
14.7k
  return (m68k_read_safe_16((info), (info)->pc) & 0xff);
189
14.7k
}
190
static unsigned int peek_imm_16(const m68k_info *info)
191
443k
{
192
443k
  return m68k_read_safe_16((info), (info)->pc);
193
443k
}
194
static unsigned int peek_imm_32(const m68k_info *info)
195
202k
{
196
202k
  return m68k_read_safe_32((info), (info)->pc);
197
202k
}
198
static unsigned long long peek_imm_64(const m68k_info *info)
199
157
{
200
157
  return m68k_read_safe_64((info), (info)->pc);
201
157
}
202
203
static unsigned int read_imm_8(m68k_info *info)
204
14.7k
{
205
14.7k
  const unsigned int value = peek_imm_8(info);
206
14.7k
  (info)->pc += 2;
207
14.7k
  return value & 0xff;
208
14.7k
}
209
static unsigned int read_imm_16(m68k_info *info)
210
246k
{
211
246k
  const unsigned int value = peek_imm_16(info);
212
246k
  (info)->pc += 2;
213
246k
  return value & 0xffff;
214
246k
}
215
static unsigned int read_imm_32(m68k_info *info)
216
9.45k
{
217
9.45k
  const unsigned int value = peek_imm_32(info);
218
9.45k
  (info)->pc += 4;
219
9.45k
  return value & 0xffffffff;
220
9.45k
}
221
static unsigned long long read_imm_64(m68k_info *info)
222
157
{
223
157
  const unsigned long long value = peek_imm_64(info);
224
157
  (info)->pc += 8;
225
157
  return value & 0xffffffffffffffff;
226
157
}
227
228
/* 100% portable signed int generators */
229
static int make_int_8(int value)
230
8.46k
{
231
8.46k
  return (value & 0x80) ? value | ~0xff : value & 0xff;
232
8.46k
}
233
234
static int make_int_16(int value)
235
2.45k
{
236
2.45k
  return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
237
2.45k
}
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.9k
{
243
12.9k
  uint32_t ext_addr = info->pc;
244
12.9k
  uint32_t extension = read_imm_16(info);
245
12.9k
  int32_t pc_adjust =
246
12.9k
    is_pc ? (int32_t)(ext_addr - info->baseAddress - 2) : 0;
247
248
12.9k
  op->address_mode = M68K_AM_AREGI_INDEX_BASE_DISP;
249
250
12.9k
  if (EXT_FULL(extension)) {
251
6.23k
    uint32_t preindex;
252
6.23k
    uint32_t postindex;
253
254
6.23k
    op->mem.base_reg = M68K_REG_INVALID;
255
6.23k
    op->mem.index_reg = M68K_REG_INVALID;
256
257
6.23k
    op->mem.in_disp =
258
6.23k
      EXT_BASE_DISPLACEMENT_PRESENT(extension) ?
259
3.59k
        (EXT_BASE_DISPLACEMENT_LONG(extension) ?
260
2.25k
           read_imm_32(info) :
261
3.59k
           (int16_t)read_imm_16(info)) :
262
6.23k
        0;
263
6.23k
    op->mem.in_disp += pc_adjust;
264
265
6.23k
    op->mem.in_disp_size =
266
6.23k
      EXT_BASE_DISPLACEMENT_PRESENT(extension) &&
267
3.59k
          EXT_BASE_DISPLACEMENT_LONG(extension) ?
268
2.25k
        1 :
269
6.23k
        0;
270
271
6.23k
    op->mem.out_disp =
272
6.23k
      EXT_OUTER_DISPLACEMENT_PRESENT(extension) ?
273
2.08k
        (EXT_OUTER_DISPLACEMENT_LONG(extension) ?
274
929
           read_imm_32(info) :
275
2.08k
           (int16_t)read_imm_16(info)) :
276
6.23k
        0;
277
278
6.23k
    op->mem.out_disp_size =
279
6.23k
      EXT_OUTER_DISPLACEMENT_PRESENT(extension) &&
280
2.08k
          EXT_OUTER_DISPLACEMENT_LONG(extension) ?
281
929
        1 :
282
6.23k
        0;
283
284
6.23k
    if (EXT_BASE_REGISTER_PRESENT(extension)) {
285
4.11k
      if (is_pc) {
286
765
        op->mem.base_reg = M68K_REG_PC;
287
3.34k
      } else {
288
3.34k
        op->mem.base_reg =
289
3.34k
          M68K_REG_A0 + (instruction & 7);
290
3.34k
      }
291
4.11k
    }
292
293
6.23k
    if (EXT_INDEX_REGISTER_PRESENT(extension)) {
294
3.99k
      if (EXT_INDEX_AR(extension)) {
295
1.54k
        op->mem.index_reg =
296
1.54k
          M68K_REG_A0 +
297
1.54k
          EXT_INDEX_REGISTER(extension);
298
2.44k
      } else {
299
2.44k
        op->mem.index_reg =
300
2.44k
          M68K_REG_D0 +
301
2.44k
          EXT_INDEX_REGISTER(extension);
302
2.44k
      }
303
304
3.99k
      op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
305
306
3.99k
      if (EXT_INDEX_SCALE(extension)) {
307
2.45k
        op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
308
2.45k
      }
309
3.99k
    }
310
311
6.23k
    preindex = (extension & 7) > 0 && (extension & 7) < 4;
312
6.23k
    postindex = (extension & 7) > 4;
313
314
6.23k
    if (preindex) {
315
1.73k
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_PRE_INDEX :
316
1.73k
               M68K_AM_MEMI_PRE_INDEX;
317
4.50k
    } else if (postindex) {
318
2.01k
      op->address_mode = is_pc ? M68K_AM_PC_MEMI_POST_INDEX :
319
2.01k
               M68K_AM_MEMI_POST_INDEX;
320
2.48k
    } else {
321
2.48k
      op->address_mode =
322
2.48k
        is_pc ? M68K_AM_PCI_INDEX_BASE_DISP :
323
2.48k
          M68K_AM_AREGI_INDEX_BASE_DISP;
324
2.48k
    }
325
326
6.23k
    return;
327
6.23k
  }
328
329
6.74k
  op->mem.index_reg =
330
6.74k
    (EXT_INDEX_AR(extension) ? M68K_REG_A0 : M68K_REG_D0) +
331
6.74k
    EXT_INDEX_REGISTER(extension);
332
6.74k
  op->mem.index_size = EXT_INDEX_LONG(extension) ? 1 : 0;
333
334
6.74k
  if (is_pc) {
335
747
    op->mem.base_reg = M68K_REG_PC;
336
747
    op->address_mode = M68K_AM_PCI_INDEX_8_BIT_DISP;
337
5.99k
  } else {
338
5.99k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
339
5.99k
    op->address_mode = M68K_AM_AREGI_INDEX_8_BIT_DISP;
340
5.99k
  }
341
342
6.74k
  op->mem.disp = (int8_t)(extension & 0xff);
343
6.74k
  op->mem.disp += (int16_t)pc_adjust;
344
6.74k
  op->mem.disp_size = 0;
345
346
6.74k
  if (EXT_INDEX_SCALE(extension)) {
347
3.87k
    op->mem.scale = 1 << EXT_INDEX_SCALE(extension);
348
3.87k
  }
349
6.74k
}
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
127k
{
381
127k
  return ir & M68K_EA_FIELD_MASK;
382
127k
}
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
127k
{
418
  // default to memory
419
420
127k
  op->type = M68K_OP_MEM;
421
422
127k
  switch (m68k_ea_field(instruction)) {
423
16.9k
  case 0x00:
424
21.7k
  case 0x01:
425
24.0k
  case 0x02:
426
25.1k
  case 0x03:
427
28.0k
  case 0x04:
428
30.5k
  case 0x05:
429
34.0k
  case 0x06:
430
36.4k
  case 0x07:
431
    /* data register direct */
432
36.4k
    op->address_mode = M68K_AM_REG_DIRECT_DATA;
433
36.4k
    op->reg = M68K_REG_D0 + (instruction & 7);
434
36.4k
    op->type = M68K_OP_REG;
435
36.4k
    break;
436
437
458
  case 0x08:
438
886
  case 0x09:
439
3.35k
  case 0x0a:
440
3.78k
  case 0x0b:
441
3.95k
  case 0x0c:
442
4.38k
  case 0x0d:
443
5.22k
  case 0x0e:
444
5.90k
  case 0x0f:
445
    /* address register direct */
446
5.90k
    op->address_mode = M68K_AM_REG_DIRECT_ADDR;
447
5.90k
    op->reg = M68K_REG_A0 + (instruction & 7);
448
5.90k
    op->type = M68K_OP_REG;
449
5.90k
    break;
450
451
2.09k
  case 0x10:
452
7.24k
  case 0x11:
453
8.91k
  case 0x12:
454
10.3k
  case 0x13:
455
11.5k
  case 0x14:
456
12.4k
  case 0x15:
457
13.0k
  case 0x16:
458
15.4k
  case 0x17:
459
    /* address register indirect */
460
15.4k
    op->address_mode = M68K_AM_REGI_ADDR;
461
15.4k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
462
15.4k
    break;
463
464
2.20k
  case 0x18:
465
4.54k
  case 0x19:
466
5.51k
  case 0x1a:
467
6.21k
  case 0x1b:
468
8.12k
  case 0x1c:
469
10.9k
  case 0x1d:
470
13.1k
  case 0x1e:
471
15.8k
  case 0x1f:
472
    /* address register indirect with postincrement */
473
15.8k
    op->address_mode = M68K_AM_REGI_ADDR_POST_INC;
474
15.8k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
475
15.8k
    break;
476
477
4.69k
  case 0x20:
478
8.49k
  case 0x21:
479
13.2k
  case 0x22:
480
15.0k
  case 0x23:
481
16.9k
  case 0x24:
482
18.7k
  case 0x25:
483
21.2k
  case 0x26:
484
23.5k
  case 0x27:
485
    /* address register indirect with predecrement */
486
23.5k
    op->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
487
23.5k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
488
23.5k
    break;
489
490
1.15k
  case 0x28:
491
3.08k
  case 0x29:
492
4.16k
  case 0x2a:
493
5.15k
  case 0x2b:
494
6.12k
  case 0x2c:
495
7.67k
  case 0x2d:
496
9.14k
  case 0x2e:
497
11.4k
  case 0x2f:
498
    /* address register indirect with displacement*/
499
11.4k
    op->address_mode = M68K_AM_REGI_ADDR_DISP;
500
11.4k
    op->mem.base_reg = M68K_REG_A0 + (instruction & 7);
501
11.4k
    op->mem.disp = (int16_t)read_imm_16(info);
502
11.4k
    op->mem.disp_size = 1;
503
11.4k
    break;
504
505
1.98k
  case 0x30:
506
3.54k
  case 0x31:
507
5.53k
  case 0x32:
508
6.87k
  case 0x33:
509
8.34k
  case 0x34:
510
9.19k
  case 0x35:
511
10.2k
  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.61k
  case 0x38:
518
    /* absolute short address */
519
2.61k
    op->address_mode = M68K_AM_ABSOLUTE_DATA_SHORT;
520
2.61k
    op->mem.address = read_imm_16(info);
521
2.61k
    break;
522
523
884
  case 0x39:
524
    /* absolute long address */
525
884
    op->address_mode = M68K_AM_ABSOLUTE_DATA_LONG;
526
884
    op->mem.address = read_imm_32(info);
527
884
    break;
528
529
1.59k
  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.59k
    uint32_t disp_addr = info->pc;
539
1.59k
    op->address_mode = M68K_AM_PCI_DISP;
540
1.59k
    op->mem.disp = (int16_t)read_imm_16(info);
541
1.59k
    op->mem.disp += (int16_t)(disp_addr - info->baseAddress - 2);
542
1.59k
    op->mem.disp_size = 1;
543
1.59k
    break;
544
10.2k
  }
545
546
1.86k
  case 0x3b:
547
    /* program counter with index */
548
1.86k
    get_with_index_address_mode(info, op, instruction, size, true);
549
1.86k
    break;
550
551
1.19k
  case 0x3c:
552
1.19k
    op->address_mode = M68K_AM_IMMEDIATE;
553
1.19k
    op->type = M68K_OP_IMM;
554
555
1.19k
    if (size == 1)
556
332
      op->imm = read_imm_8(info);
557
866
    else if (size == 2)
558
409
      op->imm = read_imm_16(info);
559
457
    else if (size == 4)
560
300
      op->imm = read_imm_32(info);
561
157
    else
562
157
      op->imm = read_imm_64(info);
563
564
1.19k
    break;
565
566
67
  default:
567
67
    break;
568
127k
  }
569
127k
}
570
571
static void set_insn_group(m68k_info *info, m68k_group_type group)
572
26.1k
{
573
26.1k
  info->groups[info->groups_count++] = (uint8_t)group;
574
26.1k
}
575
576
static cs_m68k *build_init_op(m68k_info *info, int opcode, int count, int size)
577
189k
{
578
189k
  cs_m68k *ext;
579
580
189k
  MCInst_setOpcode(info->inst, opcode);
581
582
189k
  ext = &info->extension;
583
584
189k
  ext->op_count = (uint8_t)count;
585
189k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
586
189k
  ext->op_size.cpu_size = size;
587
588
189k
  return ext;
589
189k
}
590
591
static void build_re_gen_1(m68k_info *info, bool isDreg, int opcode,
592
         uint8_t size)
593
13.4k
{
594
13.4k
  cs_m68k_op *op0;
595
13.4k
  cs_m68k_op *op1;
596
13.4k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
597
598
13.4k
  op0 = &ext->operands[0];
599
13.4k
  op1 = &ext->operands[1];
600
601
13.4k
  if (isDreg) {
602
13.4k
    op0->address_mode = M68K_AM_REG_DIRECT_DATA;
603
13.4k
    op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
604
13.4k
  } 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
13.4k
  get_ea_mode_op(info, op1, info->ir, size);
610
13.4k
}
611
612
static void build_re_1(m68k_info *info, int opcode, uint8_t size)
613
13.4k
{
614
13.4k
  build_re_gen_1(info, true, opcode, size);
615
13.4k
}
616
617
static void build_er_gen_1(m68k_info *info, bool isDreg, int opcode,
618
         uint8_t size)
619
14.6k
{
620
14.6k
  cs_m68k_op *op0;
621
14.6k
  cs_m68k_op *op1;
622
14.6k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
623
624
14.6k
  op0 = &ext->operands[0];
625
14.6k
  op1 = &ext->operands[1];
626
627
14.6k
  get_ea_mode_op(info, op0, info->ir, size);
628
629
14.6k
  if (isDreg) {
630
14.6k
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
631
14.6k
    op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
632
14.6k
  } 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.6k
}
637
638
static void append_imm_operand(m68k_info *info, uint32_t value)
639
2.34k
{
640
2.34k
  cs_m68k *ext = &info->extension;
641
2.34k
  cs_m68k_op *op = &ext->operands[ext->op_count];
642
2.34k
  op->type = M68K_OP_IMM;
643
2.34k
  op->address_mode = M68K_AM_IMMEDIATE;
644
2.34k
  op->imm = value;
645
2.34k
  ext->op_count++;
646
2.34k
}
647
648
static void build_rr(m68k_info *info, int opcode, uint8_t size, int imm)
649
4.34k
{
650
4.34k
  cs_m68k_op *op0;
651
4.34k
  cs_m68k_op *op1;
652
4.34k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
653
654
4.34k
  op0 = &ext->operands[0];
655
4.34k
  op1 = &ext->operands[1];
656
657
4.34k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
658
4.34k
  op0->reg = M68K_REG_D0 + (info->ir & 7);
659
660
4.34k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
661
4.34k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
662
663
4.34k
  if (imm > 0)
664
1.08k
    append_imm_operand(info, imm);
665
4.34k
}
666
667
static void build_r(m68k_info *info, int opcode, uint8_t size)
668
5.54k
{
669
5.54k
  cs_m68k_op *op0;
670
5.54k
  cs_m68k_op *op1;
671
5.54k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
672
673
5.54k
  op0 = &ext->operands[0];
674
5.54k
  op1 = &ext->operands[1];
675
676
5.54k
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
677
5.54k
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
678
679
5.54k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
680
5.54k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
681
5.54k
}
682
683
static void build_imm_ea(m68k_info *info, int opcode, uint8_t size,
684
       uint32_t imm)
685
19.4k
{
686
19.4k
  cs_m68k_op *op0;
687
19.4k
  cs_m68k_op *op1;
688
19.4k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
689
690
19.4k
  op0 = &ext->operands[0];
691
19.4k
  op1 = &ext->operands[1];
692
693
19.4k
  op0->type = M68K_OP_IMM;
694
19.4k
  op0->address_mode = M68K_AM_IMMEDIATE;
695
19.4k
  op0->imm = imm;
696
697
19.4k
  get_ea_mode_op(info, op1, info->ir, size);
698
19.4k
}
699
700
static void build_3bit_d(m68k_info *info, int opcode, int size)
701
6.52k
{
702
6.52k
  cs_m68k_op *op0;
703
6.52k
  cs_m68k_op *op1;
704
6.52k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
705
706
6.52k
  op0 = &ext->operands[0];
707
6.52k
  op1 = &ext->operands[1];
708
709
6.52k
  op0->type = M68K_OP_IMM;
710
6.52k
  op0->address_mode = M68K_AM_IMMEDIATE;
711
6.52k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
712
713
6.52k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
714
6.52k
  op1->reg = M68K_REG_D0 + (info->ir & 7);
715
6.52k
}
716
717
static void build_3bit_ea(m68k_info *info, int opcode, int size)
718
5.29k
{
719
5.29k
  cs_m68k_op *op0;
720
5.29k
  cs_m68k_op *op1;
721
5.29k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
722
723
5.29k
  op0 = &ext->operands[0];
724
5.29k
  op1 = &ext->operands[1];
725
726
5.29k
  op0->type = M68K_OP_IMM;
727
5.29k
  op0->address_mode = M68K_AM_IMMEDIATE;
728
5.29k
  op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7];
729
730
5.29k
  get_ea_mode_op(info, op1, info->ir, size);
731
5.29k
}
732
733
static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm)
734
4.05k
{
735
4.05k
  cs_m68k_op *op0;
736
4.05k
  cs_m68k_op *op1;
737
4.05k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
738
739
4.05k
  op0 = &ext->operands[0];
740
4.05k
  op1 = &ext->operands[1];
741
742
4.05k
  op0->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
743
4.05k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
744
745
4.05k
  op1->address_mode = M68K_AM_REGI_ADDR_PRE_DEC;
746
4.05k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
747
748
4.05k
  if (imm > 0)
749
1.26k
    append_imm_operand(info, imm);
750
4.05k
}
751
752
static void build_ea(m68k_info *info, int opcode, uint8_t size)
753
14.1k
{
754
14.1k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
755
14.1k
  get_ea_mode_op(info, &ext->operands[0], info->ir, size);
756
14.1k
}
757
758
static void build_ea_a(m68k_info *info, int opcode, uint8_t size)
759
7.77k
{
760
7.77k
  cs_m68k_op *op0;
761
7.77k
  cs_m68k_op *op1;
762
7.77k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
763
764
7.77k
  op0 = &ext->operands[0];
765
7.77k
  op1 = &ext->operands[1];
766
767
7.77k
  get_ea_mode_op(info, op0, info->ir, size);
768
769
7.77k
  op1->address_mode = M68K_AM_REG_DIRECT_ADDR;
770
7.77k
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
771
7.77k
}
772
773
static void build_ea_ea(m68k_info *info, int opcode, int size)
774
21.8k
{
775
21.8k
  cs_m68k_op *op0;
776
21.8k
  cs_m68k_op *op1;
777
21.8k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
778
779
21.8k
  op0 = &ext->operands[0];
780
21.8k
  op1 = &ext->operands[1];
781
782
21.8k
  get_ea_mode_op(info, op0, info->ir, size);
783
21.8k
  get_ea_mode_op(info, op1,
784
21.8k
           (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)),
785
21.8k
           size);
786
21.8k
}
787
788
static void build_pi_pi(m68k_info *info, int opcode, int size)
789
368
{
790
368
  cs_m68k_op *op0;
791
368
  cs_m68k_op *op1;
792
368
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
793
794
368
  op0 = &ext->operands[0];
795
368
  op1 = &ext->operands[1];
796
797
368
  op0->address_mode = M68K_AM_REGI_ADDR_POST_INC;
798
368
  op0->reg = M68K_REG_A0 + (info->ir & 7);
799
800
368
  op1->address_mode = M68K_AM_REGI_ADDR_POST_INC;
801
368
  op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
802
368
}
803
804
static void build_imm_special_reg(m68k_info *info, int opcode, uint32_t imm,
805
          int size, m68k_reg reg)
806
597
{
807
597
  cs_m68k_op *op0;
808
597
  cs_m68k_op *op1;
809
597
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
810
811
597
  op0 = &ext->operands[0];
812
597
  op1 = &ext->operands[1];
813
814
597
  op0->type = M68K_OP_IMM;
815
597
  op0->address_mode = M68K_AM_IMMEDIATE;
816
597
  op0->imm = imm;
817
818
597
  op1->address_mode = M68K_AM_NONE;
819
597
  op1->reg = reg;
820
597
}
821
822
static void build_relative_branch(m68k_info *info, int opcode, int size,
823
          int displacement)
824
10.2k
{
825
10.2k
  cs_m68k_op *op;
826
10.2k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
827
828
10.2k
  op = &ext->operands[0];
829
830
10.2k
  op->type = M68K_OP_BR_DISP;
831
10.2k
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
832
10.2k
  op->br_disp.disp = displacement;
833
10.2k
  op->br_disp.disp_size = size;
834
835
10.2k
  set_insn_group(info, M68K_GRP_JUMP);
836
10.2k
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
837
10.2k
}
838
839
static void build_absolute_jump_with_immediate(m68k_info *info, int opcode,
840
                 int size, int immediate)
841
1.66k
{
842
1.66k
  cs_m68k_op *op;
843
1.66k
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
844
845
1.66k
  op = &ext->operands[0];
846
847
1.66k
  op->type = M68K_OP_IMM;
848
1.66k
  op->address_mode = M68K_AM_IMMEDIATE;
849
1.66k
  op->imm = immediate;
850
851
1.66k
  set_insn_group(info, M68K_GRP_JUMP);
852
1.66k
}
853
854
static void build_bcc(m68k_info *info, int size, int displacement)
855
7.37k
{
856
7.37k
  build_relative_branch(info,
857
7.37k
            s_branch_lut[M68K_IR_CONDITION_NIBBLE(info)],
858
7.37k
            size, displacement);
859
7.37k
}
860
861
static void build_trap(m68k_info *info, int size, int immediate)
862
376
{
863
376
  build_absolute_jump_with_immediate(
864
376
    info, s_trap_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
865
376
    immediate);
866
376
}
867
868
static void build_dbxx(m68k_info *info, int opcode, int size, int displacement)
869
611
{
870
611
  cs_m68k_op *op0;
871
611
  cs_m68k_op *op1;
872
611
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
873
874
611
  op0 = &ext->operands[0];
875
611
  op1 = &ext->operands[1];
876
877
611
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
878
611
  op0->reg = M68K_REG_D0 + (info->ir & 7);
879
880
611
  op1->type = M68K_OP_BR_DISP;
881
611
  op1->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
882
611
  op1->br_disp.disp = displacement;
883
611
  op1->br_disp.disp_size = M68K_OP_BR_DISP_SIZE_LONG;
884
885
611
  set_insn_group(info, M68K_GRP_JUMP);
886
611
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
887
611
}
888
889
static void build_dbcc(m68k_info *info, int size, int displacement)
890
314
{
891
314
  build_dbxx(info, s_dbcc_lut[M68K_IR_CONDITION_NIBBLE(info)], size,
892
314
       displacement);
893
314
}
894
895
static void build_d_d_ea(m68k_info *info, int opcode, int size)
896
163
{
897
163
  cs_m68k_op *op0;
898
163
  cs_m68k_op *op1;
899
163
  cs_m68k_op *op2;
900
163
  uint32_t extension = read_imm_16(info);
901
163
  cs_m68k *ext = build_init_op(info, opcode, 3, size);
902
903
163
  op0 = &ext->operands[0];
904
163
  op1 = &ext->operands[1];
905
163
  op2 = &ext->operands[2];
906
907
163
  op0->address_mode = M68K_AM_REG_DIRECT_DATA;
908
163
  op0->reg = M68K_REG_D0 + (extension & 7);
909
910
163
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
911
163
  op1->reg = M68K_REG_D0 + ((extension >> 6) & 7);
912
913
163
  get_ea_mode_op(info, op2, info->ir, size);
914
163
}
915
916
static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg)
917
1.16k
{
918
1.16k
  uint8_t offset;
919
1.16k
  uint8_t width;
920
1.16k
  cs_m68k_op *op_ea;
921
1.16k
  cs_m68k_op *op1;
922
1.16k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
923
1.16k
  uint32_t extension = read_imm_16(info);
924
925
1.16k
  op_ea = &ext->operands[0];
926
1.16k
  op1 = &ext->operands[1];
927
928
1.16k
  if (BIT_B(extension))
929
722
    offset = M68K_BITFIELD_ENCODE_REG((extension >> 6) & 7);
930
447
  else
931
447
    offset = (extension >> 6) & 31;
932
933
1.16k
  if (BIT_5(extension))
934
434
    width = M68K_BITFIELD_ENCODE_REG(extension & 7);
935
735
  else
936
735
    width = (uint8_t)g_5bit_data_table[extension & 31];
937
938
1.16k
  if (has_d_arg) {
939
649
    ext->op_count = 2;
940
649
    op1->address_mode = M68K_AM_REG_DIRECT_DATA;
941
649
    op1->reg = M68K_REG_D0 + ((extension >> 12) & 7);
942
649
  }
943
944
1.16k
  get_ea_mode_op(info, op_ea, info->ir, 1);
945
946
1.16k
  op_ea->mem.bitfield = 1;
947
1.16k
  op_ea->mem.width = width;
948
1.16k
  op_ea->mem.offset = offset;
949
1.16k
}
950
951
static void build_d(m68k_info *info, int opcode, int size)
952
672
{
953
672
  cs_m68k *ext = build_init_op(info, opcode, 1, size);
954
672
  cs_m68k_op *op;
955
956
672
  op = &ext->operands[0];
957
958
672
  op->address_mode = M68K_AM_REG_DIRECT_DATA;
959
672
  op->reg = M68K_REG_D0 + (info->ir & 7);
960
672
}
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
539
{
1058
539
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1059
539
  uint32_t s = 16 - 1; // extra shift needed at end
1060
1061
7.60k
  for (v >>= 1; v; v >>= 1) {
1062
7.06k
    r <<= 1;
1063
7.06k
    r |= v & 1;
1064
7.06k
    s--;
1065
7.06k
  }
1066
1067
539
  r <<= s; // shift when v's highest bits are zero
1068
539
  return r;
1069
539
}
1070
1071
static uint8_t reverse_bits_8(uint32_t v)
1072
450
{
1073
450
  uint32_t r = v; // r will be reversed bits of v; first get LSB of v
1074
450
  uint32_t s = 8 - 1; // extra shift needed at end
1075
1076
1.78k
  for (v >>= 1; v; v >>= 1) {
1077
1.33k
    r <<= 1;
1078
1.33k
    r |= v & 1;
1079
1.33k
    s--;
1080
1.33k
  }
1081
1082
450
  r <<= s; // shift when v's highest bits are zero
1083
450
  return r;
1084
450
}
1085
1086
static void build_movem_re(m68k_info *info, int opcode, int size)
1087
1.08k
{
1088
1.08k
  cs_m68k_op *op0;
1089
1.08k
  cs_m68k_op *op1;
1090
1.08k
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
1091
1092
1.08k
  op0 = &ext->operands[0];
1093
1.08k
  op1 = &ext->operands[1];
1094
1095
1.08k
  op0->type = M68K_OP_REG_BITS;
1096
1.08k
  op0->register_bits = read_imm_16(info);
1097
1098
1.08k
  get_ea_mode_op(info, op1, info->ir, size);
1099
1100
1.08k
  if (op1->address_mode == M68K_AM_REGI_ADDR_PRE_DEC)
1101
539
    op0->register_bits = reverse_bits(op0->register_bits);
1102
1.08k
}
1103
1104
static void build_movem_er(m68k_info *info, int opcode, int size)
1105
731
{
1106
731
  cs_m68k_op *op0;
1107
731
  cs_m68k_op *op1;
1108
731
  cs_m68k *ext = build_init_op(info, opcode, 2, size);
1109
1110
731
  op0 = &ext->operands[0];
1111
731
  op1 = &ext->operands[1];
1112
1113
731
  op1->type = M68K_OP_REG_BITS;
1114
731
  op1->register_bits = read_imm_16(info);
1115
1116
731
  get_ea_mode_op(info, op0, info->ir, size);
1117
731
}
1118
1119
static void build_imm(m68k_info *info, int opcode, uint32_t data)
1120
34.3k
{
1121
34.3k
  cs_m68k_op *op;
1122
34.3k
  cs_m68k *ext = build_init_op(info, opcode, 1, 0);
1123
1124
34.3k
  MCInst_setOpcode(info->inst, opcode);
1125
1126
34.3k
  op = &ext->operands[0];
1127
1128
34.3k
  op->type = M68K_OP_IMM;
1129
34.3k
  op->address_mode = M68K_AM_IMMEDIATE;
1130
34.3k
  op->imm = data;
1131
34.3k
}
1132
1133
static void build_illegal(m68k_info *info, uint32_t data)
1134
289
{
1135
289
  build_imm(info, M68K_INS_ILLEGAL, data);
1136
289
}
1137
1138
static void build_invalid(m68k_info *info, uint32_t data)
1139
34.0k
{
1140
34.0k
  build_imm(info, M68K_INS_INVALID, data);
1141
34.0k
}
1142
1143
static void build_cas2(m68k_info *info, int size)
1144
173
{
1145
173
  uint32_t word3;
1146
173
  uint32_t extension;
1147
173
  cs_m68k_op *op0;
1148
173
  cs_m68k_op *op1;
1149
173
  cs_m68k_op *op2;
1150
173
  cs_m68k *ext = build_init_op(info, M68K_INS_CAS2, 3, size);
1151
173
  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
173
  word3 = peek_imm_32(info) & 0xffff;
1155
173
  if (!instruction_is_valid(info, word3))
1156
85
    return;
1157
1158
88
  op0 = &ext->operands[0];
1159
88
  op1 = &ext->operands[1];
1160
88
  op2 = &ext->operands[2];
1161
1162
88
  extension = read_imm_32(info);
1163
1164
88
  op0->address_mode = M68K_AM_NONE;
1165
88
  op0->type = M68K_OP_REG_PAIR;
1166
88
  op0->reg_pair.reg_0 = ((extension >> 16) & 7) + M68K_REG_D0;
1167
88
  op0->reg_pair.reg_1 = (extension & 7) + M68K_REG_D0;
1168
1169
88
  op1->address_mode = M68K_AM_NONE;
1170
88
  op1->type = M68K_OP_REG_PAIR;
1171
88
  op1->reg_pair.reg_0 = ((extension >> 22) & 7) + M68K_REG_D0;
1172
88
  op1->reg_pair.reg_1 = ((extension >> 6) & 7) + M68K_REG_D0;
1173
1174
88
  reg_0 = (extension >> 28) & 7;
1175
88
  reg_1 = (extension >> 12) & 7;
1176
1177
88
  op2->address_mode = M68K_AM_NONE;
1178
88
  op2->type = M68K_OP_REG_PAIR;
1179
88
  op2->reg_pair.reg_0 = reg_0 + (BIT_1F(extension) ? 8 : 0) + M68K_REG_D0;
1180
88
  op2->reg_pair.reg_1 = reg_1 + (BIT_F(extension) ? 8 : 0) + M68K_REG_D0;
1181
88
}
1182
1183
static void build_chk2_cmp2(m68k_info *info, int size)
1184
230
{
1185
230
  cs_m68k_op *op0;
1186
230
  cs_m68k_op *op1;
1187
230
  cs_m68k *ext = build_init_op(info, M68K_INS_CHK2, 2, size);
1188
1189
230
  uint32_t extension = read_imm_16(info);
1190
1191
230
  if (BIT_B(extension))
1192
18
    MCInst_setOpcode(info->inst, M68K_INS_CHK2);
1193
212
  else
1194
212
    MCInst_setOpcode(info->inst, M68K_INS_CMP2);
1195
1196
230
  op0 = &ext->operands[0];
1197
230
  op1 = &ext->operands[1];
1198
1199
230
  get_ea_mode_op(info, op0, info->ir, size);
1200
1201
230
  op1->address_mode = M68K_AM_NONE;
1202
230
  op1->type = M68K_OP_REG;
1203
230
  op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1204
230
       ((extension >> 12) & 7);
1205
230
}
1206
1207
static void build_move16(m68k_info *info, const uint32_t data[2],
1208
       const uint32_t modes[2])
1209
394
{
1210
394
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE16, 2, 0);
1211
394
  int i;
1212
1213
1.18k
  for (i = 0; i < 2; ++i) {
1214
788
    cs_m68k_op *op = &ext->operands[i];
1215
788
    const uint32_t d = data[i];
1216
788
    const uint32_t m = modes[i];
1217
1218
788
    op->type = M68K_OP_MEM;
1219
788
    op->address_mode = m;
1220
1221
788
    if (m == M68K_AM_REGI_ADDR_POST_INC || m == M68K_AM_REGI_ADDR)
1222
420
      op->mem.base_reg = M68K_REG_A0 + d;
1223
368
    else
1224
368
      op->mem.address = d;
1225
788
  }
1226
394
}
1227
1228
static void build_link(m68k_info *info, int disp, int size)
1229
1.13k
{
1230
1.13k
  cs_m68k_op *op0;
1231
1.13k
  cs_m68k_op *op1;
1232
1.13k
  cs_m68k *ext = build_init_op(info, M68K_INS_LINK, 2, size);
1233
1234
1.13k
  op0 = &ext->operands[0];
1235
1.13k
  op1 = &ext->operands[1];
1236
1237
1.13k
  op0->address_mode = M68K_AM_NONE;
1238
1.13k
  op0->reg = M68K_REG_A0 + (info->ir & 7);
1239
1240
1.13k
  op1->address_mode = M68K_AM_IMMEDIATE;
1241
1.13k
  op1->type = M68K_OP_IMM;
1242
1.13k
  op1->imm = disp;
1243
1.13k
}
1244
1245
static void build_cpush_cinv(m68k_info *info, int op_offset)
1246
603
{
1247
603
  cs_m68k_op *op0;
1248
603
  cs_m68k_op *op1;
1249
603
  cs_m68k *ext = build_init_op(info, M68K_INS_INVALID, 2, 0);
1250
1251
603
  switch (M68K_IR_CACHE_SCOPE(info)) {
1252
79
  case 0:
1253
79
    d68000_invalid(info);
1254
79
    return;
1255
138
  case 1: // Line
1256
138
    MCInst_setOpcode(info->inst, op_offset + 0);
1257
138
    break;
1258
266
  case 2: // Page
1259
266
    MCInst_setOpcode(info->inst, op_offset + 1);
1260
266
    break;
1261
120
  case 3: // All
1262
120
    ext->op_count = 1;
1263
120
    MCInst_setOpcode(info->inst, op_offset + 2);
1264
120
    break;
1265
0
  default:
1266
0
    return;
1267
603
  }
1268
1269
524
  op0 = &ext->operands[0];
1270
524
  op1 = &ext->operands[1];
1271
1272
524
  op0->address_mode = M68K_AM_IMMEDIATE;
1273
524
  op0->type = M68K_OP_IMM;
1274
524
  op0->imm = M68K_IR_CACHE_SEL(info);
1275
1276
524
  op1->type = M68K_OP_MEM;
1277
524
  op1->address_mode = M68K_AM_REGI_ADDR;
1278
524
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1279
524
}
1280
1281
static void build_movep_re(m68k_info *info, int size)
1282
285
{
1283
285
  cs_m68k_op *op0;
1284
285
  cs_m68k_op *op1;
1285
285
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1286
1287
285
  op0 = &ext->operands[0];
1288
285
  op1 = &ext->operands[1];
1289
1290
285
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1291
1292
285
  op1->address_mode = M68K_AM_REGI_ADDR_DISP;
1293
285
  op1->type = M68K_OP_MEM;
1294
285
  op1->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1295
285
  op1->mem.disp = (int16_t)read_imm_16(info);
1296
285
}
1297
1298
static void build_movep_er(m68k_info *info, int size)
1299
1.14k
{
1300
1.14k
  cs_m68k_op *op0;
1301
1.14k
  cs_m68k_op *op1;
1302
1.14k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEP, 2, size);
1303
1304
1.14k
  op0 = &ext->operands[0];
1305
1.14k
  op1 = &ext->operands[1];
1306
1307
1.14k
  op0->address_mode = M68K_AM_REGI_ADDR_DISP;
1308
1.14k
  op0->type = M68K_OP_MEM;
1309
1.14k
  op0->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
1310
1.14k
  op0->mem.disp = (int16_t)read_imm_16(info);
1311
1312
1.14k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
1313
1.14k
}
1314
1315
static void build_moves(m68k_info *info, int size)
1316
277
{
1317
277
  cs_m68k_op *op0;
1318
277
  cs_m68k_op *op1;
1319
277
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVES, 2, size);
1320
277
  uint32_t extension = read_imm_16(info);
1321
1322
277
  op0 = &ext->operands[0];
1323
277
  op1 = &ext->operands[1];
1324
1325
277
  if (BIT_B(extension)) {
1326
106
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1327
106
         ((extension >> 12) & 7);
1328
106
    get_ea_mode_op(info, op1, info->ir, size);
1329
171
  } else {
1330
171
    get_ea_mode_op(info, op0, info->ir, size);
1331
171
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
1332
171
         ((extension >> 12) & 7);
1333
171
  }
1334
277
}
1335
1336
static void build_er_1(m68k_info *info, int opcode, uint8_t size)
1337
14.6k
{
1338
14.6k
  build_er_gen_1(info, true, opcode, size);
1339
14.6k
}
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
34.0k
{
1381
34.0k
  build_invalid(info, info->ir);
1382
34.0k
}
1383
1384
static void d68000_illegal(m68k_info *info)
1385
289
{
1386
289
  build_illegal(info, info->ir);
1387
289
}
1388
1389
static void dcf_1111(m68k_info *info)
1390
6.07k
{
1391
6.07k
  d68000_invalid(info);
1392
6.07k
}
1393
1394
static void dcf_bitop_d(m68k_info *info, m68k_insn insn)
1395
15
{
1396
15
  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
9
{
1402
9
  dcf_bitop_d(info, M68K_INS_BITREV);
1403
9
}
1404
1405
static void dcf_byterev(m68k_info *info)
1406
4
{
1407
4
  dcf_bitop_d(info, M68K_INS_BYTEREV);
1408
4
}
1409
1410
static void dcf_ff1(m68k_info *info)
1411
2
{
1412
2
  dcf_bitop_d(info, M68K_INS_FF1);
1413
2
}
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
667
{
1424
667
  cs_m68k *ext;
1425
667
  cs_m68k_op *op0;
1426
667
  cs_m68k_op *op1;
1427
1428
667
  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
3
{
1460
3
  cs_m68k_op *op0;
1461
3
  cs_m68k_op *op1;
1462
1463
3
  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
0
{
1471
0
  cs_m68k_op *op0;
1472
0
  cs_m68k_op *op1;
1473
1474
0
  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
12
{
1482
12
  cs_m68k_op *op0;
1483
12
  cs_m68k_op *op1;
1484
1485
12
  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
2
{
1493
2
  cs_m68k_op *op0;
1494
2
  cs_m68k_op *op1;
1495
1496
2
  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
6
{
1504
6
  cs_m68k_op *op0;
1505
6
  cs_m68k_op *op1;
1506
1507
6
  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
21
{
1515
21
  cs_m68k_op *op0;
1516
21
  cs_m68k_op *op1;
1517
1518
21
  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
0
{
1526
0
  cs_m68k_op *op0;
1527
0
  cs_m68k_op *op1;
1528
1529
0
  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
0
{
1537
0
  cs_m68k_op *op0;
1538
0
  cs_m68k_op *op1;
1539
1540
0
  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
94
{
1548
94
  cs_m68k_op *op0;
1549
94
  cs_m68k_op *op1;
1550
1551
94
  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
31
{
1559
31
  cs_m68k_op *op0;
1560
31
  cs_m68k_op *op1;
1561
1562
31
  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
1
{
1570
1
  cs_m68k_op *op0;
1571
1
  cs_m68k_op *op1;
1572
1573
1
  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
8
{
1581
8
  cs_m68k_op *op0;
1582
8
  cs_m68k_op *op1;
1583
1584
8
  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
100
{
1592
100
  cs_m68k_op *op0;
1593
100
  cs_m68k_op *op1;
1594
1595
100
  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
0
{
1603
0
  cs_m68k_op *op0;
1604
0
  cs_m68k_op *op1;
1605
1606
0
  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
168
{
1614
168
  cs_m68k_op *op0;
1615
168
  cs_m68k_op *op1;
1616
1617
168
  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
8
{
1625
8
  cs_m68k_op *op0;
1626
8
  cs_m68k_op *op1;
1627
1628
8
  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
3
{
1636
3
  cs_m68k_op *op0;
1637
3
  cs_m68k_op *op1;
1638
1639
3
  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
0
{
1647
0
  cs_m68k_op *op0;
1648
0
  cs_m68k_op *op1;
1649
1650
0
  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
3.62k
{
1658
3.62k
  uint16_t ext_word;
1659
3.62k
  cs_m68k *ext;
1660
3.62k
  cs_m68k_op *op0;
1661
3.62k
  cs_m68k_op *op1;
1662
3.62k
  cs_m68k_op *op;
1663
3.62k
  uint32_t src0;
1664
3.62k
  uint32_t src1;
1665
3.62k
  uint32_t update;
1666
3.62k
  uint32_t acc;
1667
3.62k
  bool is_memory;
1668
3.62k
  bool is_emac;
1669
3.62k
  int size;
1670
1671
3.62k
  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
32
{
1748
32
  cs_m68k *ext;
1749
1750
32
  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
56
{
1759
56
  cs_m68k *ext;
1760
1761
56
  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
11
{
1770
11
  cs_m68k *ext;
1771
1772
11
  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
62
{
1781
62
  cs_m68k *ext;
1782
1783
62
  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
0
{
1792
0
  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
240
{
1811
240
  int size_bits = (info->ir >> 6) & 3;
1812
240
  int size;
1813
240
  cs_m68k *ext;
1814
1815
240
  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
8
{
1843
8
  cs_m68k *ext;
1844
1845
8
  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
5
{
1858
5
  cs_m68k *ext;
1859
5
  cs_m68k_op *op;
1860
1861
5
  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
2
{
1902
2
  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
4
{
1909
4
  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.76k
{
1916
2.76k
  uint16_t ext_word;
1917
2.76k
  bool cp1;
1918
2.76k
  bool store;
1919
2.76k
  int size;
1920
2.76k
  int opcode;
1921
2.76k
  cs_m68k *ext;
1922
1923
2.76k
  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
388
{
1965
388
  build_rr(info, M68K_INS_ABCD, 1, 0);
1966
388
}
1967
1968
static void d68000_abcd_mm(m68k_info *info)
1969
243
{
1970
243
  build_mm(info, M68K_INS_ABCD, 1, 0);
1971
243
}
1972
1973
static void d68000_add_er_8(m68k_info *info)
1974
184
{
1975
184
  build_er_1(info, M68K_INS_ADD, 1);
1976
184
}
1977
1978
static void d68000_add_er_16(m68k_info *info)
1979
438
{
1980
438
  build_er_1(info, M68K_INS_ADD, 2);
1981
438
}
1982
1983
static void d68000_add_er_32(m68k_info *info)
1984
1.03k
{
1985
1.03k
  build_er_1(info, M68K_INS_ADD, 4);
1986
1.03k
}
1987
1988
static void d68000_add_re_8(m68k_info *info)
1989
398
{
1990
398
  build_re_1(info, M68K_INS_ADD, 1);
1991
398
}
1992
1993
static void d68000_add_re_16(m68k_info *info)
1994
412
{
1995
412
  build_re_1(info, M68K_INS_ADD, 2);
1996
412
}
1997
1998
static void d68000_add_re_32(m68k_info *info)
1999
295
{
2000
295
  build_re_1(info, M68K_INS_ADD, 4);
2001
295
}
2002
2003
static void d68000_adda_16(m68k_info *info)
2004
678
{
2005
678
  build_ea_a(info, M68K_INS_ADDA, 2);
2006
678
}
2007
2008
static void d68000_adda_32(m68k_info *info)
2009
1.73k
{
2010
1.73k
  build_ea_a(info, M68K_INS_ADDA, 4);
2011
1.73k
}
2012
2013
static void d68000_addi_8(m68k_info *info)
2014
599
{
2015
599
  build_imm_ea(info, M68K_INS_ADDI, 1, read_imm_8(info));
2016
599
}
2017
2018
static void d68000_addi_16(m68k_info *info)
2019
259
{
2020
259
  build_imm_ea(info, M68K_INS_ADDI, 2, read_imm_16(info));
2021
259
}
2022
2023
static void d68000_addi_32(m68k_info *info)
2024
136
{
2025
136
  build_imm_ea(info, M68K_INS_ADDI, 4, read_imm_32(info));
2026
136
}
2027
2028
static void d68000_addq_8(m68k_info *info)
2029
466
{
2030
466
  build_3bit_ea(info, M68K_INS_ADDQ, 1);
2031
466
}
2032
2033
static void d68000_addq_16(m68k_info *info)
2034
1.50k
{
2035
1.50k
  build_3bit_ea(info, M68K_INS_ADDQ, 2);
2036
1.50k
}
2037
2038
static void d68000_addq_32(m68k_info *info)
2039
134
{
2040
134
  build_3bit_ea(info, M68K_INS_ADDQ, 4);
2041
134
}
2042
2043
static void d68000_addx_rr_8(m68k_info *info)
2044
155
{
2045
155
  build_rr(info, M68K_INS_ADDX, 1, 0);
2046
155
}
2047
2048
static void d68000_addx_rr_16(m68k_info *info)
2049
322
{
2050
322
  build_rr(info, M68K_INS_ADDX, 2, 0);
2051
322
}
2052
2053
static void d68000_addx_rr_32(m68k_info *info)
2054
85
{
2055
85
  build_rr(info, M68K_INS_ADDX, 4, 0);
2056
85
}
2057
2058
static void d68000_addx_mm_8(m68k_info *info)
2059
69
{
2060
69
  build_mm(info, M68K_INS_ADDX, 1, 0);
2061
69
}
2062
2063
static void d68000_addx_mm_16(m68k_info *info)
2064
578
{
2065
578
  build_mm(info, M68K_INS_ADDX, 2, 0);
2066
578
}
2067
2068
static void d68000_addx_mm_32(m68k_info *info)
2069
30
{
2070
30
  build_mm(info, M68K_INS_ADDX, 4, 0);
2071
30
}
2072
2073
static void d68000_and_er_8(m68k_info *info)
2074
397
{
2075
397
  build_er_1(info, M68K_INS_AND, 1);
2076
397
}
2077
2078
static void d68000_and_er_16(m68k_info *info)
2079
544
{
2080
544
  build_er_1(info, M68K_INS_AND, 2);
2081
544
}
2082
2083
static void d68000_and_er_32(m68k_info *info)
2084
560
{
2085
560
  build_er_1(info, M68K_INS_AND, 4);
2086
560
}
2087
2088
static void d68000_and_re_8(m68k_info *info)
2089
214
{
2090
214
  build_re_1(info, M68K_INS_AND, 1);
2091
214
}
2092
2093
static void d68000_and_re_16(m68k_info *info)
2094
268
{
2095
268
  build_re_1(info, M68K_INS_AND, 2);
2096
268
}
2097
2098
static void d68000_and_re_32(m68k_info *info)
2099
182
{
2100
182
  build_re_1(info, M68K_INS_AND, 4);
2101
182
}
2102
2103
static void d68000_andi_8(m68k_info *info)
2104
329
{
2105
329
  build_imm_ea(info, M68K_INS_ANDI, 1, read_imm_8(info));
2106
329
}
2107
2108
static void d68000_andi_16(m68k_info *info)
2109
231
{
2110
231
  build_imm_ea(info, M68K_INS_ANDI, 2, read_imm_16(info));
2111
231
}
2112
2113
static void d68000_andi_32(m68k_info *info)
2114
76
{
2115
76
  build_imm_ea(info, M68K_INS_ANDI, 4, read_imm_32(info));
2116
76
}
2117
2118
static void d68000_andi_to_ccr(m68k_info *info)
2119
75
{
2120
75
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_8(info), 1,
2121
75
            M68K_REG_CCR);
2122
75
}
2123
2124
static void d68000_andi_to_sr(m68k_info *info)
2125
38
{
2126
38
  build_imm_special_reg(info, M68K_INS_ANDI, read_imm_16(info), 2,
2127
38
            M68K_REG_SR);
2128
38
}
2129
2130
static void d68000_asr_s_8(m68k_info *info)
2131
1.22k
{
2132
1.22k
  build_3bit_d(info, M68K_INS_ASR, 1);
2133
1.22k
}
2134
2135
static void d68000_asr_s_16(m68k_info *info)
2136
296
{
2137
296
  build_3bit_d(info, M68K_INS_ASR, 2);
2138
296
}
2139
2140
static void d68000_asr_s_32(m68k_info *info)
2141
121
{
2142
121
  build_3bit_d(info, M68K_INS_ASR, 4);
2143
121
}
2144
2145
static void d68000_asr_r_8(m68k_info *info)
2146
316
{
2147
316
  build_r(info, M68K_INS_ASR, 1);
2148
316
}
2149
2150
static void d68000_asr_r_16(m68k_info *info)
2151
597
{
2152
597
  build_r(info, M68K_INS_ASR, 2);
2153
597
}
2154
2155
static void d68000_asr_r_32(m68k_info *info)
2156
74
{
2157
74
  build_r(info, M68K_INS_ASR, 4);
2158
74
}
2159
2160
static void d68000_asr_ea(m68k_info *info)
2161
434
{
2162
434
  build_ea(info, M68K_INS_ASR, 2);
2163
434
}
2164
2165
static void d68000_asl_s_8(m68k_info *info)
2166
1.02k
{
2167
1.02k
  build_3bit_d(info, M68K_INS_ASL, 1);
2168
1.02k
}
2169
2170
static void d68000_asl_s_16(m68k_info *info)
2171
154
{
2172
154
  build_3bit_d(info, M68K_INS_ASL, 2);
2173
154
}
2174
2175
static void d68000_asl_s_32(m68k_info *info)
2176
261
{
2177
261
  build_3bit_d(info, M68K_INS_ASL, 4);
2178
261
}
2179
2180
static void d68000_asl_r_8(m68k_info *info)
2181
440
{
2182
440
  build_r(info, M68K_INS_ASL, 1);
2183
440
}
2184
2185
static void d68000_asl_r_16(m68k_info *info)
2186
488
{
2187
488
  build_r(info, M68K_INS_ASL, 2);
2188
488
}
2189
2190
static void d68000_asl_r_32(m68k_info *info)
2191
87
{
2192
87
  build_r(info, M68K_INS_ASL, 4);
2193
87
}
2194
2195
static void d68000_asl_ea(m68k_info *info)
2196
1.17k
{
2197
1.17k
  build_ea(info, M68K_INS_ASL, 2);
2198
1.17k
}
2199
2200
static void d68000_bcc_8(m68k_info *info)
2201
6.61k
{
2202
6.61k
  build_bcc(info, 1, make_int_8(info->ir));
2203
6.61k
}
2204
2205
static void d68000_bcc_16(m68k_info *info)
2206
610
{
2207
610
  build_bcc(info, 2, make_int_16(read_imm_16(info)));
2208
610
}
2209
2210
static void d68020_bcc_32(m68k_info *info)
2211
462
{
2212
462
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2213
462
            CS_MODE_M68K_CF_ISA_C);
2214
155
  build_bcc(info, 4, read_imm_32(info));
2215
155
}
2216
2217
static void d68000_bchg_r(m68k_info *info)
2218
1.23k
{
2219
1.23k
  build_re_1(info, M68K_INS_BCHG, 1);
2220
1.23k
}
2221
2222
static void d68000_bchg_s(m68k_info *info)
2223
98
{
2224
98
  build_imm_ea(info, M68K_INS_BCHG, 1, read_imm_8(info));
2225
98
}
2226
2227
static void d68000_bclr_r(m68k_info *info)
2228
627
{
2229
627
  build_re_1(info, M68K_INS_BCLR, 1);
2230
627
}
2231
2232
static void d68000_bclr_s(m68k_info *info)
2233
1.33k
{
2234
1.33k
  build_imm_ea(info, M68K_INS_BCLR, 1, read_imm_8(info));
2235
1.33k
}
2236
2237
static void d68010_bkpt(m68k_info *info)
2238
718
{
2239
718
  LIMIT_FEATURE(info, M68010_PLUS);
2240
413
  build_absolute_jump_with_immediate(info, M68K_INS_BKPT, 0,
2241
413
             info->ir & 7);
2242
413
}
2243
2244
static void d68020_bfchg(m68k_info *info)
2245
330
{
2246
  /* Bit field ops are 68020+ only; CPU32 does NOT support them
2247
   * despite sharing CS_MODE_M68K_020. */
2248
330
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2249
264
  build_bitfield_ins(info, M68K_INS_BFCHG, false);
2250
264
}
2251
2252
static void d68020_bfclr(m68k_info *info)
2253
198
{
2254
198
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2255
118
  build_bitfield_ins(info, M68K_INS_BFCLR, false);
2256
118
}
2257
2258
static void d68020_bfexts(m68k_info *info)
2259
139
{
2260
139
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2261
72
  build_bitfield_ins(info, M68K_INS_BFEXTS, true);
2262
72
}
2263
2264
static void d68020_bfextu(m68k_info *info)
2265
339
{
2266
339
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2267
262
  build_bitfield_ins(info, M68K_INS_BFEXTU, true);
2268
262
}
2269
2270
static void d68020_bfffo(m68k_info *info)
2271
151
{
2272
151
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2273
92
  build_bitfield_ins(info, M68K_INS_BFFFO, true);
2274
92
}
2275
2276
static void d68020_bfins(m68k_info *info)
2277
410
{
2278
410
  cs_m68k *ext = &info->extension;
2279
410
  cs_m68k_op temp;
2280
2281
410
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2282
223
  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
223
  temp = ext->operands[0];
2287
223
  ext->operands[0] = ext->operands[1];
2288
223
  ext->operands[1] = temp;
2289
223
}
2290
2291
static void d68020_bfset(m68k_info *info)
2292
77
{
2293
77
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2294
19
  build_bitfield_ins(info, M68K_INS_BFSET, false);
2295
19
}
2296
2297
static void d68020_bftst(m68k_info *info)
2298
162
{
2299
162
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2300
119
  build_bitfield_ins(info, M68K_INS_BFTST, false);
2301
119
}
2302
2303
static void d68000_bra_8(m68k_info *info)
2304
742
{
2305
742
  build_relative_branch(info, M68K_INS_BRA, 1, make_int_8(info->ir));
2306
742
}
2307
2308
static void d68000_bra_16(m68k_info *info)
2309
294
{
2310
294
  build_relative_branch(info, M68K_INS_BRA, 2,
2311
294
            make_int_16(read_imm_16(info)));
2312
294
}
2313
2314
static void d68020_bra_32(m68k_info *info)
2315
194
{
2316
194
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2317
194
            CS_MODE_M68K_CF_ISA_C);
2318
113
  build_relative_branch(info, M68K_INS_BRA, 4, read_imm_32(info));
2319
113
}
2320
2321
static void d68000_bset_r(m68k_info *info)
2322
1.62k
{
2323
1.62k
  build_re_1(info, M68K_INS_BSET, 1);
2324
1.62k
}
2325
2326
static void d68000_bset_s(m68k_info *info)
2327
240
{
2328
240
  build_imm_ea(info, M68K_INS_BSET, 1, read_imm_8(info));
2329
240
}
2330
2331
static void d68000_bsr_8(m68k_info *info)
2332
1.10k
{
2333
1.10k
  build_relative_branch(info, M68K_INS_BSR, 1, make_int_8(info->ir));
2334
1.10k
}
2335
2336
static void d68000_bsr_16(m68k_info *info)
2337
350
{
2338
350
  build_relative_branch(info, M68K_INS_BSR, 2,
2339
350
            make_int_16(read_imm_16(info)));
2340
350
}
2341
2342
static void d68020_bsr_32(m68k_info *info)
2343
758
{
2344
758
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_B |
2345
758
            CS_MODE_M68K_CF_ISA_C);
2346
272
  build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info));
2347
272
}
2348
2349
static void d68000_btst_r(m68k_info *info)
2350
3.21k
{
2351
3.21k
  build_re_1(info, M68K_INS_BTST, 2);
2352
3.21k
  ISIZE = 1;
2353
3.21k
}
2354
2355
static void d68000_btst_s(m68k_info *info)
2356
168
{
2357
168
  build_imm_ea(info, M68K_INS_BTST, 1, read_imm_8(info));
2358
168
}
2359
2360
static void d68020_callm(m68k_info *info)
2361
57
{
2362
57
  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
75
{
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
75
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2374
42
  build_d_d_ea(info, M68K_INS_CAS, 1);
2375
42
}
2376
2377
static void d68020_cas_16(m68k_info *info)
2378
50
{
2379
50
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2380
40
  build_d_d_ea(info, M68K_INS_CAS, 2);
2381
40
}
2382
2383
static void d68020_cas_32(m68k_info *info)
2384
182
{
2385
182
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2386
81
  build_d_d_ea(info, M68K_INS_CAS, 4);
2387
81
}
2388
2389
static void d68020_cas2_16(m68k_info *info)
2390
144
{
2391
144
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2392
74
  build_cas2(info, 2);
2393
74
}
2394
2395
static void d68020_cas2_32(m68k_info *info)
2396
154
{
2397
154
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2398
99
  build_cas2(info, 4);
2399
99
}
2400
2401
static void d68000_chk_16(m68k_info *info)
2402
424
{
2403
424
  build_er_1(info, M68K_INS_CHK, 2);
2404
424
}
2405
2406
static void d68020_chk_32(m68k_info *info)
2407
946
{
2408
946
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
2409
640
  build_er_1(info, M68K_INS_CHK, 4);
2410
640
}
2411
2412
static void d68020_chk2_cmp2_8(m68k_info *info)
2413
218
{
2414
218
  LIMIT_FEATURE(info, M68020_PLUS);
2415
112
  build_chk2_cmp2(info, 1);
2416
112
}
2417
2418
static void d68020_chk2_cmp2_16(m68k_info *info)
2419
112
{
2420
112
  LIMIT_FEATURE(info, M68020_PLUS);
2421
43
  build_chk2_cmp2(info, 2);
2422
43
}
2423
2424
static void d68020_chk2_cmp2_32(m68k_info *info)
2425
198
{
2426
198
  LIMIT_FEATURE(info, M68020_PLUS);
2427
75
  build_chk2_cmp2(info, 4);
2428
75
}
2429
2430
static void d68040_cinv(m68k_info *info)
2431
438
{
2432
438
  LIMIT_FEATURE(info, M68040_PLUS);
2433
301
  build_cpush_cinv(info, M68K_INS_CINVL);
2434
301
}
2435
2436
static void d68000_clr_8(m68k_info *info)
2437
63
{
2438
63
  build_ea(info, M68K_INS_CLR, 1);
2439
63
}
2440
2441
static void d68000_clr_16(m68k_info *info)
2442
310
{
2443
310
  build_ea(info, M68K_INS_CLR, 2);
2444
310
}
2445
2446
static void d68000_clr_32(m68k_info *info)
2447
121
{
2448
121
  build_ea(info, M68K_INS_CLR, 4);
2449
121
}
2450
2451
static void d68000_cmp_8(m68k_info *info)
2452
391
{
2453
391
  build_er_1(info, M68K_INS_CMP, 1);
2454
391
}
2455
2456
static void d68000_cmp_16(m68k_info *info)
2457
297
{
2458
297
  build_er_1(info, M68K_INS_CMP, 2);
2459
297
}
2460
2461
static void d68000_cmp_32(m68k_info *info)
2462
716
{
2463
716
  build_er_1(info, M68K_INS_CMP, 4);
2464
716
}
2465
2466
static void d68000_cmpa_16(m68k_info *info)
2467
452
{
2468
452
  build_ea_a(info, M68K_INS_CMPA, 2);
2469
452
}
2470
2471
static void d68000_cmpa_32(m68k_info *info)
2472
405
{
2473
405
  build_ea_a(info, M68K_INS_CMPA, 4);
2474
405
}
2475
2476
static void d68000_cmpi_8(m68k_info *info)
2477
312
{
2478
312
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2479
312
}
2480
2481
static void d68020_cmpi_pcdi_8(m68k_info *info)
2482
164
{
2483
164
  LIMIT_FEATURE(info, M68010_PLUS);
2484
96
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2485
96
}
2486
2487
static void d68020_cmpi_pcix_8(m68k_info *info)
2488
155
{
2489
155
  LIMIT_FEATURE(info, M68010_PLUS);
2490
59
  build_imm_ea(info, M68K_INS_CMPI, 1, read_imm_8(info));
2491
59
}
2492
2493
static void d68000_cmpi_16(m68k_info *info)
2494
143
{
2495
143
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2496
143
}
2497
2498
static void d68020_cmpi_pcdi_16(m68k_info *info)
2499
120
{
2500
120
  LIMIT_FEATURE(info, M68010_PLUS);
2501
65
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2502
65
}
2503
2504
static void d68020_cmpi_pcix_16(m68k_info *info)
2505
207
{
2506
207
  LIMIT_FEATURE(info, M68010_PLUS);
2507
51
  build_imm_ea(info, M68K_INS_CMPI, 2, read_imm_16(info));
2508
51
}
2509
2510
static void d68000_cmpi_32(m68k_info *info)
2511
212
{
2512
212
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2513
212
}
2514
2515
static void d68020_cmpi_pcdi_32(m68k_info *info)
2516
148
{
2517
148
  LIMIT_FEATURE(info, M68010_PLUS);
2518
104
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2519
104
}
2520
2521
static void d68020_cmpi_pcix_32(m68k_info *info)
2522
347
{
2523
347
  LIMIT_FEATURE(info, M68010_PLUS);
2524
282
  build_imm_ea(info, M68K_INS_CMPI, 4, read_imm_32(info));
2525
282
}
2526
2527
static void d68000_cmpm_8(m68k_info *info)
2528
108
{
2529
108
  build_pi_pi(info, M68K_INS_CMPM, 1);
2530
108
}
2531
2532
static void d68000_cmpm_16(m68k_info *info)
2533
189
{
2534
189
  build_pi_pi(info, M68K_INS_CMPM, 2);
2535
189
}
2536
2537
static void d68000_cmpm_32(m68k_info *info)
2538
71
{
2539
71
  build_pi_pi(info, M68K_INS_CMPM, 4);
2540
71
}
2541
2542
static void make_cpbcc_operand(cs_m68k_op *op, int size, int displacement)
2543
784
{
2544
784
  op->address_mode = M68K_AM_BRANCH_DISPLACEMENT;
2545
784
  op->type = M68K_OP_BR_DISP;
2546
784
  op->br_disp.disp = displacement;
2547
784
  op->br_disp.disp_size = size;
2548
784
}
2549
2550
static void d68020_cpbcc_16(m68k_info *info)
2551
1.59k
{
2552
1.59k
  cs_m68k_op *op0;
2553
1.59k
  cs_m68k *ext;
2554
1.59k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2555
1.32k
  int cpid = M68K_CPID(info);
2556
1.32k
  int cond = M68K_IR_CONDITION(info);
2557
1.32k
  if (cpid == M68K_CPID_MMU) {
2558
371
    if (cond >= M68K_PMMU_MAX_COND ||
2559
329
        m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
2560
42
      d68000_invalid(info);
2561
42
      return;
2562
42
    }
2563
949
  } else if (cpid == M68K_CPID_FPU) {
2564
353
    if (cond >= M68K_FPU_MAX_COND) {
2565
53
      d68000_invalid(info);
2566
53
      return;
2567
53
    }
2568
596
  } else {
2569
596
    d68000_invalid(info);
2570
596
    return;
2571
596
  }
2572
2573
629
  if (info->ir == 0xf280 && peek_imm_16(info) == 0) {
2574
85
    MCInst_setOpcode(info->inst, M68K_INS_FNOP);
2575
85
    info->pc += 2;
2576
85
    return;
2577
85
  }
2578
2579
544
  ext = build_init_op(info, M68K_INS_FBF, 1, 2);
2580
544
  info->inst->Opcode += M68K_FP_COND(info->ir);
2581
544
  op0 = &ext->operands[0];
2582
2583
544
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_WORD,
2584
544
         make_int_16(read_imm_16(info)));
2585
2586
544
  set_insn_group(info, M68K_GRP_JUMP);
2587
544
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2588
544
}
2589
2590
static void d68020_cpbcc_32(m68k_info *info)
2591
3.22k
{
2592
3.22k
  cs_m68k *ext;
2593
3.22k
  cs_m68k_op *op0;
2594
3.22k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2595
2.28k
  int cpid = M68K_CPID(info);
2596
2.28k
  int cond = M68K_IR_CONDITION(info);
2597
2.28k
  if (cpid == M68K_CPID_MMU) {
2598
147
    if (cond >= M68K_PMMU_MAX_COND ||
2599
113
        m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
2600
113
      d68000_invalid(info);
2601
113
      return;
2602
113
    }
2603
2.13k
  } else if (cpid == M68K_CPID_FPU) {
2604
1.12k
    if (cond >= M68K_FPU_MAX_COND) {
2605
963
      d68000_invalid(info);
2606
963
      return;
2607
963
    }
2608
1.12k
  } else {
2609
1.01k
    d68000_invalid(info);
2610
1.01k
    return;
2611
1.01k
  }
2612
2613
193
  ext = build_init_op(info, M68K_INS_FBF, 1, 4);
2614
193
  info->inst->Opcode += M68K_FP_COND(info->ir);
2615
193
  op0 = &ext->operands[0];
2616
2617
193
  make_cpbcc_operand(op0, M68K_OP_BR_DISP_SIZE_LONG, read_imm_32(info));
2618
2619
193
  set_insn_group(info, M68K_GRP_JUMP);
2620
193
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2621
193
}
2622
2623
static void d68020_cpdbcc(m68k_info *info)
2624
454
{
2625
454
  cs_m68k *ext;
2626
454
  cs_m68k_op *op0;
2627
454
  cs_m68k_op *op1;
2628
454
  uint32_t ext1, ext2;
2629
2630
454
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2631
2632
417
  if (M68K_CPID(info) == M68K_CPID_CACHE &&
2633
59
      m68k_has_feature(info, M68040_PLUS)) {
2634
59
    if (M68K_IR_IS_CPUSH(info))
2635
0
      d68040_cpush(info);
2636
59
    else
2637
59
      d68040_cinv(info);
2638
59
    return;
2639
59
  }
2640
2641
358
  REQUIRE_CPID_FPU(info);
2642
2643
47
  ext1 = read_imm_16(info);
2644
47
  ext2 = read_imm_16(info);
2645
2646
47
  info->inst->Opcode += M68K_FP_COND(ext1);
2647
2648
47
  ext = build_init_op(info, M68K_INS_FDBF, 2, 0);
2649
47
  op0 = &ext->operands[0];
2650
47
  op1 = &ext->operands[1];
2651
2652
47
  op0->reg = M68K_REG_D0 + (info->ir & 7);
2653
2654
47
  make_cpbcc_operand(op1, M68K_OP_BR_DISP_SIZE_WORD,
2655
47
         make_int_16(ext2) + 2);
2656
2657
47
  set_insn_group(info, M68K_GRP_JUMP);
2658
47
  set_insn_group(info, M68K_GRP_BRANCH_RELATIVE);
2659
47
}
2660
2661
static void fmove_fpcr(m68k_info *info, uint32_t extension)
2662
515
{
2663
515
  cs_m68k_op *special;
2664
515
  cs_m68k_op *op_ea;
2665
2666
515
  int regsel = M68K_FEXT_REGSEL(extension);
2667
515
  int dir = M68K_FEXT_DIR(extension);
2668
2669
515
  cs_m68k *ext = build_init_op(info, M68K_INS_FMOVE, 2, 4);
2670
2671
515
  special = &ext->operands[0];
2672
515
  op_ea = &ext->operands[1];
2673
2674
515
  if (!dir) {
2675
173
    cs_m68k_op *t = special;
2676
173
    special = op_ea;
2677
173
    op_ea = t;
2678
173
  }
2679
2680
515
  get_ea_mode_op(info, op_ea, info->ir, 4);
2681
2682
515
  if (regsel & 4)
2683
215
    special->reg = M68K_REG_FPCR;
2684
300
  else if (regsel & 2)
2685
42
    special->reg = M68K_REG_FPSR;
2686
258
  else if (regsel & 1)
2687
117
    special->reg = M68K_REG_FPIAR;
2688
515
}
2689
2690
static void fmovem(m68k_info *info, uint32_t extension)
2691
1.03k
{
2692
1.03k
  cs_m68k_op *op_reglist;
2693
1.03k
  cs_m68k_op *op_ea;
2694
1.03k
  int dir = M68K_FEXT_DIR(extension);
2695
1.03k
  int mode = (extension >> 11) & 0x3;
2696
1.03k
  uint32_t reglist = extension & 0xff;
2697
1.03k
  cs_m68k *ext = build_init_op(info, M68K_INS_FMOVEM, 2, 0);
2698
2699
1.03k
  op_reglist = &ext->operands[0];
2700
1.03k
  op_ea = &ext->operands[1];
2701
2702
  // flip args around
2703
2704
1.03k
  if (!dir) {
2705
437
    cs_m68k_op *t = op_reglist;
2706
437
    op_reglist = op_ea;
2707
437
    op_ea = t;
2708
437
  }
2709
2710
1.03k
  get_ea_mode_op(info, op_ea, info->ir, 0);
2711
2712
1.03k
  switch (mode) {
2713
122
  case 1: // Dynamic list in dn register
2714
122
    op_reglist->reg = M68K_REG_D0 + ((reglist >> 4) & 7);
2715
122
    break;
2716
2717
371
  case 0:
2718
371
    op_reglist->address_mode = M68K_AM_NONE;
2719
371
    op_reglist->type = M68K_OP_REG_BITS;
2720
371
    op_reglist->register_bits = reglist << 16;
2721
371
    break;
2722
2723
450
  case 2: // Static list
2724
450
    op_reglist->address_mode = M68K_AM_NONE;
2725
450
    op_reglist->type = M68K_OP_REG_BITS;
2726
450
    op_reglist->register_bits = ((uint32_t)reverse_bits_8(reglist))
2727
450
              << 16;
2728
450
    break;
2729
89
  default:
2730
89
    break;
2731
1.03k
  }
2732
1.03k
}
2733
2734
static void d68020_cpgen(m68k_info *info)
2735
6.64k
{
2736
6.64k
  cs_m68k *ext;
2737
6.64k
  cs_m68k_op *op0;
2738
6.64k
  cs_m68k_op *op1;
2739
6.64k
  bool supports_single_op;
2740
6.64k
  uint32_t next;
2741
6.64k
  int rm, src, dst, opmode;
2742
2743
6.64k
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
2744
2745
6.24k
  if (M68K_CPID(info) == M68K_CPID_MMU &&
2746
1.27k
      m68k_has_feature(info, CS_MODE_M68K_030)) {
2747
0
    d68030_pmmu(info);
2748
0
    return;
2749
0
  }
2750
2751
6.24k
  if (M68K_CPID(info) != M68K_CPID_FPU) {
2752
1.86k
    d68000_invalid(info);
2753
1.86k
    return;
2754
1.86k
  }
2755
2756
4.38k
  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
4.38k
  uint32_t peeked = peek_imm_16(info);
2763
4.38k
  if (M68K_FEXT_TYPE(peeked) <= 1 && M68K_FEXT_SD_FLAG(peeked))
2764
496
    LIMIT_FEATURE(info, M68040_PLUS | CS_MODE_M68K_CF_FPU);
2765
2766
4.38k
  next = read_imm_16(info);
2767
2768
4.38k
  rm = M68K_FEXT_RM(next);
2769
4.38k
  src = M68K_FEXT_SRC(next);
2770
4.38k
  dst = M68K_FEXT_DST(next);
2771
4.38k
  opmode = M68K_FEXT_OPMODE(next);
2772
2773
4.38k
  if (BITFIELD(info->ir, 5, 0) == 0 && M68K_FEXT_IS_FMOVECR(next)) {
2774
86
    ext = build_init_op(info, M68K_INS_FMOVECR, 2, 0);
2775
2776
86
    op0 = &ext->operands[0];
2777
86
    op1 = &ext->operands[1];
2778
2779
86
    op0->address_mode = M68K_AM_IMMEDIATE;
2780
86
    op0->type = M68K_OP_IMM;
2781
86
    op0->imm = M68K_FEXT_OPMODE(next);
2782
2783
86
    op1->reg = M68K_REG_FP0 + M68K_FEXT_DST(next);
2784
2785
86
    return;
2786
86
  }
2787
2788
4.29k
  switch (M68K_FEXT_TYPE(next)) {
2789
173
  case 0x4:
2790
515
  case 0x5:
2791
515
    fmove_fpcr(info, next);
2792
515
    return;
2793
2794
437
  case 0x6:
2795
1.03k
  case 0x7:
2796
1.03k
    fmovem(info, next);
2797
1.03k
    return;
2798
2.74k
  default:
2799
2.74k
    break;
2800
4.29k
  }
2801
2802
2.74k
  if (M68K_FEXT_SD_FLAG(next)) {
2803
860
    if (opmode == M68K_FPOP_FSSQRT_RAW) {
2804
15
      MCInst_setOpcode(info->inst, M68K_INS_FSSQRT);
2805
15
      goto fpu_operands;
2806
845
    } else if (opmode == M68K_FPOP_FDSQRT_RAW) {
2807
11
      MCInst_setOpcode(info->inst, M68K_INS_FDSQRT);
2808
11
      goto fpu_operands;
2809
11
    }
2810
834
    opmode &= ~4;
2811
834
  }
2812
2813
2.72k
  switch (opmode) {
2814
188
  case 0x00:
2815
188
    MCInst_setOpcode(info->inst, M68K_INS_FMOVE);
2816
188
    supports_single_op = false;
2817
188
    break;
2818
41
  case 0x01:
2819
41
    MCInst_setOpcode(info->inst, M68K_INS_FINT);
2820
41
    break;
2821
58
  case 0x02:
2822
58
    MCInst_setOpcode(info->inst, M68K_INS_FSINH);
2823
58
    break;
2824
12
  case 0x03:
2825
12
    MCInst_setOpcode(info->inst, M68K_INS_FINTRZ);
2826
12
    break;
2827
61
  case 0x04:
2828
61
    MCInst_setOpcode(info->inst, M68K_INS_FSQRT);
2829
61
    break;
2830
13
  case 0x06:
2831
13
    MCInst_setOpcode(info->inst, M68K_INS_FLOGNP1);
2832
13
    break;
2833
113
  case 0x08:
2834
113
    MCInst_setOpcode(info->inst, M68K_INS_FETOXM1);
2835
113
    break;
2836
242
  case 0x09:
2837
242
    MCInst_setOpcode(info->inst, M68K_INS_FATANH);
2838
242
    break;
2839
159
  case 0x0a:
2840
159
    MCInst_setOpcode(info->inst, M68K_INS_FATAN);
2841
159
    break;
2842
3
  case 0x0c:
2843
3
    MCInst_setOpcode(info->inst, M68K_INS_FASIN);
2844
3
    break;
2845
17
  case 0x0d:
2846
17
    MCInst_setOpcode(info->inst, M68K_INS_FATANH);
2847
17
    break;
2848
10
  case 0x0e:
2849
10
    MCInst_setOpcode(info->inst, M68K_INS_FSIN);
2850
10
    break;
2851
3
  case 0x0f:
2852
3
    MCInst_setOpcode(info->inst, M68K_INS_FTAN);
2853
3
    break;
2854
51
  case 0x10:
2855
51
    MCInst_setOpcode(info->inst, M68K_INS_FETOX);
2856
51
    break;
2857
83
  case 0x11:
2858
83
    MCInst_setOpcode(info->inst, M68K_INS_FTWOTOX);
2859
83
    break;
2860
19
  case 0x12:
2861
19
    MCInst_setOpcode(info->inst, M68K_INS_FTENTOX);
2862
19
    break;
2863
25
  case 0x14:
2864
25
    MCInst_setOpcode(info->inst, M68K_INS_FLOGN);
2865
25
    break;
2866
23
  case 0x15:
2867
23
    MCInst_setOpcode(info->inst, M68K_INS_FLOG10);
2868
23
    break;
2869
155
  case 0x16:
2870
155
    MCInst_setOpcode(info->inst, M68K_INS_FLOG2);
2871
155
    break;
2872
10
  case 0x18:
2873
10
    MCInst_setOpcode(info->inst, M68K_INS_FABS);
2874
10
    break;
2875
9
  case 0x19:
2876
9
    MCInst_setOpcode(info->inst, M68K_INS_FCOSH);
2877
9
    break;
2878
18
  case 0x1a:
2879
18
    MCInst_setOpcode(info->inst, M68K_INS_FNEG);
2880
18
    break;
2881
21
  case 0x1c:
2882
21
    MCInst_setOpcode(info->inst, M68K_INS_FACOS);
2883
21
    break;
2884
3
  case 0x1d:
2885
3
    MCInst_setOpcode(info->inst, M68K_INS_FCOS);
2886
3
    break;
2887
287
  case 0x1e:
2888
287
    MCInst_setOpcode(info->inst, M68K_INS_FGETEXP);
2889
287
    break;
2890
15
  case 0x1f:
2891
15
    MCInst_setOpcode(info->inst, M68K_INS_FGETMAN);
2892
15
    break;
2893
153
  case 0x20:
2894
153
    MCInst_setOpcode(info->inst, M68K_INS_FDIV);
2895
153
    supports_single_op = false;
2896
153
    break;
2897
32
  case 0x21:
2898
32
    MCInst_setOpcode(info->inst, M68K_INS_FMOD);
2899
32
    supports_single_op = false;
2900
32
    break;
2901
30
  case 0x22:
2902
30
    MCInst_setOpcode(info->inst, M68K_INS_FADD);
2903
30
    supports_single_op = false;
2904
30
    break;
2905
15
  case 0x23:
2906
15
    MCInst_setOpcode(info->inst, M68K_INS_FMUL);
2907
15
    supports_single_op = false;
2908
15
    break;
2909
80
  case 0x24:
2910
80
    MCInst_setOpcode(info->inst, M68K_INS_FSGLDIV);
2911
80
    supports_single_op = false;
2912
80
    break;
2913
284
  case 0x25:
2914
284
    MCInst_setOpcode(info->inst, M68K_INS_FREM);
2915
284
    break;
2916
46
  case 0x26:
2917
46
    MCInst_setOpcode(info->inst, M68K_INS_FSCALE);
2918
46
    break;
2919
0
  case 0x27:
2920
0
    MCInst_setOpcode(info->inst, M68K_INS_FSGLMUL);
2921
0
    break;
2922
16
  case 0x28:
2923
16
    MCInst_setOpcode(info->inst, M68K_INS_FSUB);
2924
16
    supports_single_op = false;
2925
16
    break;
2926
11
  case 0x38:
2927
11
    MCInst_setOpcode(info->inst, M68K_INS_FCMP);
2928
11
    supports_single_op = false;
2929
11
    break;
2930
8
  case 0x3a:
2931
8
    MCInst_setOpcode(info->inst, M68K_INS_FTST);
2932
8
    break;
2933
407
  default:
2934
407
    break;
2935
2.72k
  }
2936
2937
2.72k
  if (M68K_FEXT_SD_FLAG(next)) {
2938
834
    if ((next >> 2) & 1)
2939
546
      info->inst->Opcode += 2;
2940
288
    else
2941
288
      info->inst->Opcode += 1;
2942
834
  }
2943
2944
2.74k
fpu_operands:
2945
2.74k
  ext = &info->extension;
2946
2947
2.74k
  ext->op_count = 2;
2948
2.74k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
2949
2.74k
  ext->op_size.cpu_size = 0;
2950
2951
2.74k
  if ((opmode == 0x00) && M68K_FEXT_DIR(next) != 0) {
2952
81
    op0 = &ext->operands[1];
2953
81
    op1 = &ext->operands[0];
2954
2.66k
  } else {
2955
2.66k
    op0 = &ext->operands[0];
2956
2.66k
    op1 = &ext->operands[1];
2957
2.66k
  }
2958
2959
2.74k
  if (rm == 0 && supports_single_op && src == dst) {
2960
353
    ext->op_count = 1;
2961
353
    op0->reg = M68K_REG_FP0 + dst;
2962
353
    return;
2963
353
  }
2964
2965
2.39k
  if (rm == 1) {
2966
1.04k
    switch (src) {
2967
103
    case M68K_FPSRC_LONG:
2968
103
      ext->op_size.cpu_size = M68K_CPU_SIZE_LONG;
2969
103
      get_ea_mode_op(info, op0, info->ir, 4);
2970
103
      break;
2971
2972
102
    case M68K_FPSRC_BYTE:
2973
102
      ext->op_size.cpu_size = M68K_CPU_SIZE_BYTE;
2974
102
      get_ea_mode_op(info, op0, info->ir, 1);
2975
102
      break;
2976
2977
52
    case M68K_FPSRC_WORD:
2978
52
      ext->op_size.cpu_size = M68K_CPU_SIZE_WORD;
2979
52
      get_ea_mode_op(info, op0, info->ir, 2);
2980
52
      break;
2981
2982
306
    case M68K_FPSRC_SINGLE:
2983
306
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
2984
306
      ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE;
2985
306
      get_ea_mode_op(info, op0, info->ir, 4);
2986
306
      if (op0->address_mode == M68K_AM_IMMEDIATE) {
2987
3
        op0->simm = BitsToFloat(op0->imm);
2988
3
        op0->type = M68K_OP_FP_SINGLE;
2989
3
      }
2990
306
      break;
2991
2992
74
    case M68K_FPSRC_DOUBLE:
2993
74
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
2994
74
      ext->op_size.fpu_size = M68K_FPU_SIZE_DOUBLE;
2995
74
      get_ea_mode_op(info, op0, info->ir, 8);
2996
74
      if (op0->address_mode == M68K_AM_IMMEDIATE)
2997
28
        op0->type = M68K_OP_FP_DOUBLE;
2998
74
      break;
2999
3000
132
    case M68K_FPSRC_EXTENDED:
3001
132
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3002
132
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3003
132
      get_ea_mode_op(info, op0, info->ir, 12);
3004
132
      break;
3005
3006
172
    case M68K_FPSRC_PACKED:
3007
172
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3008
172
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3009
172
      get_ea_mode_op(info, op0, info->ir, 12);
3010
172
      break;
3011
3012
107
    default:
3013
107
      ext->op_size.type = M68K_SIZE_TYPE_FPU;
3014
107
      ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED;
3015
107
      break;
3016
1.04k
    }
3017
1.34k
  } else {
3018
1.34k
    op0->reg = M68K_REG_FP0 + src;
3019
1.34k
  }
3020
3021
2.39k
  op1->reg = M68K_REG_FP0 + dst;
3022
2.39k
}
3023
3024
static void d68020_cprestore(m68k_info *info)
3025
373
{
3026
373
  cs_m68k *ext;
3027
373
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3028
138
  REQUIRE_CPID_FPU(info);
3029
3030
44
  ext = build_init_op(info, M68K_INS_FRESTORE, 1, 0);
3031
44
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
3032
44
}
3033
3034
static void d68020_cpsave(m68k_info *info)
3035
992
{
3036
992
  cs_m68k *ext;
3037
992
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3038
282
  REQUIRE_CPID_FPU(info);
3039
3040
65
  ext = build_init_op(info, M68K_INS_FSAVE, 1, 0);
3041
65
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
3042
65
}
3043
3044
static void d68040_pflush_or_cpsave(m68k_info *info)
3045
103
{
3046
103
  if (m68k_has_feature(info, M68040_PLUS)) {
3047
19
    d68040_pflush(info);
3048
19
    return;
3049
19
  }
3050
84
  d68020_cpsave(info);
3051
84
}
3052
3053
static void d68040_ptest_or_cprestore(m68k_info *info)
3054
205
{
3055
205
  if (m68k_has_feature(info, CS_MODE_M68K_040)) {
3056
117
    d68040_ptest(info);
3057
117
    return;
3058
117
  }
3059
88
  if (m68k_has_feature(info, CS_MODE_M68K_060)) {
3060
0
    d68000_invalid(info);
3061
0
    return;
3062
0
  }
3063
88
  d68020_cprestore(info);
3064
88
}
3065
3066
static void d68020_cpscc(m68k_info *info)
3067
498
{
3068
498
  cs_m68k *ext;
3069
498
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3070
399
  REQUIRE_CPID_FPU(info);
3071
85
  ext = build_init_op(info, M68K_INS_FSF, 1, 1);
3072
85
  info->inst->Opcode += M68K_FP_COND(read_imm_16(info));
3073
3074
85
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
3075
85
}
3076
3077
static void d68020_cptrapcc_0(m68k_info *info)
3078
265
{
3079
265
  uint32_t extension1;
3080
265
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3081
128
  REQUIRE_CPID_FPU(info);
3082
3083
106
  extension1 = read_imm_16(info);
3084
3085
106
  build_init_op(info, M68K_INS_FTRAPF, 0, 0);
3086
106
  info->inst->Opcode += M68K_FP_COND(extension1);
3087
106
}
3088
3089
static void d68020_cptrapcc_16(m68k_info *info)
3090
196
{
3091
196
  uint32_t extension1, extension2;
3092
196
  cs_m68k_op *op0;
3093
196
  cs_m68k *ext;
3094
196
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3095
104
  REQUIRE_CPID_FPU(info);
3096
3097
86
  extension1 = read_imm_16(info);
3098
86
  extension2 = read_imm_16(info);
3099
3100
86
  ext = build_init_op(info, M68K_INS_FTRAPF, 1, 2);
3101
86
  info->inst->Opcode += M68K_FP_COND(extension1);
3102
3103
86
  op0 = &ext->operands[0];
3104
3105
86
  op0->address_mode = M68K_AM_IMMEDIATE;
3106
86
  op0->type = M68K_OP_IMM;
3107
86
  op0->imm = extension2;
3108
86
}
3109
3110
static void d68020_cptrapcc_32(m68k_info *info)
3111
251
{
3112
251
  uint32_t extension1, extension2;
3113
251
  cs_m68k *ext;
3114
251
  cs_m68k_op *op0;
3115
251
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_FPU);
3116
243
  REQUIRE_CPID_FPU(info);
3117
3118
221
  extension1 = read_imm_16(info);
3119
221
  extension2 = read_imm_32(info);
3120
3121
221
  ext = build_init_op(info, M68K_INS_FTRAPF, 1, 2);
3122
221
  info->inst->Opcode += M68K_FP_COND(extension1);
3123
3124
221
  op0 = &ext->operands[0];
3125
3126
221
  op0->address_mode = M68K_AM_IMMEDIATE;
3127
221
  op0->type = M68K_OP_IMM;
3128
221
  op0->imm = extension2;
3129
221
}
3130
3131
static void d68040_cpush(m68k_info *info)
3132
740
{
3133
740
  LIMIT_FEATURE(info, M68040_PLUS | CS_MODE_M68K_CF_ISA_A);
3134
302
  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
302
  build_cpush_cinv(info, M68K_INS_CPUSHL);
3140
302
}
3141
3142
static void d68000_dbra(m68k_info *info)
3143
297
{
3144
297
  build_dbxx(info, M68K_INS_DBRA, 0, make_int_16(read_imm_16(info)));
3145
297
}
3146
3147
static void d68000_dbcc(m68k_info *info)
3148
314
{
3149
314
  build_dbcc(info, 0, make_int_16(read_imm_16(info)));
3150
314
}
3151
3152
static void d68000_divs(m68k_info *info)
3153
655
{
3154
655
  build_er_1(info, M68K_INS_DIVS, 2);
3155
655
}
3156
3157
static void d68000_divu(m68k_info *info)
3158
518
{
3159
518
  build_er_1(info, M68K_INS_DIVU, 2);
3160
518
}
3161
3162
static void d68020_divl(m68k_info *info)
3163
207
{
3164
207
  uint32_t extension, insn_signed;
3165
207
  bool cf_remainder;
3166
207
  cs_m68k *ext;
3167
207
  cs_m68k_op *op0;
3168
207
  cs_m68k_op *op1;
3169
207
  uint32_t reg_0, reg_1;
3170
207
  m68k_insn opcode;
3171
3172
207
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_DIV);
3173
3174
121
  extension = read_imm_16(info);
3175
121
  insn_signed = 0;
3176
3177
121
  if (BIT_B((extension)))
3178
33
    insn_signed = 1;
3179
3180
121
  reg_0 = extension & 7;
3181
121
  reg_1 = (extension >> 12) & 7;
3182
121
  cf_remainder = m68k_has_feature(info, CS_MODE_M68K_CF_DIV) &&
3183
0
           !BIT_A(extension) && (reg_0 != reg_1);
3184
3185
121
  if (cf_remainder)
3186
0
    opcode = insn_signed ? M68K_INS_REMS : M68K_INS_REMU;
3187
121
  else
3188
121
    opcode = insn_signed ? M68K_INS_DIVS : M68K_INS_DIVU;
3189
3190
121
  ext = build_init_op(info, opcode, 2, 4);
3191
121
  op0 = &ext->operands[0];
3192
121
  op1 = &ext->operands[1];
3193
3194
121
  get_ea_mode_op(info, op0, info->ir, 4);
3195
3196
121
  op1->address_mode = M68K_AM_NONE;
3197
121
  op1->type = M68K_OP_REG_PAIR;
3198
121
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
3199
121
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
3200
3201
121
  if ((reg_0 == reg_1) || (!BIT_A(extension) && !cf_remainder)) {
3202
88
    op1->type = M68K_OP_REG;
3203
88
    op1->reg = M68K_REG_D0 + reg_1;
3204
88
  }
3205
121
}
3206
3207
static void d68000_eor_8(m68k_info *info)
3208
292
{
3209
292
  build_re_1(info, M68K_INS_EOR, 1);
3210
292
}
3211
3212
static void d68000_eor_16(m68k_info *info)
3213
456
{
3214
456
  build_re_1(info, M68K_INS_EOR, 2);
3215
456
}
3216
3217
static void d68000_eor_32(m68k_info *info)
3218
847
{
3219
847
  build_re_1(info, M68K_INS_EOR, 4);
3220
847
}
3221
3222
static void d68000_eori_8(m68k_info *info)
3223
208
{
3224
208
  build_imm_ea(info, M68K_INS_EORI, 1, read_imm_8(info));
3225
208
}
3226
3227
static void d68000_eori_16(m68k_info *info)
3228
124
{
3229
124
  build_imm_ea(info, M68K_INS_EORI, 2, read_imm_16(info));
3230
124
}
3231
3232
static void d68000_eori_32(m68k_info *info)
3233
346
{
3234
346
  build_imm_ea(info, M68K_INS_EORI, 4, read_imm_32(info));
3235
346
}
3236
3237
static void d68000_eori_to_ccr(m68k_info *info)
3238
117
{
3239
117
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_8(info), 1,
3240
117
            M68K_REG_CCR);
3241
117
}
3242
3243
static void d68000_eori_to_sr(m68k_info *info)
3244
65
{
3245
65
  build_imm_special_reg(info, M68K_INS_EORI, read_imm_16(info), 2,
3246
65
            M68K_REG_SR);
3247
65
}
3248
3249
static void d68000_exg_dd(m68k_info *info)
3250
289
{
3251
289
  build_r(info, M68K_INS_EXG, 4);
3252
289
}
3253
3254
static void d68000_exg_aa(m68k_info *info)
3255
386
{
3256
386
  cs_m68k_op *op0;
3257
386
  cs_m68k_op *op1;
3258
386
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3259
3260
386
  op0 = &ext->operands[0];
3261
386
  op1 = &ext->operands[1];
3262
3263
386
  op0->address_mode = M68K_AM_NONE;
3264
386
  op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7);
3265
3266
386
  op1->address_mode = M68K_AM_NONE;
3267
386
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3268
386
}
3269
3270
static void d68000_exg_da(m68k_info *info)
3271
559
{
3272
559
  cs_m68k_op *op0;
3273
559
  cs_m68k_op *op1;
3274
559
  cs_m68k *ext = build_init_op(info, M68K_INS_EXG, 2, 4);
3275
3276
559
  op0 = &ext->operands[0];
3277
559
  op1 = &ext->operands[1];
3278
3279
559
  op0->address_mode = M68K_AM_NONE;
3280
559
  op0->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3281
3282
559
  op1->address_mode = M68K_AM_NONE;
3283
559
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3284
559
}
3285
3286
static void d68000_ext_16(m68k_info *info)
3287
116
{
3288
116
  build_d(info, M68K_INS_EXT, 2);
3289
116
}
3290
3291
static void d68000_ext_32(m68k_info *info)
3292
100
{
3293
100
  build_d(info, M68K_INS_EXT, 4);
3294
100
}
3295
3296
static void d68020_extb_32(m68k_info *info)
3297
515
{
3298
515
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
3299
113
  build_d(info, M68K_INS_EXTB, 4);
3300
113
}
3301
3302
static void d68000_jmp(m68k_info *info)
3303
260
{
3304
260
  cs_m68k *ext = build_init_op(info, M68K_INS_JMP, 1, 0);
3305
260
  set_insn_group(info, M68K_GRP_JUMP);
3306
260
  get_ea_mode_op(info, &ext->operands[0], info->ir, 4);
3307
260
}
3308
3309
static void d68000_jsr(m68k_info *info)
3310
411
{
3311
411
  cs_m68k *ext = build_init_op(info, M68K_INS_JSR, 1, 0);
3312
411
  set_insn_group(info, M68K_GRP_JUMP);
3313
411
  get_ea_mode_op(info, &ext->operands[0], info->ir, 4);
3314
411
}
3315
3316
static void d68000_lea(m68k_info *info)
3317
259
{
3318
259
  build_ea_a(info, M68K_INS_LEA, 4);
3319
259
}
3320
3321
static void d68000_link_16(m68k_info *info)
3322
385
{
3323
385
  build_link(info, read_imm_16(info), 2);
3324
385
}
3325
3326
static void d68020_link_32(m68k_info *info)
3327
971
{
3328
971
  LIMIT_FEATURE(info, M68020_PLUS);
3329
752
  build_link(info, read_imm_32(info), 4);
3330
752
}
3331
3332
static void d68000_lsr_s_8(m68k_info *info)
3333
172
{
3334
172
  build_3bit_d(info, M68K_INS_LSR, 1);
3335
172
}
3336
3337
static void d68000_lsr_s_16(m68k_info *info)
3338
357
{
3339
357
  build_3bit_d(info, M68K_INS_LSR, 2);
3340
357
}
3341
3342
static void d68000_lsr_s_32(m68k_info *info)
3343
84
{
3344
84
  build_3bit_d(info, M68K_INS_LSR, 4);
3345
84
}
3346
3347
static void d68000_lsr_r_8(m68k_info *info)
3348
93
{
3349
93
  build_r(info, M68K_INS_LSR, 1);
3350
93
}
3351
3352
static void d68000_lsr_r_16(m68k_info *info)
3353
70
{
3354
70
  build_r(info, M68K_INS_LSR, 2);
3355
70
}
3356
3357
static void d68000_lsr_r_32(m68k_info *info)
3358
213
{
3359
213
  build_r(info, M68K_INS_LSR, 4);
3360
213
}
3361
3362
static void d68000_lsr_ea(m68k_info *info)
3363
255
{
3364
255
  build_ea(info, M68K_INS_LSR, 2);
3365
255
}
3366
3367
static void d68000_lsl_s_8(m68k_info *info)
3368
72
{
3369
72
  build_3bit_d(info, M68K_INS_LSL, 1);
3370
72
}
3371
3372
static void d68000_lsl_s_16(m68k_info *info)
3373
240
{
3374
240
  build_3bit_d(info, M68K_INS_LSL, 2);
3375
240
}
3376
3377
static void d68000_lsl_s_32(m68k_info *info)
3378
30
{
3379
30
  build_3bit_d(info, M68K_INS_LSL, 4);
3380
30
}
3381
3382
static void d68000_lsl_r_8(m68k_info *info)
3383
129
{
3384
129
  build_r(info, M68K_INS_LSL, 1);
3385
129
}
3386
3387
static void d68000_lsl_r_16(m68k_info *info)
3388
248
{
3389
248
  build_r(info, M68K_INS_LSL, 2);
3390
248
}
3391
3392
static void d68000_lsl_r_32(m68k_info *info)
3393
386
{
3394
386
  build_r(info, M68K_INS_LSL, 4);
3395
386
}
3396
3397
static void d68000_lsl_ea(m68k_info *info)
3398
545
{
3399
545
  build_ea(info, M68K_INS_LSL, 2);
3400
545
}
3401
3402
static void d68000_move_8(m68k_info *info)
3403
6.03k
{
3404
6.03k
  build_ea_ea(info, M68K_INS_MOVE, 1);
3405
6.03k
}
3406
3407
static void d68000_move_16(m68k_info *info)
3408
5.88k
{
3409
5.88k
  build_ea_ea(info, M68K_INS_MOVE, 2);
3410
5.88k
}
3411
3412
static void d68000_move_32(m68k_info *info)
3413
9.88k
{
3414
9.88k
  build_ea_ea(info, M68K_INS_MOVE, 4);
3415
9.88k
}
3416
3417
static void d68000_movea_16(m68k_info *info)
3418
1.55k
{
3419
1.55k
  build_ea_a(info, M68K_INS_MOVEA, 2);
3420
1.55k
}
3421
3422
static void d68000_movea_32(m68k_info *info)
3423
1.41k
{
3424
1.41k
  build_ea_a(info, M68K_INS_MOVEA, 4);
3425
1.41k
}
3426
3427
static void d68000_move_to_ccr(m68k_info *info)
3428
172
{
3429
172
  cs_m68k_op *op0;
3430
172
  cs_m68k_op *op1;
3431
172
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3432
3433
172
  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
172
  op0 = &ext->operands[0];
3441
172
  op1 = &ext->operands[1];
3442
3443
172
  get_ea_mode_op(info, op0, info->ir, 1);
3444
3445
172
  op1->address_mode = M68K_AM_NONE;
3446
172
  op1->reg = M68K_REG_CCR;
3447
172
}
3448
3449
static void d68010_move_fr_ccr(m68k_info *info)
3450
241
{
3451
241
  cs_m68k_op *op0;
3452
241
  cs_m68k_op *op1;
3453
241
  cs_m68k *ext;
3454
3455
241
  LIMIT_FEATURE(info, M68010_PLUS | CS_MODE_M68K_CF_ISA_A);
3456
3457
166
  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
166
  ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3464
3465
166
  op0 = &ext->operands[0];
3466
166
  op1 = &ext->operands[1];
3467
3468
166
  op0->address_mode = M68K_AM_NONE;
3469
166
  op0->reg = M68K_REG_CCR;
3470
3471
166
  get_ea_mode_op(info, op1, info->ir, 1);
3472
166
}
3473
3474
static void d68000_move_fr_sr(m68k_info *info)
3475
467
{
3476
467
  cs_m68k_op *op0;
3477
467
  cs_m68k_op *op1;
3478
467
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3479
3480
467
  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
467
  op0 = &ext->operands[0];
3488
467
  op1 = &ext->operands[1];
3489
3490
467
  op0->address_mode = M68K_AM_NONE;
3491
467
  op0->reg = M68K_REG_SR;
3492
3493
467
  get_ea_mode_op(info, op1, info->ir, 2);
3494
467
}
3495
3496
static void d68000_move_to_sr(m68k_info *info)
3497
145
{
3498
145
  cs_m68k_op *op0;
3499
145
  cs_m68k_op *op1;
3500
145
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 2);
3501
3502
145
  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
145
  op0 = &ext->operands[0];
3510
145
  op1 = &ext->operands[1];
3511
3512
145
  get_ea_mode_op(info, op0, info->ir, 2);
3513
3514
145
  op1->address_mode = M68K_AM_NONE;
3515
145
  op1->reg = M68K_REG_SR;
3516
145
}
3517
3518
static void d68000_move_fr_usp(m68k_info *info)
3519
14
{
3520
14
  cs_m68k_op *op0;
3521
14
  cs_m68k_op *op1;
3522
14
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
3523
3524
14
  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
14
  op0 = &ext->operands[0];
3531
14
  op1 = &ext->operands[1];
3532
3533
14
  op0->address_mode = M68K_AM_NONE;
3534
14
  op0->reg = M68K_REG_USP;
3535
3536
14
  op1->address_mode = M68K_AM_NONE;
3537
14
  op1->reg = M68K_REG_A0 + (info->ir & 7);
3538
14
}
3539
3540
static void d68000_move_to_usp(m68k_info *info)
3541
109
{
3542
109
  cs_m68k_op *op0;
3543
109
  cs_m68k_op *op1;
3544
109
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVE, 2, 0);
3545
3546
109
  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
109
  op0 = &ext->operands[0];
3553
109
  op1 = &ext->operands[1];
3554
3555
109
  op0->address_mode = M68K_AM_NONE;
3556
109
  op0->reg = M68K_REG_A0 + (info->ir & 7);
3557
3558
109
  op1->address_mode = M68K_AM_NONE;
3559
109
  op1->reg = M68K_REG_USP;
3560
109
}
3561
3562
static void d68010_movec(m68k_info *info)
3563
2.44k
{
3564
2.44k
  uint32_t extension;
3565
2.44k
  m68k_reg reg;
3566
2.44k
  cs_m68k *ext;
3567
2.44k
  cs_m68k_op *op0;
3568
2.44k
  cs_m68k_op *op1;
3569
3570
2.44k
  LIMIT_FEATURE(info, M68010_PLUS | CS_MODE_M68K_CF_ISA_A);
3571
3572
2.26k
  extension = read_imm_16(info);
3573
2.26k
  reg = M68K_REG_INVALID;
3574
3575
2.26k
  ext = build_init_op(info, M68K_INS_MOVEC, 2, 0);
3576
3577
2.26k
  op0 = &ext->operands[0];
3578
2.26k
  op1 = &ext->operands[1];
3579
3580
2.26k
  switch (extension & 0xfff) {
3581
27
  case 0x000:
3582
27
    reg = M68K_REG_SFC;
3583
27
    break;
3584
71
  case 0x001:
3585
71
    reg = M68K_REG_DFC;
3586
71
    break;
3587
71
  case 0x800:
3588
71
    reg = M68K_REG_USP;
3589
71
    break;
3590
477
  case 0x801:
3591
477
    reg = M68K_REG_VBR;
3592
477
    break;
3593
110
  case 0x002:
3594
110
    reg = M68K_REG_CACR;
3595
110
    break;
3596
36
  case 0x802:
3597
36
    reg = M68K_REG_CAAR;
3598
36
    break;
3599
378
  case 0x803:
3600
378
    reg = M68K_REG_MSP;
3601
378
    break;
3602
21
  case 0x804:
3603
21
    reg = M68K_REG_ISP;
3604
21
    break;
3605
130
  case 0x003:
3606
130
    reg = M68K_REG_TC;
3607
130
    break;
3608
136
  case 0x004:
3609
136
    reg = M68K_REG_ITT0;
3610
136
    break;
3611
70
  case 0x005:
3612
70
    reg = M68K_REG_ITT1;
3613
70
    break;
3614
18
  case 0x006:
3615
18
    reg = M68K_REG_DTT0;
3616
18
    break;
3617
73
  case 0x007:
3618
73
    reg = M68K_REG_DTT1;
3619
73
    break;
3620
73
  case 0x805:
3621
73
    reg = M68K_REG_MMUSR;
3622
73
    break;
3623
29
  case 0x806:
3624
29
    reg = M68K_REG_URP;
3625
29
    break;
3626
160
  case 0x807:
3627
160
    reg = M68K_REG_SRP;
3628
160
    break;
3629
387
  default:
3630
387
    break;
3631
2.26k
  }
3632
3633
2.26k
  if (BIT_0(info->ir)) {
3634
839
    op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
3635
839
         ((extension >> 12) & 7);
3636
839
    op1->reg = reg;
3637
1.42k
  } else {
3638
1.42k
    op0->reg = reg;
3639
1.42k
    op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) +
3640
1.42k
         ((extension >> 12) & 7);
3641
1.42k
  }
3642
2.26k
}
3643
3644
static void d68000_movem_pd_16(m68k_info *info)
3645
126
{
3646
126
  build_movem_re(info, M68K_INS_MOVEM, 2);
3647
126
}
3648
3649
static void d68000_movem_pd_32(m68k_info *info)
3650
413
{
3651
413
  build_movem_re(info, M68K_INS_MOVEM, 4);
3652
413
}
3653
3654
static void d68000_movem_er_16(m68k_info *info)
3655
369
{
3656
369
  build_movem_er(info, M68K_INS_MOVEM, 2);
3657
369
}
3658
3659
static void d68000_movem_er_32(m68k_info *info)
3660
362
{
3661
362
  build_movem_er(info, M68K_INS_MOVEM, 4);
3662
362
}
3663
3664
static void d68000_movem_re_16(m68k_info *info)
3665
246
{
3666
246
  build_movem_re(info, M68K_INS_MOVEM, 2);
3667
246
}
3668
3669
static void d68000_movem_re_32(m68k_info *info)
3670
304
{
3671
304
  build_movem_re(info, M68K_INS_MOVEM, 4);
3672
304
}
3673
3674
static void d68000_movep_re_16(m68k_info *info)
3675
176
{
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
176
  build_movep_re(info, 2);
3681
176
}
3682
3683
static void d68000_movep_re_32(m68k_info *info)
3684
109
{
3685
109
  build_movep_re(info, 4);
3686
109
}
3687
3688
static void d68000_movep_er_16(m68k_info *info)
3689
653
{
3690
653
  build_movep_er(info, 2);
3691
653
}
3692
3693
static void d68000_movep_er_32(m68k_info *info)
3694
487
{
3695
487
  build_movep_er(info, 4);
3696
487
}
3697
3698
static void d68010_moves_8(m68k_info *info)
3699
127
{
3700
127
  LIMIT_FEATURE(info, M68010_PLUS);
3701
106
  build_moves(info, 1);
3702
106
}
3703
3704
static void d68010_moves_16(m68k_info *info)
3705
182
{
3706
  //uint32_t extension;
3707
182
  LIMIT_FEATURE(info, M68010_PLUS);
3708
92
  build_moves(info, 2);
3709
92
}
3710
3711
static void d68010_moves_32(m68k_info *info)
3712
174
{
3713
174
  LIMIT_FEATURE(info, M68010_PLUS);
3714
79
  build_moves(info, 4);
3715
79
}
3716
3717
static void d68000_moveq(m68k_info *info)
3718
6.42k
{
3719
6.42k
  cs_m68k_op *op0;
3720
6.42k
  cs_m68k_op *op1;
3721
3722
6.42k
  cs_m68k *ext = build_init_op(info, M68K_INS_MOVEQ, 2, 0);
3723
3724
6.42k
  op0 = &ext->operands[0];
3725
6.42k
  op1 = &ext->operands[1];
3726
3727
6.42k
  op0->type = M68K_OP_IMM;
3728
6.42k
  op0->address_mode = M68K_AM_IMMEDIATE;
3729
6.42k
  op0->imm = (info->ir & 0xff);
3730
3731
6.42k
  op1->address_mode = M68K_AM_REG_DIRECT_DATA;
3732
6.42k
  op1->reg = M68K_REG_D0 + ((info->ir >> 9) & 7);
3733
6.42k
}
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
26
  build_move16(info, data, modes);
3744
26
}
3745
3746
static void d68040_move16_pi_al(m68k_info *info)
3747
289
{
3748
289
  uint32_t data[2];
3749
289
  uint32_t modes[] = { M68K_AM_REGI_ADDR_POST_INC,
3750
289
           M68K_AM_ABSOLUTE_DATA_LONG };
3751
3752
289
  LIMIT_FEATURE(info, M68040_PLUS);
3753
3754
115
  data[0] = info->ir & 7;
3755
115
  data[1] = read_imm_32(info);
3756
115
  build_move16(info, data, modes);
3757
115
}
3758
3759
static void d68040_move16_al_pi(m68k_info *info)
3760
66
{
3761
66
  uint32_t data[2];
3762
66
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG,
3763
66
           M68K_AM_REGI_ADDR_POST_INC };
3764
3765
66
  LIMIT_FEATURE(info, M68040_PLUS);
3766
3767
32
  data[0] = read_imm_32(info);
3768
32
  data[1] = info->ir & 7;
3769
32
  build_move16(info, data, modes);
3770
32
}
3771
3772
static void d68040_move16_ai_al(m68k_info *info)
3773
149
{
3774
149
  uint32_t data[2];
3775
149
  uint32_t modes[] = { M68K_AM_REGI_ADDR, M68K_AM_ABSOLUTE_DATA_LONG };
3776
3777
149
  LIMIT_FEATURE(info, M68040_PLUS);
3778
3779
54
  data[0] = info->ir & 7;
3780
54
  data[1] = read_imm_32(info);
3781
54
  build_move16(info, data, modes);
3782
54
}
3783
3784
static void d68040_move16_al_ai(m68k_info *info)
3785
547
{
3786
547
  uint32_t data[2];
3787
547
  uint32_t modes[] = { M68K_AM_ABSOLUTE_DATA_LONG, M68K_AM_REGI_ADDR };
3788
3789
547
  LIMIT_FEATURE(info, M68040_PLUS);
3790
3791
167
  data[0] = read_imm_32(info);
3792
167
  data[1] = info->ir & 7;
3793
167
  build_move16(info, data, modes);
3794
167
}
3795
3796
static void d68000_muls(m68k_info *info)
3797
1.31k
{
3798
1.31k
  build_er_1(info, M68K_INS_MULS, 2);
3799
1.31k
}
3800
3801
static void d68000_mulu(m68k_info *info)
3802
991
{
3803
991
  build_er_1(info, M68K_INS_MULU, 2);
3804
991
}
3805
3806
static void d68020_mull(m68k_info *info)
3807
665
{
3808
665
  uint32_t extension, insn_signed;
3809
665
  cs_m68k *ext;
3810
665
  cs_m68k_op *op0;
3811
665
  cs_m68k_op *op1;
3812
665
  uint32_t reg_0, reg_1;
3813
3814
665
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A |
3815
665
            CS_MODE_M68K_CF_ISA_B |
3816
665
            CS_MODE_M68K_CF_ISA_C);
3817
3818
409
  extension = read_imm_16(info);
3819
409
  insn_signed = 0;
3820
3821
409
  if (BIT_B((extension)))
3822
188
    insn_signed = 1;
3823
3824
409
  ext = build_init_op(info, insn_signed ? M68K_INS_MULS : M68K_INS_MULU,
3825
409
          2, 4);
3826
3827
409
  op0 = &ext->operands[0];
3828
409
  op1 = &ext->operands[1];
3829
3830
409
  get_ea_mode_op(info, op0, info->ir, 4);
3831
3832
409
  reg_0 = extension & 7;
3833
409
  reg_1 = (extension >> 12) & 7;
3834
3835
409
  op1->address_mode = M68K_AM_NONE;
3836
409
  op1->type = M68K_OP_REG_PAIR;
3837
409
  op1->reg_pair.reg_0 = reg_0 + M68K_REG_D0;
3838
409
  op1->reg_pair.reg_1 = reg_1 + M68K_REG_D0;
3839
3840
409
  if (!BIT_A(extension)) {
3841
220
    op1->type = M68K_OP_REG;
3842
220
    op1->reg = M68K_REG_D0 + reg_1;
3843
220
  }
3844
409
}
3845
3846
static void d68000_nbcd(m68k_info *info)
3847
720
{
3848
720
  build_ea(info, M68K_INS_NBCD, 1);
3849
720
}
3850
3851
static void d68000_neg_8(m68k_info *info)
3852
115
{
3853
115
  build_ea(info, M68K_INS_NEG, 1);
3854
115
}
3855
3856
static void d68000_neg_16(m68k_info *info)
3857
423
{
3858
423
  build_ea(info, M68K_INS_NEG, 2);
3859
423
}
3860
3861
static void d68000_neg_32(m68k_info *info)
3862
279
{
3863
279
  build_ea(info, M68K_INS_NEG, 4);
3864
279
}
3865
3866
static void d68000_negx_8(m68k_info *info)
3867
752
{
3868
752
  build_ea(info, M68K_INS_NEGX, 1);
3869
752
}
3870
3871
static void d68000_negx_16(m68k_info *info)
3872
496
{
3873
496
  build_ea(info, M68K_INS_NEGX, 2);
3874
496
}
3875
3876
static void d68000_negx_32(m68k_info *info)
3877
337
{
3878
337
  build_ea(info, M68K_INS_NEGX, 4);
3879
337
}
3880
3881
static void d68000_nop(m68k_info *info)
3882
47
{
3883
47
  MCInst_setOpcode(info->inst, M68K_INS_NOP);
3884
47
}
3885
3886
static void d68000_not_8(m68k_info *info)
3887
413
{
3888
413
  build_ea(info, M68K_INS_NOT, 1);
3889
413
}
3890
3891
static void d68000_not_16(m68k_info *info)
3892
369
{
3893
369
  build_ea(info, M68K_INS_NOT, 2);
3894
369
}
3895
3896
static void d68000_not_32(m68k_info *info)
3897
346
{
3898
346
  build_ea(info, M68K_INS_NOT, 4);
3899
346
}
3900
3901
static void d68000_or_er_8(m68k_info *info)
3902
691
{
3903
691
  build_er_1(info, M68K_INS_OR, 1);
3904
691
}
3905
3906
static void d68000_or_er_16(m68k_info *info)
3907
525
{
3908
525
  build_er_1(info, M68K_INS_OR, 2);
3909
525
}
3910
3911
static void d68000_or_er_32(m68k_info *info)
3912
1.36k
{
3913
1.36k
  build_er_1(info, M68K_INS_OR, 4);
3914
1.36k
}
3915
3916
static void d68000_or_re_8(m68k_info *info)
3917
426
{
3918
426
  build_re_1(info, M68K_INS_OR, 1);
3919
426
}
3920
3921
static void d68000_or_re_16(m68k_info *info)
3922
407
{
3923
407
  build_re_1(info, M68K_INS_OR, 2);
3924
407
}
3925
3926
static void d68000_or_re_32(m68k_info *info)
3927
510
{
3928
510
  build_re_1(info, M68K_INS_OR, 4);
3929
510
}
3930
3931
static void d68000_ori_8(m68k_info *info)
3932
10.2k
{
3933
10.2k
  build_imm_ea(info, M68K_INS_ORI, 1, read_imm_8(info));
3934
10.2k
}
3935
3936
static void d68000_ori_16(m68k_info *info)
3937
1.48k
{
3938
1.48k
  build_imm_ea(info, M68K_INS_ORI, 2, read_imm_16(info));
3939
1.48k
}
3940
3941
static void d68000_ori_32(m68k_info *info)
3942
1.34k
{
3943
1.34k
  build_imm_ea(info, M68K_INS_ORI, 4, read_imm_32(info));
3944
1.34k
}
3945
3946
static void d68000_ori_to_ccr(m68k_info *info)
3947
101
{
3948
101
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_8(info), 1,
3949
101
            M68K_REG_CCR);
3950
101
}
3951
3952
static void d68000_ori_to_sr(m68k_info *info)
3953
201
{
3954
201
  build_imm_special_reg(info, M68K_INS_ORI, read_imm_16(info), 2,
3955
201
            M68K_REG_SR);
3956
201
}
3957
3958
static void d68020_pack_rr(m68k_info *info)
3959
1.49k
{
3960
1.49k
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
3961
1.40k
  build_rr(info, M68K_INS_PACK, 0, read_imm_16(info));
3962
1.40k
}
3963
3964
static void d68020_pack_mm(m68k_info *info)
3965
781
{
3966
781
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
3967
366
  build_mm(info, M68K_INS_PACK, 0, read_imm_16(info));
3968
366
}
3969
3970
static void d68000_pea(m68k_info *info)
3971
267
{
3972
267
  build_ea(info, M68K_INS_PEA, 4);
3973
267
}
3974
3975
static void d68000_reset(m68k_info *info)
3976
86
{
3977
86
  MCInst_setOpcode(info->inst, M68K_INS_RESET);
3978
86
}
3979
3980
static void d68000_ror_s_8(m68k_info *info)
3981
282
{
3982
282
  build_3bit_d(info, M68K_INS_ROR, 1);
3983
282
}
3984
3985
static void d68000_ror_s_16(m68k_info *info)
3986
328
{
3987
328
  build_3bit_d(info, M68K_INS_ROR, 2);
3988
328
}
3989
3990
static void d68000_ror_s_32(m68k_info *info)
3991
34
{
3992
34
  build_3bit_d(info, M68K_INS_ROR, 4);
3993
34
}
3994
3995
static void d68000_ror_r_8(m68k_info *info)
3996
47
{
3997
47
  build_r(info, M68K_INS_ROR, 1);
3998
47
}
3999
4000
static void d68000_ror_r_16(m68k_info *info)
4001
69
{
4002
69
  build_r(info, M68K_INS_ROR, 2);
4003
69
}
4004
4005
static void d68000_ror_r_32(m68k_info *info)
4006
299
{
4007
299
  build_r(info, M68K_INS_ROR, 4);
4008
299
}
4009
4010
static void d68000_ror_ea(m68k_info *info)
4011
531
{
4012
531
  build_ea(info, M68K_INS_ROR, 2);
4013
531
}
4014
4015
static void d68000_rol_s_8(m68k_info *info)
4016
175
{
4017
175
  build_3bit_d(info, M68K_INS_ROL, 1);
4018
175
}
4019
4020
static void d68000_rol_s_16(m68k_info *info)
4021
145
{
4022
145
  build_3bit_d(info, M68K_INS_ROL, 2);
4023
145
}
4024
4025
static void d68000_rol_s_32(m68k_info *info)
4026
183
{
4027
183
  build_3bit_d(info, M68K_INS_ROL, 4);
4028
183
}
4029
4030
static void d68000_rol_r_8(m68k_info *info)
4031
70
{
4032
70
  build_r(info, M68K_INS_ROL, 1);
4033
70
}
4034
4035
static void d68000_rol_r_16(m68k_info *info)
4036
309
{
4037
309
  build_r(info, M68K_INS_ROL, 2);
4038
309
}
4039
4040
static void d68000_rol_r_32(m68k_info *info)
4041
230
{
4042
230
  build_r(info, M68K_INS_ROL, 4);
4043
230
}
4044
4045
static void d68000_rol_ea(m68k_info *info)
4046
839
{
4047
839
  build_ea(info, M68K_INS_ROL, 2);
4048
839
}
4049
4050
static void d68000_roxr_s_8(m68k_info *info)
4051
430
{
4052
430
  build_3bit_d(info, M68K_INS_ROXR, 1);
4053
430
}
4054
4055
static void d68000_roxr_s_16(m68k_info *info)
4056
328
{
4057
328
  build_3bit_d(info, M68K_INS_ROXR, 2);
4058
328
}
4059
4060
static void d68000_roxr_s_32(m68k_info *info)
4061
238
{
4062
238
  build_3bit_d(info, M68K_INS_ROXR, 4);
4063
238
}
4064
4065
static void d68000_roxr_r_8(m68k_info *info)
4066
208
{
4067
208
  build_r(info, M68K_INS_ROXR, 1);
4068
208
}
4069
4070
static void d68000_roxr_r_16(m68k_info *info)
4071
184
{
4072
184
  build_r(info, M68K_INS_ROXR, 2);
4073
184
}
4074
4075
static void d68000_roxr_r_32(m68k_info *info)
4076
203
{
4077
203
  build_r(info, M68K_INS_ROXR, 4);
4078
203
}
4079
4080
static void d68000_roxr_ea(m68k_info *info)
4081
129
{
4082
129
  build_ea(info, M68K_INS_ROXR, 2);
4083
129
}
4084
4085
static void d68000_roxl_s_8(m68k_info *info)
4086
149
{
4087
149
  build_3bit_d(info, M68K_INS_ROXL, 1);
4088
149
}
4089
4090
static void d68000_roxl_s_16(m68k_info *info)
4091
143
{
4092
143
  build_3bit_d(info, M68K_INS_ROXL, 2);
4093
143
}
4094
4095
static void d68000_roxl_s_32(m68k_info *info)
4096
61
{
4097
61
  build_3bit_d(info, M68K_INS_ROXL, 4);
4098
61
}
4099
4100
static void d68000_roxl_r_8(m68k_info *info)
4101
133
{
4102
133
  build_r(info, M68K_INS_ROXL, 1);
4103
133
}
4104
4105
static void d68000_roxl_r_16(m68k_info *info)
4106
290
{
4107
290
  build_r(info, M68K_INS_ROXL, 2);
4108
290
}
4109
4110
static void d68000_roxl_r_32(m68k_info *info)
4111
75
{
4112
75
  build_r(info, M68K_INS_ROXL, 4);
4113
75
}
4114
4115
static void d68000_roxl_ea(m68k_info *info)
4116
695
{
4117
695
  build_ea(info, M68K_INS_ROXL, 2);
4118
695
}
4119
4120
static void d68010_rtd(m68k_info *info)
4121
154
{
4122
154
  set_insn_group(info, M68K_GRP_RET);
4123
154
  LIMIT_FEATURE(info, M68010_PLUS);
4124
63
  build_absolute_jump_with_immediate(info, M68K_INS_RTD, 0,
4125
63
             read_imm_16(info));
4126
63
}
4127
4128
static void d68000_rte(m68k_info *info)
4129
32
{
4130
32
  set_insn_group(info, M68K_GRP_IRET);
4131
32
  MCInst_setOpcode(info->inst, M68K_INS_RTE);
4132
32
}
4133
4134
static void d68020_rtm(m68k_info *info)
4135
214
{
4136
214
  cs_m68k *ext;
4137
214
  cs_m68k_op *op;
4138
4139
214
  set_insn_group(info, M68K_GRP_RET);
4140
4141
214
  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
51
{
4160
51
  set_insn_group(info, M68K_GRP_RET);
4161
51
  MCInst_setOpcode(info->inst, M68K_INS_RTR);
4162
51
}
4163
4164
static void d68000_rts(m68k_info *info)
4165
15
{
4166
15
  set_insn_group(info, M68K_GRP_RET);
4167
15
  MCInst_setOpcode(info->inst, M68K_INS_RTS);
4168
15
}
4169
4170
static void d68000_sbcd_rr(m68k_info *info)
4171
277
{
4172
277
  build_rr(info, M68K_INS_SBCD, 1, 0);
4173
277
}
4174
4175
static void d68000_sbcd_mm(m68k_info *info)
4176
774
{
4177
774
  build_mm(info, M68K_INS_SBCD, 1, 0);
4178
774
}
4179
4180
static void d68000_scc(m68k_info *info)
4181
995
{
4182
995
  cs_m68k *ext = build_init_op(
4183
995
    info, s_scc_lut[M68K_IR_CONDITION_NIBBLE(info)], 1, 1);
4184
995
  get_ea_mode_op(info, &ext->operands[0], info->ir, 1);
4185
995
}
4186
4187
static void d68000_stop(m68k_info *info)
4188
307
{
4189
307
  build_absolute_jump_with_immediate(info, M68K_INS_STOP, 0,
4190
307
             read_imm_16(info));
4191
307
}
4192
4193
static void d68040_pflush(m68k_info *info)
4194
269
{
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
269
  int mode;
4202
269
  cs_m68k *ext;
4203
269
  cs_m68k_op *op;
4204
4205
269
  LIMIT_FEATURE(info, M68040_PLUS);
4206
4207
149
  mode = (info->ir >> 3) & 3;
4208
4209
149
  switch (mode) {
4210
72
  case 0: /* PFLUSHN (An) */
4211
72
    ext = build_init_op(info, M68K_INS_PFLUSHN, 1, 0);
4212
72
    op = &ext->operands[0];
4213
72
    op->address_mode = M68K_AM_REGI_ADDR;
4214
72
    op->type = M68K_OP_MEM;
4215
72
    op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4216
72
    break;
4217
43
  case 1: /* PFLUSH (An) */
4218
43
    ext = build_init_op(info, M68K_INS_PFLUSH, 1, 0);
4219
43
    op = &ext->operands[0];
4220
43
    op->address_mode = M68K_AM_REGI_ADDR;
4221
43
    op->type = M68K_OP_MEM;
4222
43
    op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4223
43
    break;
4224
19
  case 2: /* PFLUSHAN */
4225
19
    build_init_op(info, M68K_INS_PFLUSHAN, 0, 0);
4226
19
    break;
4227
15
  case 3: /* PFLUSHA */
4228
15
    build_init_op(info, M68K_INS_PFLUSHA, 0, 0);
4229
15
    break;
4230
0
  default:
4231
0
    break;
4232
149
  }
4233
149
}
4234
4235
static void d68040_ptest(m68k_info *info)
4236
462
{
4237
  /* 68040-only PTEST instructions:
4238
   *   F548-F54F: PTESTW (An)
4239
   *   F568-F56F: PTESTR (An)
4240
   */
4241
462
  int is_read;
4242
462
  cs_m68k *ext;
4243
462
  cs_m68k_op *op;
4244
462
  int insn;
4245
4246
462
  LIMIT_FEATURE(info, CS_MODE_M68K_040);
4247
4248
297
  is_read = (info->ir >> 5) & 1;
4249
297
  insn = is_read ? M68K_INS_PTESTR : M68K_INS_PTESTW;
4250
4251
297
  ext = build_init_op(info, insn, 1, 0);
4252
297
  op = &ext->operands[0];
4253
297
  op->address_mode = M68K_AM_REGI_ADDR;
4254
297
  op->type = M68K_OP_MEM;
4255
297
  op->mem.base_reg = M68K_REG_A0 + (info->ir & 7);
4256
297
}
4257
4258
static void d68060_plpa(m68k_info *info)
4259
107
{
4260
  /* 68060-only PLPA instructions:
4261
   *   F588-F58F: PLPAW (An)
4262
   *   F5C8-F5CF: PLPAR (An)
4263
   */
4264
107
  int is_read;
4265
107
  cs_m68k *ext;
4266
107
  cs_m68k_op *op;
4267
107
  int insn;
4268
4269
107
  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
202
{
4295
202
  uint16_t ext_word;
4296
202
  int is_signed, is_round, is_memory;
4297
202
  int dx, size_bits, size;
4298
202
  int insn;
4299
202
  cs_m68k *cs_ext;
4300
202
  cs_m68k_op *op0;
4301
202
  cs_m68k_op *op1;
4302
4303
202
  if (!m68k_has_feature(info, CS_MODE_M68K_CPU32)) {
4304
202
    d68020_cpgen(info);
4305
202
    return;
4306
202
  }
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
108
{
4628
108
  if (!m68k_has_feature(info, CS_MODE_M68K_CPU32 | CS_MODE_M68K_060)) {
4629
108
    d68020_cpgen(info);
4630
108
    return;
4631
108
  }
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
447
{
4652
447
  build_er_1(info, M68K_INS_SUB, 1);
4653
447
}
4654
4655
static void d68000_sub_er_16(m68k_info *info)
4656
386
{
4657
386
  build_er_1(info, M68K_INS_SUB, 2);
4658
386
}
4659
4660
static void d68000_sub_er_32(m68k_info *info)
4661
2.13k
{
4662
2.13k
  build_er_1(info, M68K_INS_SUB, 4);
4663
2.13k
}
4664
4665
static void d68000_sub_re_8(m68k_info *info)
4666
701
{
4667
701
  build_re_1(info, M68K_INS_SUB, 1);
4668
701
}
4669
4670
static void d68000_sub_re_16(m68k_info *info)
4671
326
{
4672
326
  build_re_1(info, M68K_INS_SUB, 2);
4673
326
}
4674
4675
static void d68000_sub_re_32(m68k_info *info)
4676
1.05k
{
4677
1.05k
  build_re_1(info, M68K_INS_SUB, 4);
4678
1.05k
}
4679
4680
static void d68000_suba_16(m68k_info *info)
4681
653
{
4682
653
  build_ea_a(info, M68K_INS_SUBA, 2);
4683
653
}
4684
4685
static void d68000_suba_32(m68k_info *info)
4686
628
{
4687
628
  build_ea_a(info, M68K_INS_SUBA, 4);
4688
628
}
4689
4690
static void d68000_subi_8(m68k_info *info)
4691
455
{
4692
455
  build_imm_ea(info, M68K_INS_SUBI, 1, read_imm_8(info));
4693
455
}
4694
4695
static void d68000_subi_16(m68k_info *info)
4696
299
{
4697
299
  build_imm_ea(info, M68K_INS_SUBI, 2, read_imm_16(info));
4698
299
}
4699
4700
static void d68000_subi_32(m68k_info *info)
4701
155
{
4702
155
  build_imm_ea(info, M68K_INS_SUBI, 4, read_imm_32(info));
4703
155
}
4704
4705
static void d68000_subq_8(m68k_info *info)
4706
863
{
4707
863
  build_3bit_ea(info, M68K_INS_SUBQ, 1);
4708
863
}
4709
4710
static void d68000_subq_16(m68k_info *info)
4711
1.97k
{
4712
1.97k
  build_3bit_ea(info, M68K_INS_SUBQ, 2);
4713
1.97k
}
4714
4715
static void d68000_subq_32(m68k_info *info)
4716
348
{
4717
348
  build_3bit_ea(info, M68K_INS_SUBQ, 4);
4718
348
}
4719
4720
static void d68000_subx_rr_8(m68k_info *info)
4721
334
{
4722
334
  build_rr(info, M68K_INS_SUBX, 1, 0);
4723
334
}
4724
4725
static void d68000_subx_rr_16(m68k_info *info)
4726
410
{
4727
410
  build_rr(info, M68K_INS_SUBX, 2, 0);
4728
410
}
4729
4730
static void d68000_subx_rr_32(m68k_info *info)
4731
353
{
4732
353
  build_rr(info, M68K_INS_SUBX, 4, 0);
4733
353
}
4734
4735
static void d68000_subx_mm_8(m68k_info *info)
4736
413
{
4737
413
  build_mm(info, M68K_INS_SUBX, 1, 0);
4738
413
}
4739
4740
static void d68000_subx_mm_16(m68k_info *info)
4741
507
{
4742
507
  build_mm(info, M68K_INS_SUBX, 2, 0);
4743
507
}
4744
4745
static void d68000_subx_mm_32(m68k_info *info)
4746
49
{
4747
49
  build_mm(info, M68K_INS_SUBX, 4, 0);
4748
49
}
4749
4750
static void d68000_swap(m68k_info *info)
4751
343
{
4752
343
  build_d(info, M68K_INS_SWAP, 0);
4753
343
}
4754
4755
static void d68000_tas(m68k_info *info)
4756
221
{
4757
221
  build_ea(info, M68K_INS_TAS, 1);
4758
221
}
4759
4760
static void d68060_pulse(m68k_info *info)
4761
122
{
4762
122
  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
506
{
4768
506
  build_absolute_jump_with_immediate(info, M68K_INS_TRAP, 0,
4769
506
             info->ir & 0xf);
4770
506
}
4771
4772
static void d68020_trapcc_0(m68k_info *info)
4773
31
{
4774
31
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
4775
23
  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
23
  build_trap(info, 0, 0);
4786
4787
23
  info->extension.op_count = 0;
4788
23
}
4789
4790
static void d68020_trapcc_16(m68k_info *info)
4791
160
{
4792
160
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
4793
78
  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
78
  build_trap(info, 2, read_imm_16(info));
4804
78
}
4805
4806
static void d68020_trapcc_32(m68k_info *info)
4807
352
{
4808
352
  LIMIT_FEATURE(info, M68020_PLUS | CS_MODE_M68K_CF_ISA_A);
4809
275
  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
275
  build_trap(info, 4, read_imm_32(info));
4820
275
}
4821
4822
static void d68000_trapv(m68k_info *info)
4823
41
{
4824
41
  MCInst_setOpcode(info->inst, M68K_INS_TRAPV);
4825
41
}
4826
4827
static void d68000_tst_8(m68k_info *info)
4828
809
{
4829
809
  build_ea(info, M68K_INS_TST, 1);
4830
809
}
4831
4832
static void d68020_tst_pcdi_8(m68k_info *info)
4833
295
{
4834
295
  LIMIT_FEATURE(info, M68020_PLUS);
4835
83
  build_ea(info, M68K_INS_TST, 1);
4836
83
}
4837
4838
static void d68020_tst_pcix_8(m68k_info *info)
4839
148
{
4840
148
  LIMIT_FEATURE(info, M68020_PLUS);
4841
53
  build_ea(info, M68K_INS_TST, 1);
4842
53
}
4843
4844
static void d68020_tst_i_8(m68k_info *info)
4845
1.09k
{
4846
1.09k
  LIMIT_FEATURE(info, M68020_PLUS);
4847
276
  build_ea(info, M68K_INS_TST, 1);
4848
276
}
4849
4850
static void d68000_tst_16(m68k_info *info)
4851
399
{
4852
399
  build_ea(info, M68K_INS_TST, 2);
4853
399
}
4854
4855
static void d68020_tst_a_16(m68k_info *info)
4856
2.03k
{
4857
2.03k
  LIMIT_FEATURE(info, M68020_PLUS);
4858
1.55k
  build_ea(info, M68K_INS_TST, 2);
4859
1.55k
}
4860
4861
static void d68020_tst_pcdi_16(m68k_info *info)
4862
71
{
4863
71
  LIMIT_FEATURE(info, M68020_PLUS);
4864
53
  build_ea(info, M68K_INS_TST, 2);
4865
53
}
4866
4867
static void d68020_tst_pcix_16(m68k_info *info)
4868
105
{
4869
105
  LIMIT_FEATURE(info, M68020_PLUS);
4870
59
  build_ea(info, M68K_INS_TST, 2);
4871
59
}
4872
4873
static void d68020_tst_i_16(m68k_info *info)
4874
102
{
4875
102
  LIMIT_FEATURE(info, M68020_PLUS);
4876
26
  build_ea(info, M68K_INS_TST, 2);
4877
26
}
4878
4879
static void d68000_tst_32(m68k_info *info)
4880
151
{
4881
151
  build_ea(info, M68K_INS_TST, 4);
4882
151
}
4883
4884
static void d68020_tst_a_32(m68k_info *info)
4885
165
{
4886
165
  LIMIT_FEATURE(info, M68020_PLUS);
4887
140
  build_ea(info, M68K_INS_TST, 4);
4888
140
}
4889
4890
static void d68020_tst_pcdi_32(m68k_info *info)
4891
402
{
4892
402
  LIMIT_FEATURE(info, M68020_PLUS);
4893
182
  build_ea(info, M68K_INS_TST, 4);
4894
182
}
4895
4896
static void d68020_tst_pcix_32(m68k_info *info)
4897
442
{
4898
442
  LIMIT_FEATURE(info, M68020_PLUS);
4899
405
  build_ea(info, M68K_INS_TST, 4);
4900
405
}
4901
4902
static void d68020_tst_i_32(m68k_info *info)
4903
371
{
4904
371
  LIMIT_FEATURE(info, M68020_PLUS);
4905
137
  build_ea(info, M68K_INS_TST, 4);
4906
137
}
4907
4908
static void d68000_unlk(m68k_info *info)
4909
60
{
4910
60
  cs_m68k_op *op;
4911
60
  cs_m68k *ext = build_init_op(info, M68K_INS_UNLK, 1, 0);
4912
4913
60
  op = &ext->operands[0];
4914
4915
60
  op->address_mode = M68K_AM_REG_DIRECT_ADDR;
4916
60
  op->reg = M68K_REG_A0 + (info->ir & 7);
4917
60
}
4918
4919
static void d68020_unpk_rr(m68k_info *info)
4920
858
{
4921
858
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
4922
619
  build_rr(info, M68K_INS_UNPK, 0, read_imm_16(info));
4923
619
}
4924
4925
static void d68020_unpk_mm(m68k_info *info)
4926
1.46k
{
4927
1.46k
  LIMIT_FEATURE_EXCLUDING(info, M68020_PLUS, CS_MODE_M68K_CPU32);
4928
1.02k
  build_mm(info, M68K_INS_UNPK, 0, read_imm_16(info));
4929
1.02k
}
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
192k
{
4936
192k
  const unsigned int instruction = info->ir;
4937
192k
  const instruction_struct *i = &g_instruction_table[instruction];
4938
4939
192k
  if ((i->word2_mask &&
4940
4.96k
       ((word_check & i->word2_mask) != i->word2_match)) ||
4941
192k
      (i->instruction == d68000_invalid)) {
4942
786
    d68000_invalid(info);
4943
786
    return 0;
4944
786
  }
4945
4946
191k
  return 1;
4947
192k
}
4948
4949
static int exists_reg_list(const uint16_t *regs, uint8_t count, m68k_reg reg)
4950
245k
{
4951
245k
  uint8_t i;
4952
4953
337k
  for (i = 0; i < count; ++i) {
4954
94.4k
    if (regs[i] == (uint16_t)reg)
4955
2.13k
      return 1;
4956
94.4k
  }
4957
4958
243k
  return 0;
4959
245k
}
4960
4961
static void add_reg_to_rw_list(m68k_info *info, m68k_reg reg, int write)
4962
250k
{
4963
250k
  if (reg == M68K_REG_INVALID)
4964
5.09k
    return;
4965
4966
245k
  if (write) {
4967
137k
    if (exists_reg_list(info->regs_write, info->regs_write_count,
4968
137k
            reg))
4969
1.03k
      return;
4970
4971
136k
    info->regs_write[info->regs_write_count] = (uint16_t)reg;
4972
136k
    info->regs_write_count++;
4973
136k
  } else {
4974
107k
    if (exists_reg_list(info->regs_read, info->regs_read_count,
4975
107k
            reg))
4976
1.10k
      return;
4977
4978
106k
    info->regs_read[info->regs_read_count] = (uint16_t)reg;
4979
106k
    info->regs_read_count++;
4980
106k
  }
4981
245k
}
4982
4983
static void update_am_reg_list(m68k_info *info, cs_m68k_op *op, int write)
4984
87.4k
{
4985
87.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
16.0k
  case M68K_AM_REGI_ADDR_POST_INC:
4992
39.6k
  case M68K_AM_REGI_ADDR_PRE_DEC:
4993
39.6k
    add_reg_to_rw_list(info, op->mem.base_reg, 1);
4994
39.6k
    break;
4995
4996
16.4k
  case M68K_AM_REGI_ADDR:
4997
29.3k
  case M68K_AM_REGI_ADDR_DISP:
4998
29.3k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
4999
29.3k
    break;
5000
5001
5.99k
  case M68K_AM_AREGI_INDEX_8_BIT_DISP:
5002
8.09k
  case M68K_AM_AREGI_INDEX_BASE_DISP:
5003
9.70k
  case M68K_AM_MEMI_POST_INDEX:
5004
11.1k
  case M68K_AM_MEMI_PRE_INDEX:
5005
11.8k
  case M68K_AM_PCI_INDEX_8_BIT_DISP:
5006
12.2k
  case M68K_AM_PCI_INDEX_BASE_DISP:
5007
12.5k
  case M68K_AM_PC_MEMI_PRE_INDEX:
5008
12.9k
  case M68K_AM_PC_MEMI_POST_INDEX:
5009
12.9k
    add_reg_to_rw_list(info, op->mem.index_reg, 0);
5010
12.9k
    add_reg_to_rw_list(info, op->mem.base_reg, 0);
5011
12.9k
    break;
5012
5013
  // no register(s) in the other addressing modes
5014
5.52k
  default:
5015
5.52k
    break;
5016
87.4k
  }
5017
87.4k
}
5018
5019
static void update_bits_range(m68k_info *info, m68k_reg reg_start, uint8_t bits,
5020
            int write)
5021
7.92k
{
5022
7.92k
  int i;
5023
5024
71.3k
  for (i = 0; i < 8; ++i) {
5025
63.3k
    if (bits & (1 << i)) {
5026
16.0k
      add_reg_to_rw_list(info, reg_start + i, write);
5027
16.0k
    }
5028
63.3k
  }
5029
7.92k
}
5030
5031
static void update_reg_list_regbits(m68k_info *info, cs_m68k_op *op, int write)
5032
2.64k
{
5033
2.64k
  uint32_t bits = op->register_bits;
5034
2.64k
  update_bits_range(info, M68K_REG_D0, bits & 0xff, write);
5035
2.64k
  update_bits_range(info, M68K_REG_A0, (bits >> 8) & 0xff, write);
5036
2.64k
  update_bits_range(info, M68K_REG_FP0, (bits >> 16) & 0xff, write);
5037
2.64k
}
5038
5039
static void update_op_reg_list(m68k_info *info, cs_m68k_op *op, int write)
5040
320k
{
5041
320k
  switch ((int)op->type) {
5042
138k
  case M68K_OP_REG:
5043
138k
    add_reg_to_rw_list(info, op->reg, write);
5044
138k
    break;
5045
5046
87.4k
  case M68K_OP_MEM:
5047
87.4k
    update_am_reg_list(info, op, write);
5048
87.4k
    break;
5049
5050
2.64k
  case M68K_OP_REG_BITS:
5051
2.64k
    update_reg_list_regbits(info, op, write);
5052
2.64k
    break;
5053
5054
486
  case M68K_OP_REG_PAIR:
5055
486
    add_reg_to_rw_list(info, op->reg_pair.reg_0, write);
5056
486
    add_reg_to_rw_list(info, op->reg_pair.reg_1, write);
5057
486
    break;
5058
90.8k
  default:
5059
90.8k
    break;
5060
320k
  }
5061
320k
}
5062
5063
static void build_regs_read_write_counts(m68k_info *info)
5064
191k
{
5065
191k
  int i;
5066
5067
191k
  if (!info->extension.op_count)
5068
520
    return;
5069
5070
191k
  if (info->extension.op_count == 1) {
5071
64.7k
    update_op_reg_list(info, &info->extension.operands[0], 1);
5072
126k
  } else {
5073
    // first operand is always read
5074
126k
    update_op_reg_list(info, &info->extension.operands[0], 0);
5075
5076
    // remaining write
5077
255k
    for (i = 1; i < info->extension.op_count; ++i)
5078
129k
      update_op_reg_list(info, &info->extension.operands[i],
5079
129k
             1);
5080
126k
  }
5081
191k
}
5082
5083
static void m68k_setup_internals(m68k_info *info, MCInst *inst, uint32_t pc,
5084
         m68k_feature_mask features)
5085
192k
{
5086
192k
  info->inst = inst;
5087
192k
  info->pc = pc;
5088
192k
  info->ir = 0;
5089
192k
  info->features = features;
5090
192k
  if (m68k_has_feature(info, M68010_LESS))
5091
61.0k
    info->address_mask = 0x00ffffff;
5092
131k
  else
5093
131k
    info->address_mask = 0xffffffff;
5094
192k
}
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
192k
{
5103
192k
  MCInst *inst = info->inst;
5104
192k
  cs_m68k *ext = &info->extension;
5105
192k
  int i;
5106
192k
  unsigned int size;
5107
5108
192k
  inst->Opcode = M68K_INS_INVALID;
5109
5110
192k
  memset(ext, 0, sizeof(cs_m68k));
5111
192k
  ext->op_size.type = M68K_SIZE_TYPE_CPU;
5112
5113
1.34M
  for (i = 0; i < M68K_OPERAND_COUNT; ++i)
5114
1.15M
    ext->operands[i].type = M68K_OP_REG;
5115
5116
192k
  info->ir = peek_imm_16(info);
5117
192k
  if (instruction_is_valid(info, peek_imm_32(info) & 0xffff)) {
5118
191k
    info->ir = read_imm_16(info);
5119
191k
    g_instruction_table[info->ir].instruction(info);
5120
191k
  }
5121
5122
192k
  size = info->pc - (unsigned int)pc;
5123
192k
  info->pc = (unsigned int)pc;
5124
5125
192k
  return size;
5126
192k
}
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
193k
{
5132
#ifdef M68K_DEBUG
5133
  SStream ss;
5134
#endif
5135
193k
  uint32_t sz = 0;
5136
193k
  m68k_feature_mask features = 0;
5137
193k
  cs_struct *handle = instr->csh;
5138
193k
  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
193k
  if (code_len < 2) {
5143
588
    *size = 0;
5144
588
    return false;
5145
588
  }
5146
5147
192k
  if (instr->flat_insn->detail) {
5148
192k
    memset(instr->flat_insn->detail, 0,
5149
192k
           offsetof(cs_detail, m68k) + sizeof(cs_m68k));
5150
192k
  }
5151
5152
192k
  info->groups_count = 0;
5153
192k
  info->regs_read_count = 0;
5154
192k
  info->regs_write_count = 0;
5155
192k
  info->code = code;
5156
192k
  info->code_len = code_len;
5157
192k
  info->baseAddress = address;
5158
5159
192k
  features =
5160
192k
    (m68k_feature_mask)(handle->mode & CS_MODE_M68K_FEATURE_MASK);
5161
192k
  if (!features)
5162
61.0k
    features = CS_MODE_M68K_000;
5163
5164
192k
  m68k_setup_internals(info, instr, (uint32_t)address, features);
5165
192k
  sz = m68k_disassemble(info, address);
5166
5167
192k
  if (sz == 0) {
5168
703
    *size = 2;
5169
703
    return false;
5170
703
  }
5171
5172
191k
  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
191k
  if (sz > (uint32_t)code_len)
5181
579
    *size = (uint16_t)code_len;
5182
191k
  else
5183
191k
    *size = sz;
5184
5185
  return true;
5186
192k
}