From 25a90d8861b4528fc63aedf01365724083d40521 Mon Sep 17 00:00:00 2001 From: billow Date: Sun, 5 Jul 2026 05:11:05 +0800 Subject: [PATCH 1/5] Add ColdFire EMAC_B dual-acc MAC support --- arch/M68K/M68KDisassembler.c | 22 ++++++++- arch/M68K/M68KInstPrinter.c | 3 +- include/capstone/m68k.h | 4 ++ tests/details/m68k.yaml | 96 ++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index c0a400df13..5e3baf443e 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -1450,6 +1450,13 @@ static m68k_reg cf_primary_acc_reg(const m68k_info *info) M68K_REG_ACC; } +static m68k_insn cf_dual_acc_insn(uint16_t ext_word) +{ + if (ext_word & 0x0100) + return (ext_word & 0x2) ? M68K_INS_MSSAC : M68K_INS_MSAAC; + return (ext_word & 0x2) ? M68K_INS_MASAC : M68K_INS_MAAAC; +} + static m68k_reg cf_accext_reg(uint32_t ir) { return (ir & 0x0400) ? M68K_REG_ACCEXT23 : M68K_REG_ACCEXT01; @@ -1666,6 +1673,7 @@ static void dcf_mac_arith(m68k_info *info) uint32_t acc; bool is_memory; bool is_emac; + bool is_dual_acc; int size; LIMIT_FEATURE(info, CS_MODE_M68K_CF_MAC); @@ -1683,10 +1691,14 @@ static void dcf_mac_arith(m68k_info *info) } is_emac = m68k_has_feature(info, CS_MODE_M68K_CF_EMAC) != 0; + is_dual_acc = !is_memory && (ext_word & 0x1) && + m68k_has_feature(info, CS_MODE_M68K_CF_EMAC_B); size = (ext_word & 0x0800) ? 4 : 2; ext = build_init_op(info, - (ext_word & 0x0100) ? M68K_INS_MSAC : M68K_INS_MAC, + is_dual_acc ? cf_dual_acc_insn(ext_word) : + (ext_word & 0x0100) ? M68K_INS_MSAC : + M68K_INS_MAC, is_memory ? 0 : 2, size); op0 = &ext->operands[0]; op1 = &ext->operands[1]; @@ -1731,7 +1743,13 @@ static void dcf_mac_arith(m68k_info *info) cf_build_direct_reg_op(op, cf_reg_from_nibble(update)); } - if (is_emac) { + if (is_dual_acc) { + acc = ((info->ir & 0x80) ? 1 : 0) | ((ext_word & 0x10) ? 2 : 0); + op = &ext->operands[ext->op_count++]; + cf_build_reg_op(op, cf_acc_reg(acc)); + op = &ext->operands[ext->op_count++]; + cf_build_reg_op(op, cf_acc_reg((ext_word >> 2) & 0x3)); + } else if (is_emac) { if (is_memory) acc = ((ext_word >> 3) & 0x2) | ((~info->ir >> 7) & 0x1); diff --git a/arch/M68K/M68KInstPrinter.c b/arch/M68K/M68KInstPrinter.c index 980a7231c8..9c69c5d557 100644 --- a/arch/M68K/M68KInstPrinter.c +++ b/arch/M68K/M68KInstPrinter.c @@ -115,7 +115,8 @@ static const char *const s_instruction_names[] = { "unlk", "unpk", "wddata", "wdebug", "bgnd", "tbls", "tblu", "tblsn", "tblun", "cp0bcbusy", "cp0ld", "cp0nop", "cp0st", "cp1bcbusy", "cp1ld", - "cp1nop", "cp1st", "tpf", + "cp1nop", "cp1st", "tpf", "maaac", "masac", + "msaac", "mssac", }; #endif diff --git a/include/capstone/m68k.h b/include/capstone/m68k.h index 02b7a8eb5b..36c13e7426 100644 --- a/include/capstone/m68k.h +++ b/include/capstone/m68k.h @@ -666,6 +666,10 @@ typedef enum m68k_insn { M68K_INS_CP1NOP, M68K_INS_CP1ST, M68K_INS_TPF, + M68K_INS_MAAAC, + M68K_INS_MASAC, + M68K_INS_MSAAC, + M68K_INS_MSSAC, M68K_INS_ENDING, // <-- mark the end of the list of instructions } m68k_insn; diff --git a/tests/details/m68k.yaml b/tests/details/m68k.yaml index a28582895c..a94696f840 100644 --- a/tests/details/m68k.yaml +++ b/tests/details/m68k.yaml @@ -4898,6 +4898,102 @@ test_cases: regs_write: [a2, d1, acc0] regs_impl_read: [a1, a3] regs_impl_write: [a2, d1, acc0] + - input: + bytes: [0xa0, 0x01, 0x00, 0x05] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CF_EMAC_B] + address: 0x0 + expected: + insns: + - asm_text: "maaac.w d1l, d0l, acc0, acc1" + details: + m68k: + op_size_type: M68K_SIZE_TYPE_CPU + op_size_cpu: M68K_CPU_SIZE_WORD + operands: + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + flags: [M68K_OP_FLAG_REG_LOWER] + reg: d1 + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + flags: [M68K_OP_FLAG_REG_LOWER] + reg: d0 + - type: M68K_OP_REG + reg: acc0 + - type: M68K_OP_REG + reg: acc1 + - input: + bytes: [0xa0, 0x02, 0x00, 0x07] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CF_EMAC_B] + address: 0x0 + expected: + insns: + - asm_text: "masac.w d2l, d0l, acc0, acc1" + details: + m68k: + op_size_type: M68K_SIZE_TYPE_CPU + op_size_cpu: M68K_CPU_SIZE_WORD + operands: + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + flags: [M68K_OP_FLAG_REG_LOWER] + reg: d2 + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + flags: [M68K_OP_FLAG_REG_LOWER] + reg: d0 + - type: M68K_OP_REG + reg: acc0 + - type: M68K_OP_REG + reg: acc1 + - input: + bytes: [0xa6, 0x02, 0x09, 0x05] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CF_EMAC_B] + address: 0x0 + expected: + insns: + - asm_text: "msaac.l d2, d3, acc0, acc1" + details: + m68k: + op_size_type: M68K_SIZE_TYPE_CPU + op_size_cpu: M68K_CPU_SIZE_LONG + operands: + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + reg: d2 + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + reg: d3 + - type: M68K_OP_REG + reg: acc0 + - type: M68K_OP_REG + reg: acc1 + - input: + bytes: [0xa6, 0x02, 0x09, 0x1f] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CF_EMAC_B] + address: 0x0 + expected: + insns: + - asm_text: "mssac.l d2, d3, acc2, acc3" + details: + m68k: + op_size_type: M68K_SIZE_TYPE_CPU + op_size_cpu: M68K_CPU_SIZE_LONG + operands: + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + reg: d2 + - type: M68K_OP_REG + address_mode: M68K_AM_REG_DIRECT_DATA + reg: d3 + - type: M68K_OP_REG + reg: acc2 + - type: M68K_OP_REG + reg: acc3 - input: bytes: [0xd0, 0x80] arch: "m68k" From 0d5221b6eff942d09663dfc1a8f32d2f11ce3f4f Mon Sep 17 00:00:00 2001 From: billow Date: Sun, 5 Jul 2026 01:32:20 +0800 Subject: [PATCH 2/5] Fix M68K reserved EA decoding in Capstone --- arch/M68K/M68KDisassembler.c | 131 +++++++++++++++++++---------------- tests/details/m68k.yaml | 63 +++++++++++++++++ 2 files changed, 134 insertions(+), 60 deletions(-) diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index 5e3baf443e..30540ca301 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -137,6 +137,15 @@ typedef struct { uint16_t word2_match; /* what to match after masking */ } instruction_struct; +#define M68K_GET_EA_OR_INVALID(info, op, instruction, size) \ + do { \ + if (!get_ea_mode_op((info), (op), (instruction), (size))) { \ + (info)->inst->Opcode = M68K_INS_INVALID; \ + (info)->pc = (unsigned int)(info)->baseAddress; \ + return; \ + } \ + } while (0) + /* ======================================================================== */ /* ================================= DATA ================================= */ /* ======================================================================== */ @@ -412,7 +421,7 @@ static bool m68k_ea_is_data_register_direct_or_immediate(uint32_t ir) } /* Make string of effective address mode */ -static void get_ea_mode_op(m68k_info *info, cs_m68k_op *op, +static bool get_ea_mode_op(m68k_info *info, cs_m68k_op *op, uint32_t instruction, uint32_t size) { // default to memory @@ -564,8 +573,10 @@ static void get_ea_mode_op(m68k_info *info, cs_m68k_op *op, break; default: - break; + return false; } + + return true; } static void set_insn_group(m68k_info *info, m68k_group_type group) @@ -606,7 +617,7 @@ static void build_re_gen_1(m68k_info *info, bool isDreg, int opcode, op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7); } - get_ea_mode_op(info, op1, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); } static void build_re_1(m68k_info *info, int opcode, uint8_t size) @@ -624,7 +635,7 @@ static void build_er_gen_1(m68k_info *info, bool isDreg, int opcode, op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); if (isDreg) { op1->address_mode = M68K_AM_REG_DIRECT_DATA; @@ -694,7 +705,7 @@ static void build_imm_ea(m68k_info *info, int opcode, uint8_t size, op0->address_mode = M68K_AM_IMMEDIATE; op0->imm = imm; - get_ea_mode_op(info, op1, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); } static void build_3bit_d(m68k_info *info, int opcode, int size) @@ -727,7 +738,7 @@ static void build_3bit_ea(m68k_info *info, int opcode, int size) op0->address_mode = M68K_AM_IMMEDIATE; op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7]; - get_ea_mode_op(info, op1, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); } static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm) @@ -752,7 +763,7 @@ static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm) static void build_ea(m68k_info *info, int opcode, uint8_t size) { cs_m68k *ext = build_init_op(info, opcode, 1, size); - get_ea_mode_op(info, &ext->operands[0], info->ir, size); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); } static void build_ea_a(m68k_info *info, int opcode, uint8_t size) @@ -764,7 +775,7 @@ static void build_ea_a(m68k_info *info, int opcode, uint8_t size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); op1->address_mode = M68K_AM_REG_DIRECT_ADDR; op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7); @@ -779,10 +790,10 @@ static void build_ea_ea(m68k_info *info, int opcode, int size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, size); - get_ea_mode_op(info, op1, - (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)), - size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID( + info, op1, (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)), + size); } static void build_pi_pi(m68k_info *info, int opcode, int size) @@ -910,7 +921,7 @@ static void build_d_d_ea(m68k_info *info, int opcode, int size) op1->address_mode = M68K_AM_REG_DIRECT_DATA; op1->reg = M68K_REG_D0 + ((extension >> 6) & 7); - get_ea_mode_op(info, op2, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op2, info->ir, size); } static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg) @@ -941,7 +952,7 @@ static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg) op1->reg = M68K_REG_D0 + ((extension >> 12) & 7); } - get_ea_mode_op(info, op_ea, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 1); op_ea->mem.bitfield = 1; op_ea->mem.width = width; @@ -1095,7 +1106,7 @@ static void build_movem_re(m68k_info *info, int opcode, int size) op0->type = M68K_OP_REG_BITS; op0->register_bits = read_imm_16(info); - get_ea_mode_op(info, op1, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); if (op1->address_mode == M68K_AM_REGI_ADDR_PRE_DEC) op0->register_bits = reverse_bits(op0->register_bits); @@ -1113,7 +1124,7 @@ static void build_movem_er(m68k_info *info, int opcode, int size) op1->type = M68K_OP_REG_BITS; op1->register_bits = read_imm_16(info); - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); } static void build_imm(m68k_info *info, int opcode, uint32_t data) @@ -1196,7 +1207,7 @@ static void build_chk2_cmp2(m68k_info *info, int size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; @@ -1325,9 +1336,9 @@ static void build_moves(m68k_info *info, int size) if (BIT_B(extension)) { op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7); - get_ea_mode_op(info, op1, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); } else { - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7); } @@ -1432,7 +1443,7 @@ static void dcf_mov3q(m68k_info *info) op1 = &ext->operands[1]; cf_build_imm_op(op0, cf_mov3q_imm(info->ir)); - get_ea_mode_op(info, op1, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); } static void cf_init_two_op(m68k_info *info, m68k_insn insn, cs_m68k_op **op0, @@ -1734,7 +1745,7 @@ static void dcf_mac_arith(m68k_info *info) if (is_memory) { op = &ext->operands[ext->op_count++]; - get_ea_mode_op(info, op, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op, info->ir, size); if (ext_word & 0x20) op->flags |= M68K_OP_FLAG_MEM_UPDATE; @@ -1767,7 +1778,7 @@ static void dcf_mvs_8(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVS, 2, 1); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1778,7 +1789,7 @@ static void dcf_mvs_16(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVS, 2, 2); - get_ea_mode_op(info, &ext->operands[0], info->ir, 2); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 2); cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1789,7 +1800,7 @@ static void dcf_mvz_8(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVZ, 2, 1); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1800,7 +1811,7 @@ static void dcf_mvz_16(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVZ, 2, 2); - get_ea_mode_op(info, &ext->operands[0], info->ir, 2); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 2); cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1853,7 +1864,7 @@ static void dcf_wddata(m68k_info *info) } ext = build_init_op(info, M68K_INS_WDDATA, 1, size); - get_ea_mode_op(info, &ext->operands[0], info->ir, size); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); } static void dcf_wdebug(m68k_info *info) @@ -1868,7 +1879,7 @@ static void dcf_wdebug(m68k_info *info) } ext = build_init_op(info, M68K_INS_WDEBUG, 1, 4); - get_ea_mode_op(info, &ext->operands[0], info->ir, 4); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); } static void dcf_intouch(m68k_info *info) @@ -1966,9 +1977,9 @@ static void dcf_coproc_ldst(m68k_info *info) cf_build_direct_reg_op(&ext->operands[0], cf_reg_from_nibble((ext_word >> 12) & 0xf)); - get_ea_mode_op(info, &ext->operands[1], info->ir, size); + M68K_GET_EA_OR_INVALID(info, &ext->operands[1], info->ir, size); } else { - get_ea_mode_op(info, &ext->operands[0], info->ir, size); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); cf_build_direct_reg_op(&ext->operands[1], cf_reg_from_nibble((ext_word >> 12) & 0xf)); @@ -2695,7 +2706,7 @@ static void fmove_fpcr(m68k_info *info, uint32_t extension) op_ea = t; } - get_ea_mode_op(info, op_ea, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 4); if (regsel & 4) special->reg = M68K_REG_FPCR; @@ -2725,7 +2736,7 @@ static void fmovem(m68k_info *info, uint32_t extension) op_ea = t; } - get_ea_mode_op(info, op_ea, info->ir, 0); + M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 0); switch (mode) { case 1: // Dynamic list in dn register @@ -2984,23 +2995,23 @@ static void d68020_cpgen(m68k_info *info) switch (src) { case M68K_FPSRC_LONG: ext->op_size.cpu_size = M68K_CPU_SIZE_LONG; - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); break; case M68K_FPSRC_BYTE: ext->op_size.cpu_size = M68K_CPU_SIZE_BYTE; - get_ea_mode_op(info, op0, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 1); break; case M68K_FPSRC_WORD: ext->op_size.cpu_size = M68K_CPU_SIZE_WORD; - get_ea_mode_op(info, op0, info->ir, 2); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); break; case M68K_FPSRC_SINGLE: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE; - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); if (op0->address_mode == M68K_AM_IMMEDIATE) { op0->simm = BitsToFloat(op0->imm); op0->type = M68K_OP_FP_SINGLE; @@ -3010,7 +3021,7 @@ static void d68020_cpgen(m68k_info *info) case M68K_FPSRC_DOUBLE: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_DOUBLE; - get_ea_mode_op(info, op0, info->ir, 8); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 8); if (op0->address_mode == M68K_AM_IMMEDIATE) op0->type = M68K_OP_FP_DOUBLE; break; @@ -3018,13 +3029,13 @@ static void d68020_cpgen(m68k_info *info) case M68K_FPSRC_EXTENDED: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED; - get_ea_mode_op(info, op0, info->ir, 12); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 12); break; case M68K_FPSRC_PACKED: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED; - get_ea_mode_op(info, op0, info->ir, 12); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 12); break; default: @@ -3046,7 +3057,7 @@ static void d68020_cprestore(m68k_info *info) REQUIRE_CPID_FPU(info); ext = build_init_op(info, M68K_INS_FRESTORE, 1, 0); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); } static void d68020_cpsave(m68k_info *info) @@ -3056,7 +3067,7 @@ static void d68020_cpsave(m68k_info *info) REQUIRE_CPID_FPU(info); ext = build_init_op(info, M68K_INS_FSAVE, 1, 0); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); } static void d68040_pflush_or_cpsave(m68k_info *info) @@ -3089,7 +3100,7 @@ static void d68020_cpscc(m68k_info *info) ext = build_init_op(info, M68K_INS_FSF, 1, 1); info->inst->Opcode += M68K_FP_COND(read_imm_16(info)); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); } static void d68020_cptrapcc_0(m68k_info *info) @@ -3209,7 +3220,7 @@ static void d68020_divl(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG_PAIR; @@ -3321,14 +3332,14 @@ static void d68000_jmp(m68k_info *info) { cs_m68k *ext = build_init_op(info, M68K_INS_JMP, 1, 0); set_insn_group(info, M68K_GRP_JUMP); - get_ea_mode_op(info, &ext->operands[0], info->ir, 4); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); } static void d68000_jsr(m68k_info *info) { cs_m68k *ext = build_init_op(info, M68K_INS_JSR, 1, 0); set_insn_group(info, M68K_GRP_JUMP); - get_ea_mode_op(info, &ext->operands[0], info->ir, 4); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); } static void d68000_lea(m68k_info *info) @@ -3458,7 +3469,7 @@ static void d68000_move_to_ccr(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 1); op1->address_mode = M68K_AM_NONE; op1->reg = M68K_REG_CCR; @@ -3486,7 +3497,7 @@ static void d68010_move_fr_ccr(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->reg = M68K_REG_CCR; - get_ea_mode_op(info, op1, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); } static void d68000_move_fr_sr(m68k_info *info) @@ -3508,7 +3519,7 @@ static void d68000_move_fr_sr(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->reg = M68K_REG_SR; - get_ea_mode_op(info, op1, info->ir, 2); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 2); } static void d68000_move_to_sr(m68k_info *info) @@ -3527,7 +3538,7 @@ static void d68000_move_to_sr(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, 2); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); op1->address_mode = M68K_AM_NONE; op1->reg = M68K_REG_SR; @@ -3845,7 +3856,7 @@ static void d68020_mull(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); reg_0 = extension & 7; reg_1 = (extension >> 12) & 7; @@ -4199,7 +4210,7 @@ static void d68000_scc(m68k_info *info) { cs_m68k *ext = build_init_op( info, s_scc_lut[M68K_IR_CONDITION_NIBBLE(info)], 1, 1); - get_ea_mode_op(info, &ext->operands[0], info->ir, 1); + M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); } static void d68000_stop(m68k_info *info) @@ -4371,7 +4382,7 @@ static void d68cpu32_tbl(m68k_info *info) op1 = &cs_ext->operands[1]; if (is_memory) { - get_ea_mode_op(info, op0, info->ir, size); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); } else { int dm = info->ir & 7; int dn = ext_word & 7; @@ -4446,9 +4457,9 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = pmmu_reg; - get_ea_mode_op(info, op1, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); } else { - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = pmmu_reg; @@ -4494,7 +4505,7 @@ static void d68030_pmmu(m68k_info *info) op1->address_mode = M68K_AM_IMMEDIATE; op1->imm = mask; - get_ea_mode_op(info, op2, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op2, info->ir, 1); } else { int fc_source = cmd & 0x1f; int is_read; @@ -4516,7 +4527,7 @@ static void d68030_pmmu(m68k_info *info) op1 = &ext->operands[1]; pmmu_decode_fc(info, op0, fc_source); - get_ea_mode_op(info, op1, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); } break; } @@ -4562,9 +4573,9 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = pmmu_reg; - get_ea_mode_op(info, op1, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); } else { - get_ea_mode_op(info, op0, info->ir, 4); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = pmmu_reg; @@ -4593,9 +4604,9 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = M68K_REG_MMUSR; - get_ea_mode_op(info, op1, info->ir, 2); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 2); } else { - get_ea_mode_op(info, op0, info->ir, 2); + M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = M68K_REG_MMUSR; @@ -4627,7 +4638,7 @@ static void d68030_pmmu(m68k_info *info) op2 = &ext->operands[2]; pmmu_decode_fc(info, op0, fc_source); - get_ea_mode_op(info, op1, info->ir, 1); + M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); op2->type = M68K_OP_IMM; op2->address_mode = M68K_AM_IMMEDIATE; diff --git a/tests/details/m68k.yaml b/tests/details/m68k.yaml index a94696f840..bed562f3f9 100644 --- a/tests/details/m68k.yaml +++ b/tests/details/m68k.yaml @@ -53,6 +53,69 @@ test_cases: address: 0x0 expected: insns: [] + - input: + bytes: [0xf2, 0x3d, 0x40, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_020] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf2, 0x3e, 0x40, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_020] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf2, 0x3f, 0x40, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_020] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf0, 0x3d, 0x08, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_030] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf0, 0x3e, 0x08, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_030] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf0, 0x3f, 0x08, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_030] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf8, 0x3d, 0x01, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CPU32] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf8, 0x3e, 0x01, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CPU32] + address: 0x0 + expected: + insns: [] + - input: + bytes: [0xf8, 0x3f, 0x01, 0x00] + arch: "m68k" + options: [CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CPU32] + address: 0x0 + expected: + insns: [] - input: bytes: [0x06, 0xc0] arch: "m68k" From 44e350ccec35274aede6f2e59be0de21f999e2fd Mon Sep 17 00:00:00 2001 From: billow Date: Mon, 6 Jul 2026 20:00:26 +0800 Subject: [PATCH 3/5] Extract M68K EA invalidation helper --- arch/M68K/M68KDisassembler.c | 21 +++++++++++++-------- arch/M68K/M68KDisassembler.h | 6 +++--- arch/M68K/M68KInstPrinter.c | 17 ++++++++--------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index 30540ca301..7cf569f58d 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -137,11 +137,16 @@ typedef struct { uint16_t word2_match; /* what to match after masking */ } instruction_struct; +static inline void invalid_insn(m68k_info *info) +{ + info->inst->Opcode = M68K_INS_INVALID; + info->pc = (uint32_t)info->baseAddress; +} + #define M68K_GET_EA_OR_INVALID(info, op, instruction, size) \ do { \ if (!get_ea_mode_op((info), (op), (instruction), (size))) { \ - (info)->inst->Opcode = M68K_INS_INVALID; \ - (info)->pc = (unsigned int)(info)->baseAddress; \ + invalid_insn((info)); \ return; \ } \ } while (0) @@ -4962,7 +4967,7 @@ static void d68020_unpk_mm(m68k_info *info) static int instruction_is_valid(m68k_info *info, const uint32_t word_check) { - const unsigned int instruction = info->ir; + const uint32_t instruction = info->ir; const instruction_struct *i = &g_instruction_table[instruction]; if ((i->word2_mask && @@ -5127,12 +5132,12 @@ static void m68k_setup_internals(m68k_info *info, MCInst *inst, uint32_t pc, /* ======================================================================== */ /* Disasemble one instruction at pc and store in str_buff */ -static unsigned int m68k_disassemble(m68k_info *info, uint64_t pc) +static uint32_t m68k_disassemble(m68k_info *info, uint32_t pc) { MCInst *inst = info->inst; cs_m68k *ext = &info->extension; int i; - unsigned int size; + uint32_t size; inst->Opcode = M68K_INS_INVALID; @@ -5148,8 +5153,8 @@ static unsigned int m68k_disassemble(m68k_info *info, uint64_t pc) g_instruction_table[info->ir].instruction(info); } - size = info->pc - (unsigned int)pc; - info->pc = (unsigned int)pc; + size = info->pc - pc; + info->pc = pc; return size; } @@ -5191,7 +5196,7 @@ bool M68K_getInstruction(csh ud, const uint8_t *code, size_t code_len, features = CS_MODE_M68K_000; m68k_setup_internals(info, instr, (uint32_t)address, features); - sz = m68k_disassemble(info, address); + sz = m68k_disassemble(info, (uint32_t)address); if (sz == 0) { *size = 2; diff --git a/arch/M68K/M68KDisassembler.h b/arch/M68K/M68KDisassembler.h index 42db889556..befddaf751 100644 --- a/arch/M68K/M68KDisassembler.h +++ b/arch/M68K/M68KDisassembler.h @@ -265,10 +265,10 @@ typedef struct m68k_info { size_t code_len; uint64_t baseAddress; MCInst *inst; - unsigned int pc; /* program counter */ - unsigned int ir; /* instruction register */ + uint32_t pc; /* program counter */ + uint32_t ir; /* instruction register */ m68k_feature_mask features; - unsigned int address_mask; /* Address mask to simulate address lines */ + uint32_t address_mask; /* Address mask to simulate address lines */ cs_m68k extension; uint16_t regs_read [MAX_IMPL_R_REGS]; // list of implicit registers read by this insn diff --git a/arch/M68K/M68KInstPrinter.c b/arch/M68K/M68KInstPrinter.c index 9c69c5d557..e402279780 100644 --- a/arch/M68K/M68KInstPrinter.c +++ b/arch/M68K/M68KInstPrinter.c @@ -231,8 +231,7 @@ static void printImmediate(SStream *O, const cs_m68k *inst, SStream_concat(O, "#$%" PRIx64, op->imm); } -static void printIndex8BitDisp(SStream *O, unsigned int pc, - const cs_m68k_op *op) +static void printIndex8BitDisp(SStream *O, uint32_t pc, const cs_m68k_op *op) { if (op->address_mode == M68K_AM_PCI_INDEX_8_BIT_DISP) { SStream_concat(O, "$%" PRIx32 "(pc,%s", pc + 2 + op->mem.disp, @@ -247,7 +246,7 @@ static void printIndex8BitDisp(SStream *O, unsigned int pc, SStream_concat0(O, ")"); } -static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op) +static void printRegAddrMode(SStream *O, uint32_t pc, const cs_m68k_op *op) { m68k_reg base_reg = op->type == M68K_OP_MEM ? op->mem.base_reg : op->reg; @@ -281,7 +280,7 @@ static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op) } } -static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op) +static void printBaseDisp(SStream *O, uint32_t pc, const cs_m68k_op *op) { int is_pc = (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP); @@ -313,7 +312,7 @@ static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op) SStream_concat0(O, ")"); } -static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op) +static void printMemIndirect(SStream *O, uint32_t pc, const cs_m68k_op *op) { int is_pc = (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX || op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX); @@ -362,8 +361,8 @@ static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op) SStream_concat0(O, ")"); } -static void printAddressingMode(SStream *O, unsigned int pc, - const cs_m68k *inst, const cs_m68k_op *op) +static void printAddressingMode(SStream *O, uint32_t pc, const cs_m68k *inst, + const cs_m68k_op *op) { switch (op->address_mode) { case M68K_AM_NONE: @@ -431,7 +430,7 @@ static void printAddressingMode(SStream *O, unsigned int pc, SStream_concat0(O, "&"); } -static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext) +static void printCAS2(SStream *O, uint32_t pc, const cs_m68k *ext) { printAddressingMode(O, pc, ext, &ext->operands[0]); SStream_concat0(O, ","); @@ -443,7 +442,7 @@ static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext) s_reg_names[ext->operands[2].reg_pair.reg_1]); } -static void printCacheOp(SStream *O, unsigned int pc, const cs_m68k *ext) +static void printCacheOp(SStream *O, uint32_t pc, const cs_m68k *ext) { static const char *const cache_names[] = { "nc", "dc", "ic", "bc" }; unsigned int sel = (unsigned int)ext->operands[0].imm; From aa79256db35ded51a0ab7a334745d2894f8546be Mon Sep 17 00:00:00 2001 From: billow Date: Tue, 7 Jul 2026 12:42:13 +0800 Subject: [PATCH 4/5] Replace M68K EA macro with explicit if --- arch/M68K/M68KDisassembler.c | 292 +++++++++++++++++++++++++++-------- 1 file changed, 226 insertions(+), 66 deletions(-) diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index 7cf569f58d..62fba0b957 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -143,14 +143,6 @@ static inline void invalid_insn(m68k_info *info) info->pc = (uint32_t)info->baseAddress; } -#define M68K_GET_EA_OR_INVALID(info, op, instruction, size) \ - do { \ - if (!get_ea_mode_op((info), (op), (instruction), (size))) { \ - invalid_insn((info)); \ - return; \ - } \ - } while (0) - /* ======================================================================== */ /* ================================= DATA ================================= */ /* ======================================================================== */ @@ -622,7 +614,10 @@ static void build_re_gen_1(m68k_info *info, bool isDreg, int opcode, op0->reg = M68K_REG_A0 + ((info->ir >> 9) & 7); } - M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); + if (!get_ea_mode_op(info, op1, info->ir, size)) { + invalid_insn(info); + return; + } } static void build_re_1(m68k_info *info, int opcode, uint8_t size) @@ -640,7 +635,10 @@ static void build_er_gen_1(m68k_info *info, bool isDreg, int opcode, op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } if (isDreg) { op1->address_mode = M68K_AM_REG_DIRECT_DATA; @@ -710,7 +708,10 @@ static void build_imm_ea(m68k_info *info, int opcode, uint8_t size, op0->address_mode = M68K_AM_IMMEDIATE; op0->imm = imm; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); + if (!get_ea_mode_op(info, op1, info->ir, size)) { + invalid_insn(info); + return; + } } static void build_3bit_d(m68k_info *info, int opcode, int size) @@ -743,7 +744,10 @@ static void build_3bit_ea(m68k_info *info, int opcode, int size) op0->address_mode = M68K_AM_IMMEDIATE; op0->imm = g_3bit_qdata_table[(info->ir >> 9) & 7]; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); + if (!get_ea_mode_op(info, op1, info->ir, size)) { + invalid_insn(info); + return; + } } static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm) @@ -768,7 +772,10 @@ static void build_mm(m68k_info *info, int opcode, uint8_t size, int imm) static void build_ea(m68k_info *info, int opcode, uint8_t size) { cs_m68k *ext = build_init_op(info, opcode, 1, size); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) { + invalid_insn(info); + return; + } } static void build_ea_a(m68k_info *info, int opcode, uint8_t size) @@ -780,7 +787,10 @@ static void build_ea_a(m68k_info *info, int opcode, uint8_t size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_REG_DIRECT_ADDR; op1->reg = M68K_REG_A0 + ((info->ir >> 9) & 7); @@ -795,10 +805,16 @@ static void build_ea_ea(m68k_info *info, int opcode, int size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); - M68K_GET_EA_OR_INVALID( - info, op1, (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)), - size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } + if (!get_ea_mode_op(info, op1, + (((info->ir >> 9) & 7) | ((info->ir >> 3) & 0x38)), + size)) { + invalid_insn(info); + return; + } } static void build_pi_pi(m68k_info *info, int opcode, int size) @@ -926,7 +942,10 @@ static void build_d_d_ea(m68k_info *info, int opcode, int size) op1->address_mode = M68K_AM_REG_DIRECT_DATA; op1->reg = M68K_REG_D0 + ((extension >> 6) & 7); - M68K_GET_EA_OR_INVALID(info, op2, info->ir, size); + if (!get_ea_mode_op(info, op2, info->ir, size)) { + invalid_insn(info); + return; + } } static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg) @@ -957,7 +976,10 @@ static void build_bitfield_ins(m68k_info *info, int opcode, int has_d_arg) op1->reg = M68K_REG_D0 + ((extension >> 12) & 7); } - M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 1); + if (!get_ea_mode_op(info, op_ea, info->ir, 1)) { + invalid_insn(info); + return; + } op_ea->mem.bitfield = 1; op_ea->mem.width = width; @@ -1111,7 +1133,10 @@ static void build_movem_re(m68k_info *info, int opcode, int size) op0->type = M68K_OP_REG_BITS; op0->register_bits = read_imm_16(info); - M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); + if (!get_ea_mode_op(info, op1, info->ir, size)) { + invalid_insn(info); + return; + } if (op1->address_mode == M68K_AM_REGI_ADDR_PRE_DEC) op0->register_bits = reverse_bits(op0->register_bits); @@ -1129,7 +1154,10 @@ static void build_movem_er(m68k_info *info, int opcode, int size) op1->type = M68K_OP_REG_BITS; op1->register_bits = read_imm_16(info); - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } } static void build_imm(m68k_info *info, int opcode, uint32_t data) @@ -1212,7 +1240,10 @@ static void build_chk2_cmp2(m68k_info *info, int size) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; @@ -1341,9 +1372,15 @@ static void build_moves(m68k_info *info, int size) if (BIT_B(extension)) { op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7); - M68K_GET_EA_OR_INVALID(info, op1, info->ir, size); + if (!get_ea_mode_op(info, op1, info->ir, size)) { + invalid_insn(info); + return; + } } else { - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } op1->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7); } @@ -1448,7 +1485,10 @@ static void dcf_mov3q(m68k_info *info) op1 = &ext->operands[1]; cf_build_imm_op(op0, cf_mov3q_imm(info->ir)); - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); + if (!get_ea_mode_op(info, op1, info->ir, 4)) { + invalid_insn(info); + return; + } } static void cf_init_two_op(m68k_info *info, m68k_insn insn, cs_m68k_op **op0, @@ -1750,7 +1790,10 @@ static void dcf_mac_arith(m68k_info *info) if (is_memory) { op = &ext->operands[ext->op_count++]; - M68K_GET_EA_OR_INVALID(info, op, info->ir, size); + if (!get_ea_mode_op(info, op, info->ir, size)) { + invalid_insn(info); + return; + } if (ext_word & 0x20) op->flags |= M68K_OP_FLAG_MEM_UPDATE; @@ -1783,7 +1826,10 @@ static void dcf_mvs_8(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVS, 2, 1); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1794,7 +1840,10 @@ static void dcf_mvs_16(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVS, 2, 2); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 2); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 2)) { + invalid_insn(info); + return; + } cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1805,7 +1854,10 @@ static void dcf_mvz_8(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVZ, 2, 1); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1816,7 +1868,10 @@ static void dcf_mvz_16(m68k_info *info) LIMIT_FEATURE(info, CS_MODE_M68K_CF_ISA_B | CS_MODE_M68K_CF_ISA_C); ext = build_init_op(info, M68K_INS_MVZ, 2, 2); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 2); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 2)) { + invalid_insn(info); + return; + } cf_build_direct_reg_op(&ext->operands[1], (m68k_reg)(M68K_REG_D0 + ((info->ir >> 9) & 7))); } @@ -1869,7 +1924,10 @@ static void dcf_wddata(m68k_info *info) } ext = build_init_op(info, M68K_INS_WDDATA, 1, size); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) { + invalid_insn(info); + return; + } } static void dcf_wdebug(m68k_info *info) @@ -1884,7 +1942,10 @@ static void dcf_wdebug(m68k_info *info) } ext = build_init_op(info, M68K_INS_WDEBUG, 1, 4); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) { + invalid_insn(info); + return; + } } static void dcf_intouch(m68k_info *info) @@ -1982,9 +2043,15 @@ static void dcf_coproc_ldst(m68k_info *info) cf_build_direct_reg_op(&ext->operands[0], cf_reg_from_nibble((ext_word >> 12) & 0xf)); - M68K_GET_EA_OR_INVALID(info, &ext->operands[1], info->ir, size); + if (!get_ea_mode_op(info, &ext->operands[1], info->ir, size)) { + invalid_insn(info); + return; + } } else { - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, size); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, size)) { + invalid_insn(info); + return; + } cf_build_direct_reg_op(&ext->operands[1], cf_reg_from_nibble((ext_word >> 12) & 0xf)); @@ -2711,7 +2778,10 @@ static void fmove_fpcr(m68k_info *info, uint32_t extension) op_ea = t; } - M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 4); + if (!get_ea_mode_op(info, op_ea, info->ir, 4)) { + invalid_insn(info); + return; + } if (regsel & 4) special->reg = M68K_REG_FPCR; @@ -2741,7 +2811,10 @@ static void fmovem(m68k_info *info, uint32_t extension) op_ea = t; } - M68K_GET_EA_OR_INVALID(info, op_ea, info->ir, 0); + if (!get_ea_mode_op(info, op_ea, info->ir, 0)) { + invalid_insn(info); + return; + } switch (mode) { case 1: // Dynamic list in dn register @@ -3000,23 +3073,35 @@ static void d68020_cpgen(m68k_info *info) switch (src) { case M68K_FPSRC_LONG: ext->op_size.cpu_size = M68K_CPU_SIZE_LONG; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } break; case M68K_FPSRC_BYTE: ext->op_size.cpu_size = M68K_CPU_SIZE_BYTE; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 1); + if (!get_ea_mode_op(info, op0, info->ir, 1)) { + invalid_insn(info); + return; + } break; case M68K_FPSRC_WORD: ext->op_size.cpu_size = M68K_CPU_SIZE_WORD; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); + if (!get_ea_mode_op(info, op0, info->ir, 2)) { + invalid_insn(info); + return; + } break; case M68K_FPSRC_SINGLE: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_SINGLE; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } if (op0->address_mode == M68K_AM_IMMEDIATE) { op0->simm = BitsToFloat(op0->imm); op0->type = M68K_OP_FP_SINGLE; @@ -3026,7 +3111,10 @@ static void d68020_cpgen(m68k_info *info) case M68K_FPSRC_DOUBLE: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_DOUBLE; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 8); + if (!get_ea_mode_op(info, op0, info->ir, 8)) { + invalid_insn(info); + return; + } if (op0->address_mode == M68K_AM_IMMEDIATE) op0->type = M68K_OP_FP_DOUBLE; break; @@ -3034,13 +3122,19 @@ static void d68020_cpgen(m68k_info *info) case M68K_FPSRC_EXTENDED: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 12); + if (!get_ea_mode_op(info, op0, info->ir, 12)) { + invalid_insn(info); + return; + } break; case M68K_FPSRC_PACKED: ext->op_size.type = M68K_SIZE_TYPE_FPU; ext->op_size.fpu_size = M68K_FPU_SIZE_EXTENDED; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 12); + if (!get_ea_mode_op(info, op0, info->ir, 12)) { + invalid_insn(info); + return; + } break; default: @@ -3062,7 +3156,10 @@ static void d68020_cprestore(m68k_info *info) REQUIRE_CPID_FPU(info); ext = build_init_op(info, M68K_INS_FRESTORE, 1, 0); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } } static void d68020_cpsave(m68k_info *info) @@ -3072,7 +3169,10 @@ static void d68020_cpsave(m68k_info *info) REQUIRE_CPID_FPU(info); ext = build_init_op(info, M68K_INS_FSAVE, 1, 0); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } } static void d68040_pflush_or_cpsave(m68k_info *info) @@ -3105,7 +3205,10 @@ static void d68020_cpscc(m68k_info *info) ext = build_init_op(info, M68K_INS_FSF, 1, 1); info->inst->Opcode += M68K_FP_COND(read_imm_16(info)); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } } static void d68020_cptrapcc_0(m68k_info *info) @@ -3225,7 +3328,10 @@ static void d68020_divl(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG_PAIR; @@ -3337,14 +3443,20 @@ static void d68000_jmp(m68k_info *info) { cs_m68k *ext = build_init_op(info, M68K_INS_JMP, 1, 0); set_insn_group(info, M68K_GRP_JUMP); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) { + invalid_insn(info); + return; + } } static void d68000_jsr(m68k_info *info) { cs_m68k *ext = build_init_op(info, M68K_INS_JSR, 1, 0); set_insn_group(info, M68K_GRP_JUMP); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 4); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 4)) { + invalid_insn(info); + return; + } } static void d68000_lea(m68k_info *info) @@ -3474,7 +3586,10 @@ static void d68000_move_to_ccr(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 1); + if (!get_ea_mode_op(info, op0, info->ir, 1)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->reg = M68K_REG_CCR; @@ -3502,7 +3617,10 @@ static void d68010_move_fr_ccr(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->reg = M68K_REG_CCR; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); + if (!get_ea_mode_op(info, op1, info->ir, 1)) { + invalid_insn(info); + return; + } } static void d68000_move_fr_sr(m68k_info *info) @@ -3524,7 +3642,10 @@ static void d68000_move_fr_sr(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->reg = M68K_REG_SR; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 2); + if (!get_ea_mode_op(info, op1, info->ir, 2)) { + invalid_insn(info); + return; + } } static void d68000_move_to_sr(m68k_info *info) @@ -3543,7 +3664,10 @@ static void d68000_move_to_sr(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); + if (!get_ea_mode_op(info, op0, info->ir, 2)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->reg = M68K_REG_SR; @@ -3861,7 +3985,10 @@ static void d68020_mull(m68k_info *info) op0 = &ext->operands[0]; op1 = &ext->operands[1]; - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } reg_0 = extension & 7; reg_1 = (extension >> 12) & 7; @@ -4215,7 +4342,10 @@ static void d68000_scc(m68k_info *info) { cs_m68k *ext = build_init_op( info, s_scc_lut[M68K_IR_CONDITION_NIBBLE(info)], 1, 1); - M68K_GET_EA_OR_INVALID(info, &ext->operands[0], info->ir, 1); + if (!get_ea_mode_op(info, &ext->operands[0], info->ir, 1)) { + invalid_insn(info); + return; + } } static void d68000_stop(m68k_info *info) @@ -4387,7 +4517,10 @@ static void d68cpu32_tbl(m68k_info *info) op1 = &cs_ext->operands[1]; if (is_memory) { - M68K_GET_EA_OR_INVALID(info, op0, info->ir, size); + if (!get_ea_mode_op(info, op0, info->ir, size)) { + invalid_insn(info); + return; + } } else { int dm = info->ir & 7; int dn = ext_word & 7; @@ -4462,9 +4595,15 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = pmmu_reg; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); + if (!get_ea_mode_op(info, op1, info->ir, 4)) { + invalid_insn(info); + return; + } } else { - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = pmmu_reg; @@ -4510,7 +4649,10 @@ static void d68030_pmmu(m68k_info *info) op1->address_mode = M68K_AM_IMMEDIATE; op1->imm = mask; - M68K_GET_EA_OR_INVALID(info, op2, info->ir, 1); + if (!get_ea_mode_op(info, op2, info->ir, 1)) { + invalid_insn(info); + return; + } } else { int fc_source = cmd & 0x1f; int is_read; @@ -4532,7 +4674,10 @@ static void d68030_pmmu(m68k_info *info) op1 = &ext->operands[1]; pmmu_decode_fc(info, op0, fc_source); - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); + if (!get_ea_mode_op(info, op1, info->ir, 1)) { + invalid_insn(info); + return; + } } break; } @@ -4578,9 +4723,15 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = pmmu_reg; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 4); + if (!get_ea_mode_op(info, op1, info->ir, 4)) { + invalid_insn(info); + return; + } } else { - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 4); + if (!get_ea_mode_op(info, op0, info->ir, 4)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = pmmu_reg; @@ -4609,9 +4760,15 @@ static void d68030_pmmu(m68k_info *info) op0->address_mode = M68K_AM_NONE; op0->type = M68K_OP_REG; op0->reg = M68K_REG_MMUSR; - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 2); + if (!get_ea_mode_op(info, op1, info->ir, 2)) { + invalid_insn(info); + return; + } } else { - M68K_GET_EA_OR_INVALID(info, op0, info->ir, 2); + if (!get_ea_mode_op(info, op0, info->ir, 2)) { + invalid_insn(info); + return; + } op1->address_mode = M68K_AM_NONE; op1->type = M68K_OP_REG; op1->reg = M68K_REG_MMUSR; @@ -4643,7 +4800,10 @@ static void d68030_pmmu(m68k_info *info) op2 = &ext->operands[2]; pmmu_decode_fc(info, op0, fc_source); - M68K_GET_EA_OR_INVALID(info, op1, info->ir, 1); + if (!get_ea_mode_op(info, op1, info->ir, 1)) { + invalid_insn(info); + return; + } op2->type = M68K_OP_IMM; op2->address_mode = M68K_AM_IMMEDIATE; From 7f4b6a357a5714281e3e73c56e18854e1ea52b57 Mon Sep 17 00:00:00 2001 From: billow Date: Tue, 7 Jul 2026 21:47:32 +0800 Subject: [PATCH 5/5] Update arch/M68K/M68KDisassembler.c Co-authored-by: Rot127 <45763064+Rot127@users.noreply.github.com>