Coverage Report

Created: 2026-04-29 06:06

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