1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +00:00

Ensures that reset doesn't push to the stack.

This commit is contained in:
Thomas Harte 2020-10-28 21:23:35 -04:00
parent 1e4679ae14
commit 1df2ce513a
3 changed files with 36 additions and 7 deletions

View File

@ -410,6 +410,13 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
pending_exceptions_ &= ~(Reset | PowerOn);
data_address_ = 0xfffc;
set_reset_state();
// Also switch tracks to the reset program, and don't load up the
// data buffer. set_reset_state() will already have fixed the
// interrupt and decimal flags.
active_instruction_ = &instructions[size_t(OperationSlot::ResetTail)];
next_op_ = &micro_ops_[active_instruction_->program_offsets[0]];
continue;
} else if(pending_exceptions_ & NMI) {
pending_exceptions_ &= ~NMI;
data_address_ = registers_.emulation_flag ? 0xfffa : 0xffea;

View File

@ -70,11 +70,16 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
++opcode;
}
void set_exception_generator(Generator generator) {
void set_exception_generator(Generator generator, Generator reset_tail_generator) {
const auto map_entry = install(generator);
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offsets[0] =
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offsets[1] = uint16_t(map_entry->second.first);
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].operation = JMPind;
const auto reset_tail_entry = install(reset_tail_generator);
storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].program_offsets[0] =
storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].program_offsets[1] = uint16_t(reset_tail_entry->second.first);
storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].operation = JMPind;
}
void install_fetch_decode_execute() {
@ -597,8 +602,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CycleFetchPCThrowaway); // IO.
target(CycleFetchPCThrowaway); // IO.
target(OperationPrepareException); // Populates the data buffer; this skips a micro-op if
// in emulation mode.
target(OperationPrepareException); // Populates the data buffer; if the exception is a
// reset then switches to the reset tail program.
// Otherwise skips a micro-op if in emulation mode.
target(CyclePush); // PBR [skipped in emulation mode].
target(CyclePush); // PCH.
@ -611,6 +617,20 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(OperationPerform); // Jumps to the vector address.
}
static void reset_tail(AccessType, bool, const std::function<void(MicroOp)> &target) {
// The reset program still walks through three stack accesses as if it were doing
// the usual exception stack activity, but forces them to reads that don't modify
// the stack pointer. Here they are:
target(CycleAccessStack); // PCH.
target(CycleAccessStack); // PCL.
target(CycleAccessStack); // P.
target(CycleFetchIncrementVector); // AAVL.
target(CycleFetchVector); // AAVH.
target(OperationPerform); // Jumps to the vector address.
}
// 22b. Stack; s, PLx.
static void stack_pull(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchPCThrowaway); // IO.
@ -1027,7 +1047,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0xff SBC al, x */ op(absolute_long_x, SBC);
#undef op
constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception);
constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception, &ProcessorStorageConstructor::reset_tail);
constructor.install_fetch_decode_execute();
// Find any OperationMoveToNextProgram.

View File

@ -241,14 +241,16 @@ struct ProcessorStorage {
/// So the program to perform is that at @c program_offsets[mx_flags[size_field]]
uint8_t size_field = 0;
};
Instruction instructions[256 + 2]; // Arranged as:
Instruction instructions[256 + 3]; // Arranged as:
// 256 entries: instructions;
// the entry for 'exceptions' (i.e. reset, irq, nmi); and
// the entry for 'exceptions' (i.e. reset, irq, nmi);
// a duplicate entry for the final part of exceptions if the selected exception is a reset; and
// the entry for fetch-decode-execute.
enum class OperationSlot {
Exception = 256,
FetchDecodeExecute
ResetTail,
FetchDecodeExecute,
};
// A helper for testing.