mirror of
https://github.com/pevans/erc-c.git
synced 2025-08-15 03:27:19 +00:00
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.
This commit is contained in:
@@ -136,13 +136,13 @@ extern int mos6502_instruction(vm_8bit);
|
|||||||
extern mos6502 *mos6502_create(vm_segment *, vm_segment *);
|
extern mos6502 *mos6502_create(vm_segment *, vm_segment *);
|
||||||
extern mos6502_instruction_handler mos6502_get_instruction_handler(vm_8bit);
|
extern mos6502_instruction_handler mos6502_get_instruction_handler(vm_8bit);
|
||||||
extern vm_16bit mos6502_get16(mos6502 *, size_t);
|
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_get(mos6502 *, size_t);
|
||||||
|
extern vm_8bit mos6502_pop_stack(mos6502 *);
|
||||||
extern void mos6502_execute(mos6502 *);
|
extern void mos6502_execute(mos6502 *);
|
||||||
extern void mos6502_free(mos6502 *);
|
extern void mos6502_free(mos6502 *);
|
||||||
extern void mos6502_last_executed(mos6502 *, vm_8bit *, vm_8bit *, vm_16bit *);
|
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_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_set(mos6502 *, size_t, vm_8bit);
|
||||||
extern void mos6502_set16(mos6502 *, size_t, vm_16bit);
|
extern void mos6502_set16(mos6502 *, size_t, vm_16bit);
|
||||||
extern void mos6502_set_memory(mos6502 *, vm_segment *, vm_segment *);
|
extern void mos6502_set_memory(mos6502 *, vm_segment *, vm_segment *);
|
||||||
|
@@ -254,7 +254,7 @@ apple2_reset(apple2 *mach)
|
|||||||
{
|
{
|
||||||
mach->cpu->P = MOS_INTERRUPT;
|
mach->cpu->P = MOS_INTERRUPT;
|
||||||
mach->cpu->PC = vm_segment_get16(mach->main, 0xFFFC);
|
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
|
// Switch video mode back to 40 column text
|
||||||
apple2_set_display(mach, DISPLAY_DEFAULT);
|
apple2_set_display(mach, DISPLAY_DEFAULT);
|
||||||
|
@@ -163,7 +163,7 @@ mos6502_create(vm_segment *rmem, vm_segment *wmem)
|
|||||||
cpu->X = 0;
|
cpu->X = 0;
|
||||||
cpu->Y = 0;
|
cpu->Y = 0;
|
||||||
cpu->P = 0;
|
cpu->P = 0;
|
||||||
cpu->S = 0;
|
cpu->S = 0xff;
|
||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
@@ -189,29 +189,29 @@ mos6502_free(mos6502 *cpu)
|
|||||||
* 256, addresses.
|
* 256, addresses.
|
||||||
*/
|
*/
|
||||||
void
|
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
|
// And finally we need to increment S by 2 (since we've used two
|
||||||
// bytes in the stack).
|
// bytes in the stack).
|
||||||
cpu->S += 2;
|
cpu->S--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pop an address from the stack and return that.
|
* Pop an address from the stack and return that.
|
||||||
*/
|
*/
|
||||||
vm_16bit
|
vm_8bit
|
||||||
mos6502_pop_stack(mos6502 *cpu)
|
mos6502_pop_stack(mos6502 *cpu)
|
||||||
{
|
{
|
||||||
// The first thing we want to do here is to decrement S by 2, since
|
// 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.
|
// 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
|
// 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
|
// bytes we retrieve from the stack into the actual position we
|
||||||
// would use for the PC register.
|
// would use for the PC register.
|
||||||
return mos6502_get16(cpu, 0x0100 + cpu->S);
|
return mos6502_get(cpu, 0x0100 + cpu->S);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -14,7 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
DEFINE_INST(brk)
|
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);
|
mos6502_push_stack(cpu, cpu->P);
|
||||||
cpu->P |= MOS_INTERRUPT;
|
cpu->P |= MOS_INTERRUPT;
|
||||||
cpu->PC += 2;
|
cpu->PC += 2;
|
||||||
@@ -36,7 +37,10 @@ DEFINE_INST(jmp)
|
|||||||
*/
|
*/
|
||||||
DEFINE_INST(jsr)
|
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;
|
cpu->PC = cpu->eff_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +61,7 @@ DEFINE_INST(rti)
|
|||||||
{
|
{
|
||||||
cpu->P = mos6502_pop_stack(cpu);
|
cpu->P = mos6502_pop_stack(cpu);
|
||||||
cpu->PC = 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)
|
DEFINE_INST(rts)
|
||||||
{
|
{
|
||||||
cpu->PC = mos6502_pop_stack(cpu);
|
cpu->PC = mos6502_pop_stack(cpu);
|
||||||
|
cpu->PC |= mos6502_pop_stack(cpu) << 8;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user