Skip to content

Commit

Permalink
SmartStack improvements. Can now detect the rti shim for restoring ba…
Browse files Browse the repository at this point in the history
…nks when leaving interrupt logic.
  • Loading branch information
indigodarkwolf committed Dec 5, 2023
1 parent 4d195ab commit bb03daa
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 46 deletions.
31 changes: 19 additions & 12 deletions src/cpu/fake6502.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ uint8_t debug6502 = 0;
uint8_t penaltyop, penaltyaddr;
uint8_t waiting = 0;

_smart_stack stack6502[256];
_smart_stack stack6502[256];
uint8_t stack6502_underflow = 0;

// externally supplied functions
extern uint8_t read6502(uint16_t address);
Expand Down Expand Up @@ -128,9 +129,11 @@ static void putvalue(uint16_t saveval)

void nmi6502()
{
auto &ss = stack6502[state6502.sp_depth++];
ss.source_pc = state6502.pc;
auto &ss = stack6502[state6502.sp_depth++];
ss.source_pc = state6502.pc;
ss.source_bank = bank6502(state6502.pc);
ss.push_depth = 0;
state6502.sp_unwind_depth = state6502.sp_depth;

push16(state6502.pc);
push8(state6502.status & ~FLAG_BREAK);
Expand All @@ -140,18 +143,21 @@ void nmi6502()
state6502.pc = (uint16_t)read6502(0xFFFA) | ((uint16_t)read6502(0xFFFB) << 8);
waiting = 0;

ss.dest_pc = state6502.pc;
ss.dest_pc = state6502.pc;
ss.dest_bank = bank6502(state6502.pc);
ss.op_type = _stack_op_type::nmi;
ss.opcode = 0;
ss.op_type = _stack_op_type::nmi;
ss.pop_type = _stack_pop_type::unknown;
ss.opcode = 0;
}

void irq6502()
{
if (!(state6502.status & FLAG_INTERRUPT)) {
auto &ss = stack6502[state6502.sp_depth++];
ss.source_pc = state6502.pc;
auto &ss = stack6502[state6502.sp_depth++];
ss.source_pc = state6502.pc;
ss.source_bank = bank6502(state6502.pc);
ss.push_depth = 0;
state6502.sp_unwind_depth = state6502.sp_depth;

push16(state6502.pc);
push8(state6502.status & ~FLAG_BREAK);
Expand All @@ -160,10 +166,11 @@ void irq6502()
vp6502();
state6502.pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);

ss.dest_pc = state6502.pc;
ss.dest_pc = state6502.pc;
ss.dest_bank = bank6502(state6502.pc);
ss.op_type = _stack_op_type::irq;
ss.opcode = 0;
ss.pop_type = _stack_pop_type::unknown;
ss.opcode = 0;
}
waiting = 0;
}
Expand Down Expand Up @@ -198,7 +205,7 @@ void exec6502(uint32_t tickcount)
(*addrtable[opcode])();
(*optable[opcode])();

