mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Eliminates the 6502's specialised jam handler in favour of the generic trap handler, and simplifies the lookup costs of that as it's otherwise doubling execution costs.
This commit is contained in:
parent
fd6623b5a5
commit
b642d9f712
@ -9,7 +9,7 @@
|
||||
import XCTest
|
||||
import Foundation
|
||||
|
||||
class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
|
||||
class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
|
||||
|
||||
func testWolfgangLorenzStart() {
|
||||
self.runWolfgangLorenzTest(" start")
|
||||
@ -201,7 +201,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
|
||||
if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
|
||||
|
||||
machine = CSTestMachine6502()
|
||||
machine.jamHandler = self
|
||||
machine.trapHandler = self
|
||||
// machine.logActivity = true
|
||||
output = ""
|
||||
|
||||
@ -225,11 +225,18 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
|
||||
] as [UInt8]), count: 19)
|
||||
machine.setData( irqHandler, atAddress: 0xff48)
|
||||
|
||||
machine.setValue(CSTestMachine6502JamOpcode, forAddress:0xffd2) // print character
|
||||
machine.addTrapAddress(0xffd2) // print character
|
||||
machine.addTrapAddress(0xffe4) // scan keyboard
|
||||
|
||||
machine.addTrapAddress(0x8000) // exit
|
||||
machine.addTrapAddress(0xa474) // exit
|
||||
|
||||
machine.setValue(0x60, forAddress:0xffd2) // 0x60 is RTS
|
||||
machine.setValue(0x60, forAddress:0xffe4)
|
||||
machine.setValue(0x60, forAddress:0x8000)
|
||||
machine.setValue(0x60, forAddress:0xa474)
|
||||
|
||||
machine.setValue(CSTestMachine6502JamOpcode, forAddress:0xe16f) // load
|
||||
machine.setValue(CSTestMachine6502JamOpcode, forAddress:0xffe4) // scan keyboard
|
||||
machine.setValue(CSTestMachine6502JamOpcode, forAddress:0x8000) // exit
|
||||
machine.setValue(CSTestMachine6502JamOpcode, forAddress:0xa474) // exit
|
||||
|
||||
machine.setValue(0x0801, for: CSTestMachine6502Register.programCounter)
|
||||
machine.setValue(0xfd, for: CSTestMachine6502Register.stackPointer)
|
||||
@ -296,19 +303,17 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
|
||||
return result
|
||||
}
|
||||
|
||||
func testMachine(_ machine: CSTestMachine6502!, didJamAtAddress address: UInt16) {
|
||||
func testMachine(_ testMachine: CSTestMachine, didTrapAtAddress address: UInt16) {
|
||||
let testMachine6502 = testMachine as! CSTestMachine6502
|
||||
switch address {
|
||||
case 0xffd2:
|
||||
machine.setValue(0x00, forAddress: 0x030c)
|
||||
testMachine6502.setValue(0x00, forAddress: 0x030c)
|
||||
|
||||
let character = machine.value(for: CSTestMachine6502Register.A)
|
||||
let character = testMachine6502.value(for: CSTestMachine6502Register.A)
|
||||
output.append(Character(UnicodeScalar(character)!))
|
||||
|
||||
machine.returnFromSubroutine()
|
||||
|
||||
case 0xffe4:
|
||||
machine.setValue(0x3, for:CSTestMachine6502Register.A)
|
||||
machine.returnFromSubroutine()
|
||||
testMachine6502.setValue(0x3, for:CSTestMachine6502Register.A)
|
||||
|
||||
case 0x8000, 0xa474:
|
||||
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: self.petsciiToString(output), userInfo: nil).raise()
|
||||
@ -316,9 +321,6 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
|
||||
case 0x0000:
|
||||
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: "Execution hit 0000", userInfo: nil).raise()
|
||||
|
||||
case 0xe16f: // load next (which we consider to be success)
|
||||
break;
|
||||
|
||||
default:
|
||||
let hexAddress = String(format:"%04x", address)
|
||||
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()
|
||||
|
@ -78,13 +78,6 @@ extern const uint8_t JamOpcode;
|
||||
jammed state.
|
||||
*/
|
||||
template <class T> class Processor {
|
||||
public:
|
||||
|
||||
class JamHandler {
|
||||
public:
|
||||
virtual void processor_did_jam(Processor *processor, uint16_t address) = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
@ -426,8 +419,6 @@ template <class T> class Processor {
|
||||
}
|
||||
|
||||
bool is_jammed_;
|
||||
JamHandler *jam_handler_;
|
||||
|
||||
int cycles_left_to_run_;
|
||||
|
||||
enum InterruptRequestFlags: uint8_t {
|
||||
@ -511,7 +502,6 @@ template <class T> class Processor {
|
||||
protected:
|
||||
Processor() :
|
||||
is_jammed_(false),
|
||||
jam_handler_(nullptr),
|
||||
cycles_left_to_run_(0),
|
||||
ready_line_is_enabled_(false),
|
||||
ready_is_active_(false),
|
||||
@ -704,11 +694,6 @@ template <class T> class Processor {
|
||||
is_jammed_ = true;
|
||||
static const MicroOp jam[] = JAM;
|
||||
scheduled_program_counter_ = jam;
|
||||
|
||||
if(jam_handler_) {
|
||||
jam_handler_->processor_did_jam(this, pc_.full - 1);
|
||||
checkSchedule(is_jammed_ = false;);
|
||||
}
|
||||
} continue;
|
||||
|
||||
#pragma mark - Bitwise
|
||||
@ -1230,15 +1215,6 @@ template <class T> class Processor {
|
||||
inline bool is_jammed() {
|
||||
return is_jammed_;
|
||||
}
|
||||
|
||||
/*!
|
||||
Installs a jam handler. Jam handlers are notified if a running 6502 jams.
|
||||
|
||||
@param handler The class instance that will be this 6502's jam handler from now on.
|
||||
*/
|
||||
inline void set_jam_handler(JamHandler *handler) {
|
||||
jam_handler_ = handler;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ class AllRAMProcessor:
|
||||
|
||||
public:
|
||||
static AllRAMProcessor *Processor();
|
||||
virtual ~AllRAMProcessor() {}
|
||||
|
||||
virtual void run_for_cycles(int number_of_cycles) = 0;
|
||||
virtual bool is_jammed() = 0;
|
||||
|
@ -12,6 +12,7 @@ using namespace CPU;
|
||||
|
||||
AllRAMProcessor::AllRAMProcessor(size_t memory_size) :
|
||||
memory_(memory_size),
|
||||
traps_(memory_size, false),
|
||||
timestamp_(0) {}
|
||||
|
||||
void AllRAMProcessor::set_data_at_address(uint16_t startAddress, size_t length, const uint8_t *data) {
|
||||
@ -33,5 +34,5 @@ void AllRAMProcessor::set_trap_handler(TrapHandler *trap_handler) {
|
||||
}
|
||||
|
||||
void AllRAMProcessor::add_trap_address(uint16_t address) {
|
||||
trap_addresses_.insert(address);
|
||||
traps_[address] = true;
|
||||
}
|
||||
|
@ -34,14 +34,14 @@ class AllRAMProcessor {
|
||||
uint32_t timestamp_;
|
||||
|
||||
inline void check_address_for_trap(uint16_t address) {
|
||||
if(trap_addresses_.find(address) != trap_addresses_.end()) {
|
||||
if(traps_[address]) {
|
||||
trap_handler_->processor_did_trap(*this, address);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<uint16_t> trap_addresses_;
|
||||
TrapHandler *trap_handler_;
|
||||
std::vector<bool> traps_;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user