// // TimingTests.swift // Clock Signal // // Created by Thomas Harte on 13/08/2015. // Copyright © 2015 Thomas Harte. All rights reserved. // import Foundation import XCTest class MOS6502TimingTests: XCTestCase, CSTestMachineJamHandler { fileprivate var endTime: UInt32 = 0 func testImplied() { let code: [UInt8] = [ 0xea, // [2] NOP 0x88, // [2] DEY 0xca, // [2] DEX 0x18, // [2] CLC 0x2a, // [2] ROL A CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 10) } 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 testBIT() { let code: [UInt8] = [ 0x24, 0x2a, // [3] BIT $2a 0x2c, 0x2a, 0x2b, // [4] BIT $2b2a CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 7) } func testSTA() { let code: [UInt8] = [ 0x85, 0x00, // [3] STA $00 0x95, 0x00, // [4] STA $00,X 0x8d, 0x00, 0x00, // [4] STA $0000 0x9d, 0x00, 0x00, // [5] STA $0000, x (no wrap) 0x9d, 0x02, 0x00, // [5] STA $0002, x (wrap) 0x99, 0x00, 0x00, // [5] STA $0000, y (no wrap) 0x99, 0x10, 0x00, // [5] STA $0010, y (wrap) 0x81, 0x44, // [6] STA ($44, x) 0x91, 0x00, // [6] STA ($00), y (no wrap) 0x91, 0x02, // [6] STA ($01), y (wrap) CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 49) } func testINC() { let code: [UInt8] = [ 0xe6, 0x00, // [5] INC $00 0xf6, 0x00, // [6] INC $00,X 0xee, 0x00, 0x00, // [6] INC $0000 0xfe, 0x00, 0x00, // [7] INC $0000, x (no wrap) 0xfe, 0x02, 0x00, // [7] INC $0002, x (wrap) CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 31) } func testJSR() { let code: [UInt8] = [ 0x20, 0x04, 0x02, // [6] JSR $0204 CSTestMachineJamOpcode, 0x60, // [6] RTS ] self.runTest(code, expectedRunLength: 12) } func testJMP() { let code: [UInt8] = [ 0x6c, 0x04, 0x00, // [5] JMP ($0004) 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0b, 0x02, // [3] JMP 020b CSTestMachineJamOpcode, ] self.runTest(code, expectedRunLength: 8) } func testPHAPLA() { let code: [UInt8] = [ 0x48, // [3] PHA 0x48, // [3] PHA 0x68, // [4] PLA CSTestMachineJamOpcode, ] self.runTest(code, expectedRunLength: 10) } 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 testSnippet1() { let code: [UInt8] = [ 0x8d, 0x08, 0x00, // [4] STA $0008 0xc6, 0xb4, // [5] DEC $B4 CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 9) } func testSnippet2() { let code: [UInt8] = [ 0x16, 0x16, // [6] ASL $16, x 0x46, 0x46, // [5] LSR $46 CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 11) } func testSnippet3() { let code: [UInt8] = [ 0x20, 0x04, 0x02, // [6] JSR $0204 CSTestMachineJamOpcode, 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x85, 0x09, // [3] STA $09 0x85, 0x09, // [3] STA $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x85, 0x09, // [3] STA $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x85, 0x09, // [3] STA $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x86, 0x09, // [3] STX $09 0x87, 0x09, // [3] SAX $09 0x60, // [6] RTS CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 66) } func testNOP() { let code: [UInt8] = [ 0x04, 0x00, // [3] NOP zpg 0x14, 0x00, // [4] NOP zpg, x 0x34, 0x00, // [4] NOP zpg, x 0x44, 0x00, // [3] NOP zpg 0x54, 0x00, // [4] NOP zpg, x 0x64, 0x00, // [3] NOP zpg 0x74, 0x00, // [4] NOP zpg, x 0x80, 0x00, // [2] NOP # 0x82, 0x00, // [2] NOP # 0x89, 0x00, // [2] NOP # 0xc2, 0x00, // [2] NOP # 0xd4, 0x00, // [4] NOP zpg, x 0xe2, 0x00, // [2] NOP # 0xf4, 0x00, // [4] NOP zpg, x CSTestMachineJamOpcode] self.runTest(code, expectedRunLength: 43) } func runTest(_ code: [UInt8], expectedRunLength: UInt32) { let machine = CSTestMachine() machine.jamHandler = self let immediateCode = Data(bytes: UnsafePointer(code), count: code.count) 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(0x08, forAddress: 0x0004) machine.setValue(0x02, forAddress: 0x0005) machine.setValue(0x200, for: CSTestMachineRegister.programCounter) machine.setValue(0xff, for: CSTestMachineRegister.X) machine.setValue(0xfe, for: CSTestMachineRegister.Y) self.endTime = 0 while self.endTime == 0 { machine.runForNumber(ofCycles: 10) } XCTAssert(self.endTime == expectedRunLength, "Took \(self.endTime) cycles to perform rather than \(expectedRunLength)") } func testMachine(_ machine: CSTestMachine!, didJamAtAddress address: UInt16) { if self.endTime == 0 { self.endTime = machine.timestamp - 9 } } }