1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 21:30:14 +00:00

I'm not yet sure this is the best approach, but starts trying to make use of Lorenz's 6526 tests.

This commit is contained in:
Thomas Harte 2021-07-30 21:21:16 -04:00
parent 5c1ac05170
commit f576baf214
5 changed files with 78 additions and 13 deletions

View File

@ -35,6 +35,7 @@ extern const uint8_t CSTestMachine6502JamOpcode;
- (nonnull instancetype)init NS_UNAVAILABLE;
- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor hasCIAs:(BOOL)hasCIAs;
- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor;
- (void)setData:(nonnull NSData *)data atAddress:(uint32_t)startAddress;

View File

@ -39,25 +39,29 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg)
#pragma mark - Lifecycle
- (instancetype)initWithProcessor:(CSTestMachine6502Processor)processor {
- (instancetype)initWithProcessor:(CSTestMachine6502Processor)processor hasCIAs:(BOOL)hasCIAs {
self = [super init];
if(self) {
switch(processor) {
case CSTestMachine6502Processor6502:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::T6502);
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::T6502, hasCIAs);
break;
case CSTestMachine6502Processor65C02:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65C02);
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65C02, hasCIAs);
break;
case CSTestMachine6502Processor65816:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65816);
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65816, hasCIAs);
}
}
return self;
}
- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor {
return [self initWithProcessor:processor hasCIAs:NO];
}
- (void)dealloc {
delete _processor;
}

View File

@ -226,6 +226,13 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
/* The NOP tests also don't apply; the 65816 has only one, well-defined NOP. */
// MARK: - CIA Tests
func testCIA1TA() {
runTest("cia1ta", suffixes: [""], processor: .processor6502)
}
// MARK: - Collections
func testTransfers(processor: CSTestMachine6502Processor) {
@ -284,10 +291,13 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
fileprivate func runTest(_ name: String, processor: CSTestMachine6502Processor) {
var machine: CSTestMachine6502!
if let filename = Bundle(for: type(of: self)).path(forResource: name, ofType: nil) {
if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
let bundle = Bundle(for: type(of: self))
let mainBundle = Bundle.main
if let testFilename = bundle.url(forResource: name, withExtension: nil),
let kernelFilename = mainBundle.url(forResource: "kernal.901227-02", withExtension: "bin", subdirectory: "ROMImages/Commodore64") {
if let testData = try? Data(contentsOf: testFilename), let kernelData = try? Data(contentsOf: kernelFilename) {
machine = CSTestMachine6502(processor: processor)
machine = CSTestMachine6502(processor: processor, hasCIAs: true)
machine.trapHandler = self
output = ""
@ -296,9 +306,18 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
let contents = testData.subdata(in: 2 ..< testData.count)
machine.setData(contents, atAddress: loadAddress)
machine.setData(kernelData, atAddress: 0xe000)
// Cf. http://www.softwolves.com/arkiv/cbm-hackers/7/7114.html for the steps being taken here.
// Signal in-border, set up NMI and IRQ vectors as defaults.
machine.setValue(0xff, forAddress: 0xd011)
machine.setValue(0x66, forAddress: 0x0316)
machine.setValue(0xfe, forAddress: 0x0317)
machine.setValue(0x31, forAddress: 0x0314)
machine.setValue(0xea, forAddress: 0x0315)
// Initialise memory locations as instructed.
machine.setValue(0x00, forAddress: 0x0002)
machine.setValue(0x00, forAddress: 0xa002)
@ -345,7 +364,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
}
if machine == nil {
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Couldn't load file \(name)", userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Couldn't load kernel, or file \(name)", userInfo: nil).raise()
}
while machine.value(for: .lastOperationAddress) != 0xe16f && !machine.isJammed {

View File

@ -11,6 +11,8 @@
#include <algorithm>
#include <cstring>
#include "../../../Components/6526/6526.hpp"
//#define BE_NOISY
using namespace CPU::MOS6502;
@ -19,17 +21,24 @@ namespace {
using Type = CPU::MOS6502Esque::Type;
template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
template <Type type, bool has_cias> class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
public:
ConcreteAllRAMProcessor(size_t memory_size) :
AllRAMProcessor(memory_size),
mos6502_(*this) {
mos6502_(*this),
cia1_(cia1_handler_),
cia2_(cia2_handler_) {
mos6502_.set_power_on(false);
}
inline Cycles perform_bus_operation(BusOperation operation, uint32_t address, uint8_t *value) {
timestamp_ += Cycles(1);
if constexpr (has_cias) {
cia1_.run_for(HalfCycles(2));
cia2_.run_for(HalfCycles(2));
}
if(isAccessOperation(operation)) {
if(operation == BusOperation::ReadOpcode) {
#ifdef BE_NOISY
@ -46,6 +55,16 @@ template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
if(isReadOperation(operation)) {
*value = memory_[address];
if constexpr (has_cias) {
if((address & 0xff00) == 0xdc00) {
*value = cia1_.read(address);
} else if((address & 0xff00) == 0xdd00) {
*value = cia2_.read(address);
}
}
#ifdef BE_NOISY
// if((address&0xff00) == 0x100) {
printf("%04x -> %02x\n", address, *value);
@ -53,6 +72,14 @@ template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
#endif
} else {
memory_[address] = *value;
if constexpr (has_cias) {
if((address & 0xff00) == 0xdc00) {
cia1_.write(address, *value);
} else if((address & 0xff00) == 0xdd00) {
cia2_.write(address, *value);
}
}
#ifdef BE_NOISY
// if((address&0xff00) == 0x100) {
printf("%04x <- %02x\n", address, *value);
@ -61,6 +88,9 @@ template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
}
}
mos6502_.set_irq_line(cia1_.get_interrupt_line());
mos6502_.set_nmi_line(cia2_.get_interrupt_line());
return Cycles(1);
}
@ -98,12 +128,21 @@ template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
private:
CPU::MOS6502Esque::Processor<type, ConcreteAllRAMProcessor, false> mos6502_;
int instructions_ = 0;
class PortHandler: public MOS::MOS6526::PortHandler {};
PortHandler cia1_handler_, cia2_handler_;
MOS::MOS6526::MOS6526<PortHandler, MOS::MOS6526::Personality::P6526> cia1_, cia2_;
};
}
AllRAMProcessor *AllRAMProcessor::Processor(Type type) {
#define Bind(p) case p: return new ConcreteAllRAMProcessor<p>(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024);
AllRAMProcessor *AllRAMProcessor::Processor(Type type, bool has_cias) {
#define Bind(p) \
case p: \
if(has_cias) return new ConcreteAllRAMProcessor<p, true>(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \
else return new ConcreteAllRAMProcessor<p, false>(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \
switch(type) {
default:
Bind(Type::T6502)

View File

@ -18,7 +18,7 @@ namespace MOS6502 {
class AllRAMProcessor:
public ::CPU::AllRAMProcessor {
public:
static AllRAMProcessor *Processor(CPU::MOS6502Esque::Type type);
static AllRAMProcessor *Processor(CPU::MOS6502Esque::Type type, bool has_cias = false);
virtual ~AllRAMProcessor() {}
virtual void run_for(const Cycles cycles) = 0;
@ -29,6 +29,8 @@ class AllRAMProcessor:
virtual uint16_t get_value_of_register(Register r) = 0;
virtual void set_value_of_register(Register r, uint16_t value) = 0;
protected:
AllRAMProcessor(size_t memory_size) : ::CPU::AllRAMProcessor(memory_size) {}
};