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:
parent
054e0af071
commit
0418f51ef2
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user