1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Takes a shot at emulation-mode 'exceptions'.

It's just RTI and correct decimal SBC left of the official 6502s now, I think.
This commit is contained in:
Thomas Harte 2020-10-08 17:52:13 -04:00
parent 054e0af071
commit 0418f51ef2
6 changed files with 80 additions and 14 deletions

View File

@ -9,7 +9,6 @@
#import "TestMachine6502.h"
#include <stdint.h>
#include "../../../../Processors/6502/AllRAM/6502AllRAM.hpp"
//#include "../../../../Processors/65816/AllRAM/65816AllRAM.hpp"
#import "TestMachine+ForSubclassEyesOnly.h"
const uint8_t CSTestMachine6502JamOpcode = CPU::MOS6502::JamOpcode;

View File

@ -55,7 +55,9 @@ class KlausDormannTests: XCTestCase {
case 0x36ac, 0x36f6: return "Improper JSR return address on stack"
case 0x36c6: return "Unexpected RESET"
case 0x36d1: return "BRK: unexpected BRK or IRQ"
case 0x36e5: return "BRK flag not set on stack"
case 0x36e5: return "BRK flag not set on stack following BRK"
case 0x36ea: return "BRK did not set the I flag"
case 0x36fd: return "Wrong address put on stack by BRK"
case 0: return "Didn't find tests"

View File

@ -11,6 +11,8 @@
#include <algorithm>
#include <cstring>
#define BE_NOISY
using namespace CPU::MOS6502;
namespace {
@ -28,20 +30,31 @@ template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
timestamp_ += Cycles(1);
if(operation == BusOperation::ReadOpcode) {
// TEMPORARY LOGGING. TODO: remove.
#ifdef BE_NOISY
printf("[%04x] %02x a:%04x x:%04x y:%04x p:%02x s:%02x\n", address, memory_[address],
mos6502_.get_value_of_register(Register::A),
mos6502_.get_value_of_register(Register::X),
mos6502_.get_value_of_register(Register::Y),
mos6502_.get_value_of_register(Register::Flags) & 0xff,
mos6502_.get_value_of_register(Register::StackPointer) & 0xff);
#endif
check_address_for_trap(address);
}
if(isReadOperation(operation)) {
*value = memory_[address];
#ifdef BE_NOISY
if((address&0xff00) == 0x100) {
printf("%04x -> %02x\n", address, *value);
}
#endif
} else {
memory_[address] = *value;
#ifdef BE_NOISY
if((address&0xff00) == 0x100) {
printf("%04x <- %02x\n", address, *value);
}
#endif
}
return Cycles(1);

View File

@ -296,6 +296,49 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
data_address_ = data_bank_ + (instruction_buffer_.value + y()) & 0xffff;
continue;
case OperationPrepareException: {
// Put the proper exception vector into the data address, put the flags and PC
// into the data buffer (possibly also PBR), and skip an instruction if in
// emulation mode.
bool is_brk = false;
if(pending_exceptions_ & (Reset | PowerOn)) {
// TODO: set emulation mode, etc.
pending_exceptions_ &= ~(Reset | PowerOn);
data_address_ = 0xfffc;
} else if(pending_exceptions_ & NMI) {
pending_exceptions_ &= ~NMI;
data_address_ = 0xfffa;
} else if(pending_exceptions_ & IRQ) {
pending_exceptions_ &= ~IRQ;
data_address_ = 0xfffe;
} else {
is_brk = active_instruction_ == instructions;
if(is_brk) {
data_address_ = emulation_flag_ ? 0xfffe : 0xfff6;
} else {
// Implicitly: COP.
data_address_ = 0xfff4;
}
}
data_buffer_.value = (pc_ << 8) | flags_.get();
if(emulation_flag_) {
if(is_brk) data_buffer_.value |= Flag::Break;
data_buffer_.size = 3;
++next_op_;
} else {
data_buffer_.value |= program_bank_ << 24;
data_buffer_.size = 4;
program_bank_ = 0;
assert(false); // TODO: proper flags, still.
}
flags_.inverse_interrupt = 0;
} continue;
//
// Performance.
//
@ -687,7 +730,6 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
// XCE, XBA,
// STP, WAI,
// RTI, RTL,
// BRK,
// TCD, TCS, TDC, TSC
default:
@ -695,8 +737,6 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
}
continue;
// TODO: OperationPrepareException
default:
assert(false);
}

View File

@ -111,7 +111,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
const auto map_entry = installed_patterns.find(key);
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 = BRK;
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].operation = JMPind;
}
void install_fetch_decode_execute() {
@ -579,6 +579,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CyclePush); // PCL
target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull?
target(CycleFetchIncrementData); // AAVL
target(CycleFetchData); // AAVH
@ -677,8 +678,23 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
}
// 22j. Stack; s, BRK/COP.
static void brk_cop(AccessType, bool, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // Signature.
// Covered by stack_exception.
target(OperationPrepareException); // Populates the data buffer; this skips a micro-op if
// in emulation mode.
target(CyclePush); // PBR [skipped in emulation mode]
target(CyclePush); // PCH
target(CyclePush); // PCL
target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull?
target(CycleFetchIncrementData); // AAVL
target(CycleFetchData); // AAVH
target(OperationPerform); // Jumps to the vector address.
}
// 23. Stack Relative; d, s.
static void stack_relative(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
@ -710,9 +726,9 @@ ProcessorStorage::ProcessorStorage() {
// Install the instructions.
#define op(x, y) constructor.install(&ProcessorStorageConstructor::x, y)
/* 0x00 BRK s */ op(stack_exception, BRK);
/* 0x00 BRK s */ op(brk_cop, JMPind);
/* 0x01 ORA (d, x) */ op(direct_indexed_indirect, ORA);
/* 0x02 COP s */ op(stack_exception, BRK);
/* 0x02 COP s */ op(brk_cop, JMPind);
/* 0x03 ORA d, s */ op(stack_relative, ORA);
/* 0x04 TSB d */ op(direct_rmw, TSB);
/* 0x05 ORA d */ op(direct, ORA);

View File

@ -193,10 +193,6 @@ enum Operation: uint8_t {
/// Loads the PC with the contents of the data buffer + 1.
RTS,
/// i.e. jump to vector. TODO: is this really distinct from JMP? I'm assuming so for now,
/// as I assume the PBR is implicitly modified. But then is it just JML? We'll see.
BRK,
};
class ProcessorStorageConstructor;