if (debug6502 & (DEBUG6502_READ | DEBUG6502_WRITE)) {
if ((debug6502 & (DEBUG6502_READ | DEBUG6502_WRITE)) || stack6502_underflow) {
state6502 = debug_state6502;
clockticks6502 = debug_clockticks6502;
return;
Expand Down Expand Up @@ -240,7 +247,7 @@ void step6502()
(*addrtable[opcode])();
(*optable[opcode])();

if (debug6502 & (DEBUG6502_READ | DEBUG6502_WRITE)) {
if ((debug6502 & (DEBUG6502_READ | DEBUG6502_WRITE)) || stack6502_underflow) {
state6502 = debug_state6502;
clockticks6502 = debug_clockticks6502;
return;
Expand Down
43 changes: 35 additions & 8 deletions src/cpu/fake6502.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,50 @@

struct _state6502 {
uint16_t pc;
uint8_t sp_depth;
uint8_t sp_depth;
uint8_t sp_unwind_depth;
uint8_t sp, a, x, y, status;
};

enum class _stack_op_type : uint8_t {
op,
nmi,
irq,
jsr,
smart,
};

enum class _stack_pop_type : uint8_t {
unknown,
rts,
rti
};

enum class _push_op_type : uint8_t {
unknown,
a,
x,
y,
status
};

struct _smart_stack_ex {
_push_op_type push_type;
_push_op_type pull_type;
uint8_t value;
};

struct _smart_stack {
uint16_t source_pc;
uint16_t dest_pc;
uint8_t source_bank;
uint8_t dest_bank;
_stack_op_type op_type;
uint8_t opcode;
uint16_t source_pc;
uint16_t dest_pc;
uint8_t source_bank;
uint8_t dest_bank;
_stack_op_type op_type;
_stack_pop_type pop_type;
uint16_t pop_pc;
uint8_t pop_bank;
uint8_t opcode;
uint8_t push_depth;
_smart_stack_ex pushed_bytes[256];
};

extern void init6502();
Expand Down
58 changes: 56 additions & 2 deletions src/cpu/instructions_6502.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,16 @@ jsr()
auto &ss = stack6502[state6502.sp_depth++];
ss.source_pc = state6502.pc;
ss.source_bank = bank6502(state6502.pc);
ss.push_depth = 0;
state6502.sp_unwind_depth = state6502.sp_depth;

push16(state6502.pc - 1);
state6502.pc = ea;

ss.dest_pc = state6502.pc;
ss.dest_bank = bank6502(state6502.pc);
ss.op_type = _stack_op_type::op;
ss.op_type = _stack_op_type::jsr;
ss.pop_type = _stack_pop_type::unknown;
ss.opcode = opcode;
}

Expand Down Expand Up @@ -466,12 +469,38 @@ static void
pha()
{
push8(state6502.a);
auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
auto &ssx = ss.pushed_bytes[ss.push_depth++];
ssx.push_type = _push_op_type::a;
ssx.pull_type = _push_op_type::unknown;
ssx.value = state6502.a;
}

static void
php()
{
push8(state6502.status | FLAG_BREAK);
auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
auto &ssx = ss.pushed_bytes[ss.push_depth++];
ssx.push_type = _push_op_type::status;
ssx.pull_type = _push_op_type::unknown;
ssx.value = state6502.status | FLAG_BREAK;

if (ss.op_type != _stack_op_type::jsr && ss.push_depth == 5) {
ss.push_depth -= 3;

auto &ss2 = stack6502[state6502.sp_depth++];
ss2.source_pc = (static_cast<uint16_t>(ss.pushed_bytes[ss.push_depth].value) << 8) | static_cast<uint16_t>(ss.pushed_bytes[ss.push_depth+1].value);
ss2.source_bank = bank6502(state6502.pc);
ss2.push_depth = 0;
state6502.sp_unwind_depth = state6502.sp_depth;

ss2.dest_pc = state6502.pc;
ss2.dest_bank = bank6502(state6502.pc);
ss2.op_type = _stack_op_type::smart;
ss2.pop_type = _stack_pop_type::unknown;
ss2.opcode = 0;
}
}

static void
Expand All @@ -481,12 +510,22 @@ pla()

zerocalc(state6502.a);
signcalc(state6502.a);

auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
ss.push_depth -= !!ss.push_depth;
auto &ssx = ss.pushed_bytes[ss.push_depth];
ssx.pull_type = _push_op_type::a;
}

static void
plp()
{
state6502.status = pull8() | FLAG_CONSTANT;

auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
ss.push_depth -= !!ss.push_depth;
auto &ssx = ss.pushed_bytes[ss.push_depth];
ssx.pull_type = _push_op_type::status;
}

static void
Expand Down Expand Up @@ -521,18 +560,33 @@ ror()
static void
rti()
{
const uint16_t old_pc = state6502.pc;
state6502.status = pull8();
value = pull16();
state6502.pc = value;
stack6502_underflow |= !state6502.sp_depth;
state6502.sp_depth -= !!state6502.sp_depth;

auto &ss = stack6502[state6502.sp_depth];
ss.pop_type = _stack_pop_type::rti;
ss.pop_pc = old_pc - 1;
ss.pop_bank = bank6502(old_pc);
}

static void
rts()
{
value = pull16();
const uint16_t old_pc = state6502.pc;

value = pull16();
state6502.pc = value + 1;
stack6502_underflow |= !state6502.sp_depth;
state6502.sp_depth -= !!state6502.sp_depth;

auto &ss = stack6502[state6502.sp_depth];
ss.pop_type = _stack_pop_type::rts;
ss.pop_pc = old_pc - 1;
ss.pop_bank = bank6502(old_pc);
}

static void
Expand Down
20 changes: 20 additions & 0 deletions src/cpu/instructions_65c02.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ static void
phx()
{
push8(state6502.x);
auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
auto &ssx = ss.pushed_bytes[ss.push_depth++];
ssx.push_type = _push_op_type::x;
ssx.pull_type = _push_op_type::unknown;
ssx.value = state6502.x;
}

static void
Expand All @@ -93,12 +98,22 @@ plx()

zerocalc(state6502.x);
signcalc(state6502.x);

auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
ss.push_depth -= !!ss.push_depth;
auto &ssx = ss.pushed_bytes[ss.push_depth];
ssx.pull_type = _push_op_type::x;
}

static void
phy()
{
push8(state6502.y);
auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
auto &ssx = ss.pushed_bytes[ss.push_depth++];
ssx.push_type = _push_op_type::y;
ssx.pull_type = _push_op_type::unknown;
ssx.value = state6502.y;
}

static void
Expand All @@ -108,6 +123,11 @@ ply()

zerocalc(state6502.y);
signcalc(state6502.y);

auto &ss = stack6502[(state6502.sp_depth + 255) & 0xff];
ss.push_depth -= !!ss.push_depth;
auto &ssx = ss.pushed_bytes[ss.push_depth];
ssx.pull_type = _push_op_type::y;
}

// *******************************************************************************************
Expand Down
14 changes: 8 additions & 6 deletions src/cpu/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ uint8_t pull8()
void reset6502()
{
vp6502();
state6502.pc = (uint16_t)read6502(0xFFFC) | ((uint16_t)read6502(0xFFFD) << 8);
state6502.sp_depth = 0;
state6502.a = 0;
state6502.x = 0;
state6502.y = 0;
state6502.sp = 0xFD;
state6502.pc = (uint16_t)read6502(0xFFFC) | ((uint16_t)read6502(0xFFFD) << 8);
state6502.sp_depth = 0;
state6502.sp_unwind_depth = 0;
state6502.a = 0;
state6502.x = 0;
state6502.y = 0;
state6502.sp = 0xFD;
state6502.status |= FLAG_CONSTANT | FLAG_BREAK;
stack6502_underflow = 0;
setinterrupt();
cleardecimal();
waiting = 0;
Expand Down
1 change: 1 addition & 0 deletions src/glue.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
extern _state6502 state6502;
extern uint8_t waiting;
extern _smart_stack stack6502[256];
extern uint8_t stack6502_underflow;

extern uint8_t *RAM;
extern uint8_t ROM[ROM_SIZE];
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ void emulator_loop()

uint64_t old_clockticks6502 = clockticks6502;
step6502();
if (debug6502) {
if (debug6502 || stack6502_underflow) {
debugger_process_cpu();
if (debugger_is_paused()) {
continue;
Expand Down
Loading

0 comments on commit bb03daa

Please sign in to comment.