// // 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, CSTestMachineTrapHandler { private var endTime: UInt32 = 0 private let machine = CSTestMachine6502(is65C02: false) func testImplied() { let code: [UInt8] = [ 0xea, // [2] NOP 0x88, // [2] DEY 0xca, // [2] DEX 0x18, // [2] CLC 0x2a, // [2] ROL A ] 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) ] self.runTest(code, expectedRunLength: 48) } func testBIT() { let code: [UInt8] = [ 0x24, 0x2a, // [3] BIT $2a 0x2c, 0x2a, 0x2b, // [4] BIT $2b2a ] 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) ] 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) ] self.runTest(code, expectedRunLength: 31) } func testJSR() { let code: [UInt8] = [ 0x20, 0x04, 0x02, // [6] JSR $0204 0x00, 0x60, // [6] RTS ] machine.addTrapAddress(0x0203) 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 ] self.runTest(code, expectedRunLength: 8) } func testPHAPLA() { let code: [UInt8] = [ 0x48, // [3] PHA 0x48, // [3] PHA 0x68, // [4] PLA ] 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, ] self.runTest(code, expectedRunLength: 14) } func testSnippet1() { let code: [UInt8] = [ 0x8d, 0x08, 0x00, // [4] STA $0008 0xc6, 0xb4, // [5] DEC $B4 ] self.runTest(code, expectedRunLength: 9) } func testSnippet2() { let code: [UInt8] = [ 0x16, 0x16, // [6] ASL $16, x 0x46, 0x46, // [5] LSR $46 ] self.runTest(code, expectedRunLength: 11) } func testSnippet3() { let code: [UInt8] = [ 0x20, 0x04, 0x02, // [6] JSR $0204 0x00, 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 ] machine.addTrapAddress(0x0203) 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 ] self.runTest(code, expectedRunLength: 43) } func runTest(_ code: [UInt8], expectedRunLength: UInt32) { machine.trapHandler = self let immediateCode = Data(bytes: UnsafePointer(code), count: code.count) machine.setData(immediateCode, atAddress: 0x200) machine.addTrapAddress(UInt16(0x200 + code.count)) 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: CSTestMachine6502Register.programCounter) machine.setValue(0xff, for: CSTestMachine6502Register.X) machine.setValue(0xfe, for: CSTestMachine6502Register.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(_ testMachine: CSTestMachine, didTrapAtAddress address: UInt16) { if self.endTime == 0 { self.endTime = (machine.timestamp / 2) - 1 } } }