From 0581ed6b441d8df65967137659f92e392a055698 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Sun, 21 Jan 2018 01:09:42 -0600 Subject: [PATCH] Fix stack in several ways 1. The stack should descend, not ascend; 2. The stack should be pushed byte for byte; meaning, when pushing P or A, those should consume one byte, not two; 3. The MSB should be pushed first when doing JSR and BRK, which makes some sense if you were reading the stack from $0100 - $01FF. --- include/mos6502.h | 4 ++-- src/apple2.c | 2 +- src/mos6502.c | 14 +++++++------- src/mos6502.exec.c | 10 ++++++++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/include/mos6502.h b/include/mos6502.h index 95bba8c..9fb056f 100644 --- a/include/mos6502.h +++ b/include/mos6502.h @@ -136,13 +136,13 @@ extern int mos6502_instruction(vm_8bit); extern mos6502 *mos6502_create(vm_segment *, vm_segment *); extern mos6502_instruction_handler mos6502_get_instruction_handler(vm_8bit); extern vm_16bit mos6502_get16(mos6502 *, size_t); -extern vm_16bit mos6502_pop_stack(mos6502 *); extern vm_8bit mos6502_get(mos6502 *, size_t); +extern vm_8bit mos6502_pop_stack(mos6502 *); extern void mos6502_execute(mos6502 *); extern void mos6502_free(mos6502 *); extern void mos6502_last_executed(mos6502 *, vm_8bit *, vm_8bit *, vm_16bit *); extern void mos6502_modify_status(mos6502 *, vm_8bit, int, int); -extern void mos6502_push_stack(mos6502 *, vm_16bit); +extern void mos6502_push_stack(mos6502 *, vm_8bit); extern void mos6502_set(mos6502 *, size_t, vm_8bit); extern void mos6502_set16(mos6502 *, size_t, vm_16bit); extern void mos6502_set_memory(mos6502 *, vm_segment *, vm_segment *); diff --git a/src/apple2.c b/src/apple2.c index deb6857..63da6f2 100644 --- a/src/apple2.c +++ b/src/apple2.c @@ -254,7 +254,7 @@ apple2_reset(apple2 *mach) { mach->cpu->P = MOS_INTERRUPT; mach->cpu->PC = vm_segment_get16(mach->main, 0xFFFC); - mach->cpu->S = 0; + mach->cpu->S = 0xff; // Switch video mode back to 40 column text apple2_set_display(mach, DISPLAY_DEFAULT); diff --git a/src/mos6502.c b/src/mos6502.c index efc3424..bb586e6 100644 --- a/src/mos6502.c +++ b/src/mos6502.c @@ -163,7 +163,7 @@ mos6502_create(vm_segment *rmem, vm_segment *wmem) cpu->X = 0; cpu->Y = 0; cpu->P = 0; - cpu->S = 0; + cpu->S = 0xff; return cpu; } @@ -189,29 +189,29 @@ mos6502_free(mos6502 *cpu) * 256, addresses. */ void -mos6502_push_stack(mos6502 *cpu, vm_16bit addr) +mos6502_push_stack(mos6502 *cpu, vm_8bit addr) { - mos6502_set16(cpu, 0x100 + cpu->S, addr); + mos6502_set(cpu, 0x100 + cpu->S, addr); // And finally we need to increment S by 2 (since we've used two // bytes in the stack). - cpu->S += 2; + cpu->S--; } /* * Pop an address from the stack and return that. */ -vm_16bit +vm_8bit mos6502_pop_stack(mos6502 *cpu) { // The first thing we want to do here is to decrement S by 2, since // the value we want to return is two positions back. - cpu->S -= 2; + cpu->S++; // We need to use a bitwise-or operation to combine the hi and lo // bytes we retrieve from the stack into the actual position we // would use for the PC register. - return mos6502_get16(cpu, 0x0100 + cpu->S); + return mos6502_get(cpu, 0x0100 + cpu->S); } /* diff --git a/src/mos6502.exec.c b/src/mos6502.exec.c index 545542a..14146a7 100644 --- a/src/mos6502.exec.c +++ b/src/mos6502.exec.c @@ -14,7 +14,8 @@ */ DEFINE_INST(brk) { - mos6502_push_stack(cpu, cpu->PC); + mos6502_push_stack(cpu, cpu->PC >> 8); + mos6502_push_stack(cpu, cpu->PC & 0xff); mos6502_push_stack(cpu, cpu->P); cpu->P |= MOS_INTERRUPT; cpu->PC += 2; @@ -36,7 +37,10 @@ DEFINE_INST(jmp) */ DEFINE_INST(jsr) { - mos6502_push_stack(cpu, cpu->PC + 3); + vm_16bit pc3 = cpu->PC + 3; + + mos6502_push_stack(cpu, pc3 >> 8); + mos6502_push_stack(cpu, pc3 & 0xff); cpu->PC = cpu->eff_addr; } @@ -57,6 +61,7 @@ DEFINE_INST(rti) { cpu->P = mos6502_pop_stack(cpu); cpu->PC = mos6502_pop_stack(cpu); + cpu->PC |= mos6502_pop_stack(cpu) << 8; } /* @@ -66,4 +71,5 @@ DEFINE_INST(rti) DEFINE_INST(rts) { cpu->PC = mos6502_pop_stack(cpu); + cpu->PC |= mos6502_pop_stack(cpu) << 8; }