Coverage Report

Created: 2026-06-15 06:41

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