Coverage Report

Created: 2026-06-06 06:15

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