Coverage Report

Created: 2026-05-30 06:22

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