mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Starts transcribing the addressing examples I have into tests.
Correspondingly extends the exposed register set and test-machine addressing range.
This commit is contained in:
parent
3e6a2adaaf
commit
b22aa5d699
@ -215,6 +215,7 @@
|
||||
4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
|
||||
4B4F47652533EA64004245B8 /* suite-a.prg in Resources */ = {isa = PBXBuildFile; fileRef = 4B4F475E2533EA64004245B8 /* suite-a.prg */; };
|
||||
4B4F477C253530B7004245B8 /* Jeek816Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4F477B253530B7004245B8 /* Jeek816Tests.swift */; };
|
||||
4B4F478A25367EDC004245B8 /* 65816AddressingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4F478925367EDC004245B8 /* 65816AddressingTests.swift */; };
|
||||
4B50AF80242817F40099BBD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */; };
|
||||
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; };
|
||||
4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; };
|
||||
@ -1132,6 +1133,7 @@
|
||||
4B4F2B7024DF99D4000DA6B0 /* CSScanTarget+CppScanTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSScanTarget+CppScanTarget.h"; sourceTree = "<group>"; };
|
||||
4B4F475E2533EA64004245B8 /* suite-a.prg */ = {isa = PBXFileReference; lastKnownFileType = file; path = "suite-a.prg"; sourceTree = "<group>"; };
|
||||
4B4F477B253530B7004245B8 /* Jeek816Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Jeek816Tests.swift; sourceTree = "<group>"; };
|
||||
4B4F478925367EDC004245B8 /* 65816AddressingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 65816AddressingTests.swift; sourceTree = "<group>"; };
|
||||
4B50AF7F242817F40099BBD7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
4B51F70920A521D700AFA2C1 /* Source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Source.hpp; sourceTree = "<group>"; };
|
||||
4B51F70A20A521D700AFA2C1 /* Observer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Observer.hpp; sourceTree = "<group>"; };
|
||||
@ -3464,6 +3466,7 @@
|
||||
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */,
|
||||
4BC751B11D157E61006C31D9 /* 6522Tests.swift */,
|
||||
4B1E85801D176468001EF87D /* 6532Tests.swift */,
|
||||
4B4F478925367EDC004245B8 /* 65816AddressingTests.swift */,
|
||||
4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */,
|
||||
4B049CDC1DA3C82F00322067 /* BCDTest.swift */,
|
||||
4B3BA0C21D318AEB005DD7A7 /* C1540Tests.swift */,
|
||||
@ -5009,6 +5012,7 @@
|
||||
4B778F5723A5F2BB0000D260 /* ZX8081.cpp in Sources */,
|
||||
4B778F2F23A5F0B10000D260 /* ScanTarget.cpp in Sources */,
|
||||
4BE90FFD22D5864800FB464D /* MacintoshVideoTests.mm in Sources */,
|
||||
4B4F478A25367EDC004245B8 /* 65816AddressingTests.swift in Sources */,
|
||||
4B778F0B23A5EC150000D260 /* TapeUEF.cpp in Sources */,
|
||||
4B778F0523A5EBB00000D260 /* ST.cpp in Sources */,
|
||||
4B778F0C23A5EC150000D260 /* TZX.cpp in Sources */,
|
||||
|
@ -17,7 +17,7 @@ class MOS6502InterruptTests: XCTestCase {
|
||||
// create a machine full of NOPs
|
||||
machine = CSTestMachine6502(processor: .processor6502)
|
||||
for c in 0...65535 {
|
||||
machine.setValue(0xea, forAddress: UInt16(c))
|
||||
machine.setValue(0xea, forAddress: UInt32(c))
|
||||
}
|
||||
|
||||
// set the IRQ vector to be 0x1234
|
||||
|
93
OSBindings/Mac/Clock SignalTests/65816AddressingTests.swift
Normal file
93
OSBindings/Mac/Clock SignalTests/65816AddressingTests.swift
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// WDC65816AddressingTests.swift
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 13/10/2020.
|
||||
// Copyright 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
// This exactly transcribes the examples given in http://6502.org/tutorials/65c816opcodes.html#5.9
|
||||
class WDC65816AddressingTests: XCTestCase {
|
||||
|
||||
private func machine16() -> CSTestMachine6502 {
|
||||
let machine = CSTestMachine6502(processor: .processor65816)
|
||||
machine.setValue(0, for: .emulationFlag)
|
||||
machine.setValue(0, for: .flags)
|
||||
return machine
|
||||
}
|
||||
|
||||
func testAbsolute() {
|
||||
let machine = machine16()
|
||||
|
||||
machine.setValue(0x12, for: .dataBank)
|
||||
|
||||
machine.setValue(0xab, forAddress: 0x12ffff)
|
||||
machine.setValue(0xcd, forAddress: 0x130000)
|
||||
|
||||
// LDA $ffff; NOP
|
||||
machine.setData(Data([0xad, 0xff, 0xff, 0xea]), atAddress: 0x200)
|
||||
|
||||
machine.setValue(0x200, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 6)
|
||||
|
||||
XCTAssertEqual(machine.value(for: .A), 0xcdab)
|
||||
}
|
||||
|
||||
func testAbsoluteX() {
|
||||
let machine = machine16()
|
||||
|
||||
machine.setValue(0x12, for: .dataBank)
|
||||
machine.setValue(0x0a, for: .X)
|
||||
|
||||
machine.setValue(0xab, forAddress: 0x130008)
|
||||
machine.setValue(0xcd, forAddress: 0x130009)
|
||||
|
||||
// LDA $fffe, x; NOP
|
||||
machine.setData(Data([0xbd, 0xfe, 0xff, 0xea]), atAddress: 0x200)
|
||||
|
||||
machine.setValue(0x200, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 7)
|
||||
|
||||
XCTAssertEqual(machine.value(for: .A), 0xcdab)
|
||||
}
|
||||
|
||||
func testJMPAbsoluteIndirect() {
|
||||
let machine = machine16()
|
||||
|
||||
machine.setValue(0x12, for: .programBank)
|
||||
machine.setValue(0x0a, for: .X)
|
||||
|
||||
machine.setValue(0x34, forAddress: 0x0000)
|
||||
machine.setValue(0x56, forAddress: 0xffff)
|
||||
|
||||
// JMP ($ffff); NOP
|
||||
machine.setData(Data([0x6c, 0xff, 0xff, 0xea]), atAddress: 0x120200)
|
||||
|
||||
machine.setValue(0x200, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 6)
|
||||
|
||||
XCTAssertEqual(machine.value(for: .programCounter), 0x3456 + 1)
|
||||
XCTAssertEqual(machine.value(for: .programBank), 0x12)
|
||||
}
|
||||
|
||||
func testIndirectAbsoluteX() {
|
||||
let machine = machine16()
|
||||
|
||||
machine.setValue(0x12, for: .programBank)
|
||||
machine.setValue(0x0a, for: .X)
|
||||
machine.setValue(0x56, forAddress: 0x120008)
|
||||
machine.setValue(0x34, forAddress: 0x120009)
|
||||
|
||||
// JMP ($fffe, x); NOP
|
||||
machine.setData(Data([0x7c, 0xfe, 0xff, 0xea]), atAddress: 0x120200)
|
||||
|
||||
machine.setValue(0x200, for: .programCounter)
|
||||
machine.runForNumber(ofCycles: 7)
|
||||
|
||||
XCTAssertEqual(machine.value(for: .programCounter), 0x3456 + 1)
|
||||
XCTAssertEqual(machine.value(for: .programBank), 0x12)
|
||||
}
|
||||
}
|
@ -17,6 +17,10 @@ typedef NS_ENUM(NSInteger, CSTestMachine6502Register) {
|
||||
CSTestMachine6502RegisterA,
|
||||
CSTestMachine6502RegisterX,
|
||||
CSTestMachine6502RegisterY,
|
||||
CSTestMachine6502RegisterEmulationFlag,
|
||||
CSTestMachine6502RegisterDataBank,
|
||||
CSTestMachine6502RegisterProgramBank,
|
||||
CSTestMachine6502RegisterDirect,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSTestMachine6502Processor) {
|
||||
@ -33,11 +37,11 @@ extern const uint8_t CSTestMachine6502JamOpcode;
|
||||
|
||||
- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor;
|
||||
|
||||
- (void)setData:(nonnull NSData *)data atAddress:(uint16_t)startAddress;
|
||||
- (void)setData:(nonnull NSData *)data atAddress:(uint32_t)startAddress;
|
||||
- (void)runForNumberOfCycles:(int)cycles;
|
||||
|
||||
- (void)setValue:(uint8_t)value forAddress:(uint16_t)address;
|
||||
- (uint8_t)valueForAddress:(uint16_t)address;
|
||||
- (void)setValue:(uint8_t)value forAddress:(uint32_t)address;
|
||||
- (uint8_t)valueForAddress:(uint32_t)address;
|
||||
- (void)setValue:(uint16_t)value forRegister:(CSTestMachine6502Register)reg;
|
||||
- (uint16_t)valueForRegister:(CSTestMachine6502Register)reg;
|
||||
|
||||
|
@ -24,6 +24,10 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg)
|
||||
case CSTestMachine6502RegisterX: return CPU::MOS6502::Register::X;
|
||||
case CSTestMachine6502RegisterY: return CPU::MOS6502::Register::Y;
|
||||
case CSTestMachine6502RegisterStackPointer: return CPU::MOS6502::Register::StackPointer;
|
||||
case CSTestMachine6502RegisterEmulationFlag: return CPU::MOS6502::Register::EmulationFlag;
|
||||
case CSTestMachine6502RegisterDataBank: return CPU::MOS6502::Register::DataBank;
|
||||
case CSTestMachine6502RegisterProgramBank: return CPU::MOS6502::Register::ProgramBank;
|
||||
case CSTestMachine6502RegisterDirect: return CPU::MOS6502::Register::Direct;
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,13 +64,13 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg)
|
||||
|
||||
#pragma mark - Accessors
|
||||
|
||||
- (uint8_t)valueForAddress:(uint16_t)address {
|
||||
- (uint8_t)valueForAddress:(uint32_t)address {
|
||||
uint8_t value;
|
||||
_processor->get_data_at_address(address, 1, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
- (void)setValue:(uint8_t)value forAddress:(uint16_t)address {
|
||||
- (void)setValue:(uint8_t)value forAddress:(uint32_t)address {
|
||||
_processor->set_data_at_address(address, 1, &value);
|
||||
}
|
||||
|
||||
@ -78,7 +82,7 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg)
|
||||
return _processor->get_value_of_register(registerForRegister(reg));
|
||||
}
|
||||
|
||||
- (void)setData:(NSData *)data atAddress:(uint16_t)startAddress {
|
||||
- (void)setData:(NSData *)data atAddress:(uint32_t)startAddress {
|
||||
_processor->set_data_at_address(startAddress, data.length, (const uint8_t *)data.bytes);
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
|
||||
output = ""
|
||||
|
||||
let dataPointer = (testData as NSData).bytes.bindMemory(to: UInt8.self, capacity: testData.count)
|
||||
let loadAddress = UInt16(dataPointer[0]) | (UInt16(dataPointer[1]) << 8)
|
||||
let loadAddress = UInt32(dataPointer[0]) | (UInt32(dataPointer[1]) << 8)
|
||||
let contents = testData.subdata(in: 2 ..< testData.count)
|
||||
|
||||
machine.setData(contents, atAddress: loadAddress)
|
||||
|
@ -34,7 +34,13 @@ enum Register {
|
||||
Flags,
|
||||
A,
|
||||
X,
|
||||
Y
|
||||
Y,
|
||||
|
||||
// These exist on the 65816 only.
|
||||
EmulationFlag,
|
||||
DataBank,
|
||||
ProgramBank,
|
||||
Direct
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -19,18 +19,26 @@ uint16_t ProcessorBase::get_value_of_register(Register r) const {
|
||||
case Register::A: return a_.full;
|
||||
case Register::X: return x_.full;
|
||||
case Register::Y: return y_.full;
|
||||
case Register::EmulationFlag: return emulation_flag_;
|
||||
case Register::DataBank: return data_bank_ >> 16;
|
||||
case Register::ProgramBank: return program_bank_ >> 16;
|
||||
case Register::Direct: return direct_;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessorBase::set_value_of_register(Register r, uint16_t value) {
|
||||
switch (r) {
|
||||
case Register::ProgramCounter: pc_ = value; break;
|
||||
case Register::StackPointer: s_.full = value; break;
|
||||
case Register::Flags: set_flags(uint8_t(value)); break;
|
||||
case Register::A: a_.full = value; break;
|
||||
case Register::X: x_.full = value; break;
|
||||
case Register::Y: y_.full = value; break;
|
||||
case Register::ProgramCounter: pc_ = value; break;
|
||||
case Register::StackPointer: s_.full = value; break;
|
||||
case Register::Flags: set_flags(uint8_t(value)); break;
|
||||
case Register::A: a_.full = value; break;
|
||||
case Register::X: x_.full = value; break;
|
||||
case Register::Y: y_.full = value; break;
|
||||
case Register::EmulationFlag: set_emulation_mode(value); break;
|
||||
case Register::DataBank: data_bank_ = uint32_t(value) << 16; break;
|
||||
case Register::ProgramBank: program_bank_ = uint32_t(value) << 16; break;
|
||||
case Register::Direct: direct_ = value; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -232,13 +232,19 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
||||
data_address_increment_mask_ = 0xff'ff'ff;
|
||||
continue;
|
||||
|
||||
case OperationConstructAbsolute16:
|
||||
data_address_ = instruction_buffer_.value;
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
continue;
|
||||
|
||||
case OperationConstructAbsoluteLong:
|
||||
data_address_ = instruction_buffer_.value;
|
||||
data_address_increment_mask_ = 0xff'ff'ff;
|
||||
continue;
|
||||
|
||||
// Used for JMP and JSR (absolute, x).
|
||||
case OperationConstructAbsoluteIndexedIndirect:
|
||||
data_address_ = (instruction_buffer_.value + x()) & 0xffff;
|
||||
data_address_ = program_bank_ + ((instruction_buffer_.value + x()) & 0xffff);
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
continue;
|
||||
|
||||
|
@ -237,8 +237,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CycleFetchIncrementPC); // New AAL.
|
||||
target(CycleFetchPC); // New AAH.
|
||||
|
||||
target(OperationConstructAbsolute); // Calculate data address.
|
||||
// TODO: needs to apply a 16-bit limit here:
|
||||
target(OperationConstructAbsolute16); // Calculate data address.
|
||||
target(CycleFetchIncrementData); // New PCL
|
||||
target(CycleFetchIncrementData); // New PCH
|
||||
target(CycleFetchData); // New PBR
|
||||
@ -251,8 +250,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CycleFetchIncrementPC); // New AAL.
|
||||
target(CycleFetchPC); // New AAH.
|
||||
|
||||
target(OperationConstructAbsolute); // Calculate data address.
|
||||
// TODO: needs to apply a 16-bit limit here:
|
||||
target(OperationConstructAbsolute16); // Calculate data address.
|
||||
target(CycleFetchIncrementData); // New PCL
|
||||
target(CycleFetchData); // New PCH
|
||||
|
||||
|
@ -57,6 +57,9 @@ enum MicroOp: uint8_t {
|
||||
/// using the data register as a high byte.
|
||||
OperationConstructAbsolute,
|
||||
|
||||
/// Constructs a strictly 16-bit address from the instruction buffer.
|
||||
OperationConstructAbsolute16,
|
||||
|
||||
/// Sets the data address by copying the entire instruction buffer.
|
||||
OperationConstructAbsoluteLong,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user