1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-07 23:25:00 +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:
Thomas Harte
2017-06-03 21:54:42 -04:00
parent fd6623b5a5
commit b642d9f712
5 changed files with 23 additions and 43 deletions

View File

@@ -9,7 +9,7 @@
import XCTest import XCTest
import Foundation import Foundation
class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler { class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
func testWolfgangLorenzStart() { func testWolfgangLorenzStart() {
self.runWolfgangLorenzTest(" start") self.runWolfgangLorenzTest(" start")
@@ -201,7 +201,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) { if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
machine = CSTestMachine6502() machine = CSTestMachine6502()
machine.jamHandler = self machine.trapHandler = self
// machine.logActivity = true // machine.logActivity = true
output = "" output = ""
@@ -225,11 +225,18 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
] as [UInt8]), count: 19) ] as [UInt8]), count: 19)
machine.setData( irqHandler, atAddress: 0xff48) 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: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(0x0801, for: CSTestMachine6502Register.programCounter)
machine.setValue(0xfd, for: CSTestMachine6502Register.stackPointer) machine.setValue(0xfd, for: CSTestMachine6502Register.stackPointer)
@@ -296,19 +303,17 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
return result return result
} }
func testMachine(_ machine: CSTestMachine6502!, didJamAtAddress address: UInt16) { func testMachine(_ testMachine: CSTestMachine, didTrapAtAddress address: UInt16) {
let testMachine6502 = testMachine as! CSTestMachine6502
switch address { switch address {
case 0xffd2: 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)!)) output.append(Character(UnicodeScalar(character)!))
machine.returnFromSubroutine()
case 0xffe4: case 0xffe4:
machine.setValue(0x3, for:CSTestMachine6502Register.A) testMachine6502.setValue(0x3, for:CSTestMachine6502Register.A)
machine.returnFromSubroutine()
case 0x8000, 0xa474: case 0x8000, 0xa474:
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: self.petsciiToString(output), userInfo: nil).raise() NSException(name: NSExceptionName(rawValue: "Failed test"), reason: self.petsciiToString(output), userInfo: nil).raise()
@@ -316,9 +321,6 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachine6502JamHandler {
case 0x0000: case 0x0000:
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: "Execution hit 0000", userInfo: nil).raise() 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: default:
let hexAddress = String(format:"%04x", address) let hexAddress = String(format:"%04x", address)
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise() NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()

View File

@@ -78,13 +78,6 @@ extern const uint8_t JamOpcode;
jammed state. jammed state.
*/ */
template <class T> class Processor { template <class T> class Processor {
public:
class JamHandler {
public:
virtual void processor_did_jam(Processor *processor, uint16_t address) = 0;
};
private: private:
/* /*
@@ -426,8 +419,6 @@ template <class T> class Processor {
} }
bool is_jammed_; bool is_jammed_;
JamHandler *jam_handler_;
int cycles_left_to_run_; int cycles_left_to_run_;
enum InterruptRequestFlags: uint8_t { enum InterruptRequestFlags: uint8_t {
@@ -511,7 +502,6 @@ template <class T> class Processor {
protected: protected:
Processor() : Processor() :
is_jammed_(false), is_jammed_(false),
jam_handler_(nullptr),
cycles_left_to_run_(0), cycles_left_to_run_(0),
ready_line_is_enabled_(false), ready_line_is_enabled_(false),
ready_is_active_(false), ready_is_active_(false),
@@ -704,11 +694,6 @@ template <class T> class Processor {
is_jammed_ = true; is_jammed_ = true;
static const MicroOp jam[] = JAM; static const MicroOp jam[] = JAM;
scheduled_program_counter_ = jam; scheduled_program_counter_ = jam;
if(jam_handler_) {
jam_handler_->processor_did_jam(this, pc_.full - 1);
checkSchedule(is_jammed_ = false;);
}
} continue; } continue;
#pragma mark - Bitwise #pragma mark - Bitwise
@@ -1230,15 +1215,6 @@ template <class T> class Processor {
inline bool is_jammed() { inline bool is_jammed() {
return 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;
}
}; };
} }

View File

@@ -20,6 +20,7 @@ class AllRAMProcessor:
public: public:
static AllRAMProcessor *Processor(); static AllRAMProcessor *Processor();
virtual ~AllRAMProcessor() {}
virtual void run_for_cycles(int number_of_cycles) = 0; virtual void run_for_cycles(int number_of_cycles) = 0;
virtual bool is_jammed() = 0; virtual bool is_jammed() = 0;

View File

@@ -12,6 +12,7 @@ using namespace CPU;
AllRAMProcessor::AllRAMProcessor(size_t memory_size) : AllRAMProcessor::AllRAMProcessor(size_t memory_size) :
memory_(memory_size), memory_(memory_size),
traps_(memory_size, false),
timestamp_(0) {} timestamp_(0) {}
void AllRAMProcessor::set_data_at_address(uint16_t startAddress, size_t length, const uint8_t *data) { 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) { void AllRAMProcessor::add_trap_address(uint16_t address) {
trap_addresses_.insert(address); traps_[address] = true;
} }

View File

@@ -34,14 +34,14 @@ class AllRAMProcessor {
uint32_t timestamp_; uint32_t timestamp_;
inline void check_address_for_trap(uint16_t address) { 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); trap_handler_->processor_did_trap(*this, address);
} }
} }
private: private:
std::set<uint16_t> trap_addresses_;
TrapHandler *trap_handler_; TrapHandler *trap_handler_;
std::vector<bool> traps_;
}; };
} }