mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-24 12:30:17 +00:00
Added a couple of timing tests, both of which seem to pass for now.
This commit is contained in:
parent
e8f70398c1
commit
503d684af0
@ -56,6 +56,5 @@ class KlausDormannTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,9 @@ typedef NS_ENUM(NSInteger, CSTestMachineRegister) {
|
|||||||
CSTestMachineRegisterProgramCounter,
|
CSTestMachineRegisterProgramCounter,
|
||||||
CSTestMachineRegisterStackPointer,
|
CSTestMachineRegisterStackPointer,
|
||||||
CSTestMachineRegisterFlags,
|
CSTestMachineRegisterFlags,
|
||||||
CSTestMachineRegisterA
|
CSTestMachineRegisterA,
|
||||||
|
CSTestMachineRegisterX,
|
||||||
|
CSTestMachineRegisterY,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const uint8_t CSTestMachineJamOpcode;
|
extern const uint8_t CSTestMachineJamOpcode;
|
||||||
|
@ -51,6 +51,8 @@ class MachineJamHandler: public CPU6502::AllRAMProcessor::JamHandler {
|
|||||||
case CSTestMachineRegisterLastOperationAddress: return CPU6502::Register::LastOperationAddress;
|
case CSTestMachineRegisterLastOperationAddress: return CPU6502::Register::LastOperationAddress;
|
||||||
case CSTestMachineRegisterFlags: return CPU6502::Register::Flags;
|
case CSTestMachineRegisterFlags: return CPU6502::Register::Flags;
|
||||||
case CSTestMachineRegisterA: return CPU6502::Register::A;
|
case CSTestMachineRegisterA: return CPU6502::Register::A;
|
||||||
|
case CSTestMachineRegisterX: return CPU6502::Register::X;
|
||||||
|
case CSTestMachineRegisterY: return CPU6502::Register::Y;
|
||||||
case CSTestMachineRegisterStackPointer: return CPU6502::Register::S;
|
case CSTestMachineRegisterStackPointer: return CPU6502::Register::S;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,50 @@ class TimingTests: XCTestCase, CSTestMachineJamHandler {
|
|||||||
self.runTest(code, expectedRunLength: 2)
|
self.runTest(code, expectedRunLength: 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testLDA() {
|
||||||
|
let code: [UInt8] = [
|
||||||
|
0xa9, 0x00, // [2] LDA #$00
|
||||||
|
0xa5, 0x00, // [3] LDA $00
|
||||||
|
0xb5, 0x00, // [4] LDA $00,X
|
||||||
|
0xad, 0x00, 0x00, // [4] LDA $0000
|
||||||
|
0xbd, 0x00, 0x00, // [4] LDA $0000, x (no wrap)
|
||||||
|
0xbd, 0x02, 0x00, // [5] LDA $0002, x (wrap)
|
||||||
|
0xb9, 0x00, 0x00, // [4] LDA $0000, y (no wrap)
|
||||||
|
0xb9, 0x10, 0x00, // [5] LDA $0010, y (wrap)
|
||||||
|
0xa1, 0x44, // [6] LDA ($44, x)
|
||||||
|
0xb1, 0x00, // [5] LDA ($00), y (no wrap)
|
||||||
|
0xb1, 0x02, // [6] LDA ($01), y (wrap)
|
||||||
|
CSTestMachineJamOpcode]
|
||||||
|
self.runTest(code, expectedRunLength: 48)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBCS() {
|
||||||
|
let code: [UInt8] = [
|
||||||
|
0x18, // [2] CLC
|
||||||
|
0xb0, 0xff, // [2] BCS -1 (not taken)
|
||||||
|
0x90, 0x7f, // [3] BCC +7f (taken)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x90, 0x00, // [3] BCC 0 (taken)
|
||||||
|
0x90, 0x7f, // [4] BCC +6f (taken, page wrap)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
CSTestMachineJamOpcode]
|
||||||
|
self.runTest(code, expectedRunLength: 14)
|
||||||
|
}
|
||||||
|
|
||||||
func runTest(code: [UInt8], expectedRunLength: UInt32) {
|
func runTest(code: [UInt8], expectedRunLength: UInt32) {
|
||||||
let machine = CSTestMachine()
|
let machine = CSTestMachine()
|
||||||
|
|
||||||
@ -25,7 +69,13 @@ class TimingTests: XCTestCase, CSTestMachineJamHandler {
|
|||||||
|
|
||||||
let immediateCode = NSData(bytes: code, length: code.count)
|
let immediateCode = NSData(bytes: code, length: code.count)
|
||||||
machine.setData(immediateCode, atAddress: 0x200)
|
machine.setData(immediateCode, atAddress: 0x200)
|
||||||
|
machine.setValue(0x00, forAddress: 0x0000)
|
||||||
|
machine.setValue(0x00, forAddress: 0x0001)
|
||||||
|
machine.setValue(0xff, forAddress: 0x0002)
|
||||||
|
machine.setValue(0x00, forAddress: 0x0003)
|
||||||
machine.setValue(0x200, forRegister: CSTestMachineRegister.ProgramCounter)
|
machine.setValue(0x200, forRegister: CSTestMachineRegister.ProgramCounter)
|
||||||
|
machine.setValue(0xff, forRegister: CSTestMachineRegister.X)
|
||||||
|
machine.setValue(0xfe, forRegister: CSTestMachineRegister.Y)
|
||||||
|
|
||||||
self.endTime = 0
|
self.endTime = 0
|
||||||
while self.endTime == 0 {
|
while self.endTime == 0 {
|
||||||
@ -37,7 +87,7 @@ class TimingTests: XCTestCase, CSTestMachineJamHandler {
|
|||||||
|
|
||||||
func testMachine(machine: CSTestMachine!, didJamAtAddress address: UInt16) {
|
func testMachine(machine: CSTestMachine!, didJamAtAddress address: UInt16) {
|
||||||
if self.endTime == 0 {
|
if self.endTime == 0 {
|
||||||
self.endTime = machine.timestamp - 3
|
self.endTime = machine.timestamp - 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ enum class Register {
|
|||||||
StackPointer,
|
StackPointer,
|
||||||
Flags,
|
Flags,
|
||||||
A,
|
A,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
S
|
S
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ template <class T> class Processor {
|
|||||||
CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL,
|
CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL,
|
||||||
CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute,
|
CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute,
|
||||||
OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow,
|
OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow,
|
||||||
CycleAddYToAddressLow, CycleCorrectAddressHigh, OperationMoveToNextProgram, OperationIncrementPC,
|
CycleAddYToAddressLow, OperationCorrectAddressHigh, OperationMoveToNextProgram, OperationIncrementPC,
|
||||||
CycleFetchOperandFromAddress, CycleWriteOperandToAddress, OperationCopyOperandFromA, OperationCopyOperandToA,
|
CycleFetchOperandFromAddress, CycleWriteOperandToAddress, OperationCopyOperandFromA, OperationCopyOperandToA,
|
||||||
CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh, OperationDecrementOperand,
|
CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh, OperationDecrementOperand,
|
||||||
OperationIncrementOperand, OperationORA, OperationAND, OperationEOR,
|
OperationIncrementOperand, OperationORA, OperationAND, OperationEOR,
|
||||||
@ -135,13 +137,13 @@ template <class T> class Processor {
|
|||||||
#define Program(...) {__VA_ARGS__, OperationMoveToNextProgram}
|
#define Program(...) {__VA_ARGS__, OperationMoveToNextProgram}
|
||||||
|
|
||||||
#define Absolute CycleLoadAddressAbsolute
|
#define Absolute CycleLoadAddressAbsolute
|
||||||
#define AbsoluteX CycleLoadAddressAbsolute, CycleAddXToAddressLow, CycleCorrectAddressHigh
|
#define AbsoluteX CycleLoadAddressAbsolute, CycleAddXToAddressLow, OperationCorrectAddressHigh
|
||||||
#define AbsoluteY CycleLoadAddressAbsolute, CycleAddYToAddressLow, CycleCorrectAddressHigh
|
#define AbsoluteY CycleLoadAddressAbsolute, CycleAddYToAddressLow, OperationCorrectAddressHigh
|
||||||
#define Zero OperationLoadAddressZeroPage
|
#define Zero OperationLoadAddressZeroPage
|
||||||
#define ZeroX CycleLoadAddessZeroX
|
#define ZeroX CycleLoadAddessZeroX
|
||||||
#define ZeroY CycleLoadAddessZeroY
|
#define ZeroY CycleLoadAddessZeroY
|
||||||
#define IndexedIndirect CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh
|
#define IndexedIndirect CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh
|
||||||
#define IndirectIndexed CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLow, CycleCorrectAddressHigh
|
#define IndirectIndexed CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLow, OperationCorrectAddressHigh
|
||||||
|
|
||||||
#define Read(op) CycleFetchOperandFromAddress, op
|
#define Read(op) CycleFetchOperandFromAddress, op
|
||||||
#define Write(op) op, CycleWriteOperandToAddress
|
#define Write(op) op, CycleWriteOperandToAddress
|
||||||
@ -750,7 +752,7 @@ template <class T> class Processor {
|
|||||||
throwaway_read(_address.full);
|
throwaway_read(_address.full);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CycleCorrectAddressHigh:
|
case OperationCorrectAddressHigh:
|
||||||
_address.full = _nextAddress.full;
|
_address.full = _nextAddress.full;
|
||||||
break;
|
break;
|
||||||
case CycleIncrementPCFetchAddressLowFromOperand:
|
case CycleIncrementPCFetchAddressLowFromOperand:
|
||||||
@ -888,6 +890,8 @@ template <class T> class Processor {
|
|||||||
case Register::StackPointer: return _s;
|
case Register::StackPointer: return _s;
|
||||||
case Register::Flags: return get_flags();
|
case Register::Flags: return get_flags();
|
||||||
case Register::A: return _a;
|
case Register::A: return _a;
|
||||||
|
case Register::X: return _x;
|
||||||
|
case Register::Y: return _y;
|
||||||
case Register::S: return _s;
|
case Register::S: return _s;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -900,6 +904,8 @@ template <class T> class Processor {
|
|||||||
case Register::StackPointer: _s = value; break;
|
case Register::StackPointer: _s = value; break;
|
||||||
case Register::Flags: set_flags(value); break;
|
case Register::Flags: set_flags(value); break;
|
||||||
case Register::A: _a = value; break;
|
case Register::A: _a = value; break;
|
||||||
|
case Register::X: _x = value; break;
|
||||||
|
case Register::Y: _y = value; break;
|
||||||
case Register::S: _s = value; break;
|
case Register::S: _s = value; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user