From a3707d3c995142cf27af508e56db8972d66f5607 Mon Sep 17 00:00:00 2001 From: pos Date: Fri, 9 Oct 2026 03:25:43 +0200 Subject: [PATCH 1/3] cpu: support 68020 full extension JSR with base displacement, no indirect (M294) --- src/cpu.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index 724c117..add9785 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -600,17 +600,39 @@ static int reference_step(struct amivm_cpu_state *cpu, struct amivm_vm *vm) uint32_t index, target, sp; if (fetch16(cpu, vm, next_pc, &ext) != 0) return deliver_fault(cpu, vm, instruction_pc); - /* Full-format extensions are 68020+ and not handled here. */ - if ((ext & 0x0100u) != 0u) { - set_fault(cpu, AMIVM_CPU_FAULT_ILLEGAL, instruction_pc, opcode); - return deliver_fault(cpu, vm, instruction_pc); - } index = (ext & 0x8000u) ? cpu->a[(ext >> 12u) & 7u] : cpu->d[(ext >> 12u) & 7u]; if ((ext & 0x0800u) == 0u) index = (uint32_t)(int32_t)(int16_t)(index & 0xffffu); - target = cpu->a[reg] + index + (uint32_t)(int32_t)(int8_t)(ext & 0xffu); - sp = cpu->a[7] - 4u; - if (!cpu_write32(cpu, vm, sp, is_supervisor(cpu), next_pc + 2u)) + if ((ext & 0x0100u) != 0u) { /* 68020+ full extension, no memory indirect */ + uint32_t base = (ext & 0x0080u) ? 0u : cpu->a[reg]; + uint32_t displacement = 0u; + unsigned bd_size = (unsigned)((ext >> 4u) & 3u); + if ((ext & 0x000fu) != 0u || bd_size == 0u) { + set_fault(cpu, AMIVM_CPU_FAULT_ILLEGAL, instruction_pc, opcode); + return deliver_fault(cpu, vm, instruction_pc); + } + if (bd_size == 2u) { + uint16_t word; + if (fetch16(cpu, vm, next_pc + 2u, &word) != 0) + return deliver_fault(cpu, vm, instruction_pc); + displacement = (uint32_t)(int32_t)(int16_t)word; + } else if (bd_size == 3u) { + if (fetch32(cpu, vm, next_pc + 2u, &displacement) != 0) + return deliver_fault(cpu, vm, instruction_pc); + } + if ((ext & 0x0040u) != 0u) index = 0u; + else index <<= (ext >> 9u) & 3u; + target = base + displacement + index; + sp = cpu->a[7] - 4u; + if (!cpu_write32(cpu, vm, sp, is_supervisor(cpu), + next_pc + 2u + (bd_size == 2u ? 2u : bd_size == 3u ? 4u : 0u))) + return deliver_fault(cpu, vm, instruction_pc); + } else { + target = cpu->a[reg] + index + (uint32_t)(int32_t)(int8_t)(ext & 0xffu); + sp = cpu->a[7] - 4u; + if (!cpu_write32(cpu, vm, sp, is_supervisor(cpu), next_pc + 2u)) + return deliver_fault(cpu, vm, instruction_pc); + } return deliver_fault(cpu, vm, instruction_pc); cpu->a[7] = sp; save_active_sp(cpu); From 681155a1f0c16d2c6718e86dd17c8517563d17e8 Mon Sep 17 00:00:00 2001 From: pos Date: Fri, 9 Oct 2026 03:25:49 +0200 Subject: [PATCH 2/3] test: add full extension base-displacement JSR differential (M294) --- tests/test_m283.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_m283.c b/tests/test_m283.c index 862c7f3..c37866c 100644 --- a/tests/test_m283.c +++ b/tests/test_m283.c @@ -234,6 +234,16 @@ int main(void) { sizeof(jsr_a1_word_negative_disp),0u,1,0u,6u)==0); CHECK(run_case_index("JSR A1.L positive",jsr_a1_long_positive, sizeof(jsr_a1_long_positive),0u,1,0u,2u)==0); + /* M294: 68020 full extension, base A0 + signed word displacement. + * Index suppressed, no memory indirect: target ROM+0x110. */ + static const uint8_t jsr_full_word_bd[] = { + 0x4eu,0xb0u,0x01u,0x60u,0x00u,0x04u, /* JSR ([A0]+4), full ext */ + 0x60u,0xfeu, /* BRA.S self */ + 0x4eu,0x71u,0x4eu,0x71u,0x4eu,0x71u, + 0x4eu,0x71u,0x4eu,0x75u /* +16: RTS */ + }; + CHECK(run_case_setup("JSR full extension word base displacement / RTS", + jsr_full_word_bd,sizeof(jsr_full_word_bd),0u,1)==0); /* Exercise data-register and condition-code changes before a BRA loop. */ static const uint8_t moveq_zero_bra[] = {0x70u,0x00u,0x60u,0xfeu}; static const uint8_t moveq_neg_bra[] = {0x70u,0xffu,0x60u,0xfeu}; From 801a8532a25ef1ed0522d31f32aa4558b8898259 Mon Sep 17 00:00:00 2001 From: pos Date: Fri, 9 Oct 2026 03:26:28 +0200 Subject: [PATCH 3/3] fix: remove unconditional fault after indexed JSR address resolution --- src/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpu.c b/src/cpu.c index add9785..cdb310b 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -633,7 +633,6 @@ static int reference_step(struct amivm_cpu_state *cpu, struct amivm_vm *vm) if (!cpu_write32(cpu, vm, sp, is_supervisor(cpu), next_pc + 2u)) return deliver_fault(cpu, vm, instruction_pc); } - return deliver_fault(cpu, vm, instruction_pc); cpu->a[7] = sp; save_active_sp(cpu); cpu->pc = target;