1
0
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:
Thomas Harte 2020-10-13 21:38:30 -04:00
parent 3e6a2adaaf
commit b22aa5d699
11 changed files with 146 additions and 20 deletions

View File

@ -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 */,

View File

@ -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

View 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)
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -34,7 +34,13 @@ enum Register {
Flags,
A,
X,
Y
Y,
// These exist on the 65816 only.
EmulationFlag,
DataBank,
ProgramBank,
Direct
};
/*

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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,