Skip to content

Commit c9a6051

Browse files
committed
Add tests for bitfield instructions and PC-relative addressing in m68k.yaml
1 parent 46fa2a8 commit c9a6051

2 files changed

Lines changed: 137 additions & 8 deletions

File tree

arch/M68K/M68KDisassembler.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,10 @@ static void get_with_index_address_mode(m68k_info *info, cs_m68k_op *op,
494494
uint32_t instruction, uint32_t size,
495495
bool is_pc)
496496
{
497+
uint32_t ext_addr = info->pc;
497498
uint32_t extension = read_imm_16(info);
499+
int32_t pc_adjust =
500+
is_pc ? (int32_t)(ext_addr - info->baseAddress - 2) : 0;
498501

499502
op->address_mode = M68K_AM_AREGI_INDEX_BASE_DISP;
500503

@@ -511,6 +514,7 @@ static void get_with_index_address_mode(m68k_info *info, cs_m68k_op *op,
511514
read_imm_32(info) :
512515
(int16_t)read_imm_16(info)) :
513516
0;
517+
op->mem.in_disp += pc_adjust;
514518

515519
op->mem.in_disp_size =
516520
EXT_BASE_DISPLACEMENT_PRESENT(extension) &&
@@ -590,6 +594,7 @@ static void get_with_index_address_mode(m68k_info *info, cs_m68k_op *op,
590594
}
591595

592596
op->mem.disp = (int8_t)(extension & 0xff);
597+
op->mem.disp += pc_adjust;
593598
op->mem.disp_size = 0;
594599

595600
if (EXT_INDEX_SCALE(extension)) {
@@ -712,12 +717,22 @@ static void get_ea_mode_op(m68k_info *info, cs_m68k_op *op,
712717
op->imm = read_imm_32(info);
713718
break;
714719

715-
case 0x3a:
720+
case 0x3a: {
716721
/* program counter with displacement */
722+
/* The printer computes the effective address as
723+
* instruction_start + 2 + disp, assuming the displacement
724+
* extension word immediately follows the opcode word.
725+
* When extra words precede the EA (e.g. an immediate in
726+
* BTST #imm,disp(PC)), the displacement word is further
727+
* along. Adjust disp so the printer still produces the
728+
* correct absolute address. */
729+
uint32_t disp_addr = info->pc;
717730
op->address_mode = M68K_AM_PCI_DISP;
718731
op->mem.disp = (int16_t)read_imm_16(info);
732+
op->mem.disp += (int16_t)(disp_addr - info->baseAddress - 2);
719733
op->mem.disp_size = 1;
720734
break;
735+
}
721736

722737
case 0x3b:
723738
/* program counter with index */
@@ -1761,31 +1776,33 @@ static void d68010_bkpt(m68k_info *info)
17611776

17621777
static void d68020_bfchg(m68k_info *info)
17631778
{
1764-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1779+
/* Bit field ops are 68020+ only; CPU32 does NOT support them
1780+
* despite sharing TYPE_68020. */
1781+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17651782
build_bitfield_ins(info, M68K_INS_BFCHG, false);
17661783
}
17671784

17681785
static void d68020_bfclr(m68k_info *info)
17691786
{
1770-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1787+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17711788
build_bitfield_ins(info, M68K_INS_BFCLR, false);
17721789
}
17731790

17741791
static void d68020_bfexts(m68k_info *info)
17751792
{
1776-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1793+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17771794
build_bitfield_ins(info, M68K_INS_BFEXTS, true);
17781795
}
17791796

17801797
static void d68020_bfextu(m68k_info *info)
17811798
{
1782-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1799+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17831800
build_bitfield_ins(info, M68K_INS_BFEXTU, true);
17841801
}
17851802

17861803
static void d68020_bfffo(m68k_info *info)
17871804
{
1788-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1805+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17891806
build_bitfield_ins(info, M68K_INS_BFFFO, true);
17901807
}
17911808

@@ -1794,7 +1811,7 @@ static void d68020_bfins(m68k_info *info)
17941811
cs_m68k *ext = &info->extension;
17951812
cs_m68k_op temp;
17961813

1797-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1814+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
17981815
build_bitfield_ins(info, M68K_INS_BFINS, true);
17991816

18001817
// a bit hacky but we need to flip the args on only this instruction
@@ -1806,12 +1823,13 @@ static void d68020_bfins(m68k_info *info)
18061823

18071824
static void d68020_bfset(m68k_info *info)
18081825
{
1809-
LIMIT_CPU_TYPES(info, M68020_PLUS);
1826+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
18101827
build_bitfield_ins(info, M68K_INS_BFSET, false);
18111828
}
18121829

18131830
static void d68020_bftst(m68k_info *info)
18141831
{
1832+
LIMIT_CPU_TYPES_NOT_CPU32(info, M68020_PLUS);
18151833
build_bitfield_ins(info, M68K_INS_BFTST, false);
18161834
}
18171835

tests/details/m68k.yaml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,3 +2403,114 @@ test_cases:
24032403
asm_text: "dc.w $f000"
24042404
-
24052405
asm_text: "move.l d0, d2"
2406+
2407+
# Bug 15a: Bitfield instructions (bftst etc.) must be illegal on 68000
2408+
# Full encoding: e8f8 0800 009c = bftst $9c.w{d0:32} on 68020+
2409+
# On 68000, e8f8 has size bits=11 which is undefined → dc.w, remainder = btst
2410+
-
2411+
input:
2412+
bytes: [ 0xe8, 0xf8, 0x08, 0x00, 0x00, 0x9c ]
2413+
arch: "m68k"
2414+
options: [ CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_000 ]
2415+
address: 0x0
2416+
expected:
2417+
insns:
2418+
-
2419+
asm_text: "dc.w $e8f8"
2420+
-
2421+
asm_text: "btst.b #$9c, d0"
2422+
2423+
# Bug 15b: Bitfield instructions must be illegal on CPU32
2424+
# CPU32 has TYPE_68020|TYPE_CPU32, so LIMIT_CPU_TYPES_NOT_CPU32 rejects it
2425+
-
2426+
input:
2427+
bytes: [ 0xe8, 0xf8, 0x08, 0x00, 0x00, 0x9c ]
2428+
arch: "m68k"
2429+
options: [ CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_CPU32 ]
2430+
address: 0x0
2431+
expected:
2432+
insns:
2433+
-
2434+
asm_text: "dc.w $e8f8"
2435+
-
2436+
asm_text: "btst.b #$9c, d0"
2437+
2438+
# Bug 15c: Bitfield instructions valid on 68020 — full 3-word encoding
2439+
-
2440+
input:
2441+
bytes: [ 0xe8, 0xf8, 0x08, 0x00, 0x00, 0x9c ]
2442+
arch: "m68k"
2443+
options: [ CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_020 ]
2444+
address: 0x0
2445+
expected:
2446+
insns:
2447+
-
2448+
asm_text: "bftst $9c.w{0:32}"
2449+
details:
2450+
m68k:
2451+
operands:
2452+
-
2453+
type: M68K_OP_MEM
2454+
address_mode: M68K_AM_ABSOLUTE_DATA_SHORT
2455+
2456+
# Bug 16: btst PC-relative displacement (case 0x3a) must account for
2457+
# extra words consumed before the displacement word.
2458+
# Encoding: 083a 00e8 0a54 at address 0x1050
2459+
# btst #$e8, d16(PC) where d16=0x0a54, read at PC=0x1054
2460+
# Target: 0x1054 + 0x0a54 = 0x1aa8
2461+
# Printer: pc + 2 + disp = 0x1050 + 2 + disp => disp must be 0xa56
2462+
-
2463+
input:
2464+
bytes: [ 0x08, 0x3a, 0x00, 0xe8, 0x0a, 0x54 ]
2465+
arch: "m68k"
2466+
options: [ CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_000 ]
2467+
address: 0x1050
2468+
expected:
2469+
insns:
2470+
-
2471+
asm_text: "btst.b #$e8, $1aa8(pc)"
2472+
details:
2473+
m68k:
2474+
operands:
2475+
-
2476+
type: M68K_OP_IMM
2477+
imm: 0xe8
2478+
-
2479+
type: M68K_OP_MEM
2480+
mem:
2481+
disp: 0xa56
2482+
disp_size: 1
2483+
address_mode: M68K_AM_PCI_DISP
2484+
2485+
# Bug 17: btst PC-relative indexed (case 0x3b) must account for
2486+
# extra words consumed before the extension word.
2487+
# Encoding: 083b 0038 0039 at address 0x3400
2488+
# btst #$38, (d8,PC,d0.w) where ext=0x0039 (brief: d0.w*1, disp=0x39)
2489+
# Extension read at PC=0x3404
2490+
# Target: 0x3404 + 0x39 = 0x343d
2491+
# Printer: pc + 2 + disp = 0x3400 + 2 + disp => disp must be 0x3b
2492+
-
2493+
input:
2494+
bytes: [ 0x08, 0x3b, 0x00, 0x38, 0x00, 0x39 ]
2495+
arch: "m68k"
2496+
options: [ CS_OPT_DETAIL, CS_MODE_BIG_ENDIAN, CS_MODE_M68K_000 ]
2497+
address: 0x3400
2498+
expected:
2499+
insns:
2500+
-
2501+
asm_text: "btst.b #$38, $343d(pc, d0.w)"
2502+
details:
2503+
regs_read: [ d0, pc ]
2504+
m68k:
2505+
operands:
2506+
-
2507+
type: M68K_OP_IMM
2508+
imm: 0x38
2509+
-
2510+
type: M68K_OP_MEM
2511+
mem:
2512+
base_reg: pc
2513+
index_reg: d0
2514+
index_size: -1
2515+
disp: 0x3b
2516+
address_mode: M68K_AM_PCI_INDEX_8_BIT_DISP

0 commit comments

Comments
 (0)