From 8a49302e3cb607c63a2715a0ed0e98df0ef6f0fe Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 13 Sep 2019 00:14:49 +0200 Subject: [PATCH] implemented a bunch of 65c02 opcodes --- .../razorvine/ksim65/components/Cpu6502.kt | 570 +++++++++--------- .../razorvine/ksim65/components/Cpu65C02.kt | 408 +++++++++++-- src/test/kotlin/Test65C02.kt | 152 ++--- 3 files changed, 738 insertions(+), 392 deletions(-) diff --git a/src/main/kotlin/razorvine/ksim65/components/Cpu6502.kt b/src/main/kotlin/razorvine/ksim65/components/Cpu6502.kt index 0ccda0a..3f856b3 100644 --- a/src/main/kotlin/razorvine/ksim65/components/Cpu6502.kt +++ b/src/main/kotlin/razorvine/ksim65/components/Cpu6502.kt @@ -2,12 +2,15 @@ package razorvine.ksim65.components // TODO: implement the illegal opcodes, see http://www.ffd2.com/fridge/docs/6502-NMOS.extra.opcodes // TODO: add the optional additional cycles to certain instructions and addressing modes +// TODO: add 6510 behavior mode (is there even a difference to be simulated here?) - +/** + * 6502 cpu simulation (the NMOS version) including the 'illegal' opcodes. + */ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { var tracing: Boolean = false var totalCycles: Long = 0 - private set + protected set class InstructionError(msg: String) : RuntimeException(msg) @@ -23,6 +26,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { Acc, Imm, Zp, + Zpr, // special addressing mode used by the 65C02 ZpX, ZpY, Rel, @@ -31,7 +35,8 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { AbsY, Ind, IzX, - IzY + IzY, + Izp // special addressing mode used by the 65C02 } class Instruction(val mnemonic: String, val mode: AddrMode, val cycles: Int) @@ -89,7 +94,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { var PC: Address = 0 val Status = StatusRegister() var currentOpcode: Int = 0 - private lateinit var currentInstruction: Instruction + protected lateinit var currentInstruction: Instruction // has an interrupt been requested? protected var pendingInterrupt: Pair? = null @@ -98,7 +103,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { private var fetchedData: Int = 0 // all other addressing modes yield a fetched memory address - private var fetchedAddress: Address = 0 + protected var fetchedAddress: Address = 0 private val breakpoints = mutableMapOf Unit>() @@ -162,6 +167,14 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { zpAddr )}" } + AddrMode.Zpr -> { + // addressing mode used by the 65C02 only + TODO("ZPR addressing mode") + } + AddrMode.Izp -> { + // addressing mode used by the 65C02 only + TODO("ZPI addressing mode") + } AddrMode.ZpX -> { val zpAddr = memory[address++] line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB( @@ -300,7 +313,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { totalCycles++ } - fun step() { + open fun step() { // step a whole instruction while (instrCycles > 0) clock() // remaining instruction subcycles from the previous instruction clock() // the actual instruction execution cycle @@ -343,16 +356,16 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { else read(fetchedAddress) - private fun readPc(): Int = bus.read(PC++).toInt() + protected fun readPc(): Int = bus.read(PC++).toInt() - private fun pushStackAddr(address: Address) { + protected fun pushStackAddr(address: Address) { val lo = address and 0xff val hi = (address ushr 8) pushStack(hi) pushStack(lo) } - private fun pushStack(status: StatusRegister) { + protected fun pushStack(status: StatusRegister) { pushStack(status.asByte().toInt()) } @@ -372,271 +385,273 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { return lo or (hi shl 8) } - private fun read(address: Address): Int = bus.read(address).toInt() + protected fun read(address: Address): Int = bus.read(address).toInt() protected fun readWord(address: Address): Int = bus.read(address).toInt() or (bus.read(address + 1).toInt() shl 8) - private fun write(address: Address, data: Int) = bus.write(address, data.toShort()) + protected fun write(address: Address, data: Int) = bus.write(address, data.toShort()) // opcodes table from http://www.oxyron.de/html/opcodes02.html - private val instructions = listOf( - Instruction("brk", AddrMode.Imp, 7), - Instruction("ora", AddrMode.IzX, 6), - Instruction("???", AddrMode.Imp, 0), - Instruction("slo", AddrMode.IzX, 8), - Instruction("nop", AddrMode.Zp, 3), - Instruction("ora", AddrMode.Zp, 3), - Instruction("asl", AddrMode.Zp, 5), - Instruction("slo", AddrMode.Zp, 5), - Instruction("php", AddrMode.Imp, 3), - Instruction("ora", AddrMode.Imm, 2), - Instruction("asl", AddrMode.Acc, 2), - Instruction("anc", AddrMode.Imm, 2), - Instruction("nop", AddrMode.Abs, 4), - Instruction("ora", AddrMode.Abs, 4), - Instruction("asl", AddrMode.Abs, 6), - Instruction("slo", AddrMode.Abs, 6), - Instruction("bpl", AddrMode.Rel, 2), - Instruction("ora", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("slo", AddrMode.IzY, 6), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("ora", AddrMode.ZpX, 4), - Instruction("asl", AddrMode.ZpX, 6), - Instruction("slo", AddrMode.ZpX, 6), - Instruction("clc", AddrMode.Imp, 2), - Instruction("ora", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("slo", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("ora", AddrMode.AbsX, 4), - Instruction("asl", AddrMode.AbsX, 7), - Instruction("slo", AddrMode.AbsX, 7), - Instruction("jsr", AddrMode.Abs, 6), - Instruction("and", AddrMode.IzX, 6), - Instruction("???", AddrMode.Imp, 0), - Instruction("rla", AddrMode.IzX, 8), - Instruction("bit", AddrMode.Zp, 3), - Instruction("and", AddrMode.Zp, 3), - Instruction("rol", AddrMode.Zp, 5), - Instruction("rla", AddrMode.Zp, 5), - Instruction("plp", AddrMode.Imp, 4), - Instruction("and", AddrMode.Imm, 2), - Instruction("rol", AddrMode.Acc, 2), - Instruction("anc", AddrMode.Imm, 2), - Instruction("bit", AddrMode.Abs, 4), - Instruction("and", AddrMode.Abs, 4), - Instruction("rol", AddrMode.Abs, 6), - Instruction("rla", AddrMode.Abs, 6), - Instruction("bmi", AddrMode.Rel, 2), - Instruction("and", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("rla", AddrMode.IzY, 8), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("and", AddrMode.ZpX, 4), - Instruction("rol", AddrMode.ZpX, 6), - Instruction("rla", AddrMode.ZpX, 6), - Instruction("sec", AddrMode.Imp, 2), - Instruction("and", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("rla", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("and", AddrMode.AbsX, 4), - Instruction("rol", AddrMode.AbsX, 7), - Instruction("rla", AddrMode.AbsX, 7), - Instruction("rti", AddrMode.Imp, 6), - Instruction("eor", AddrMode.IzX, 6), - Instruction("???", AddrMode.Imp, 0), - Instruction("sre", AddrMode.IzX, 8), - Instruction("nop", AddrMode.Zp, 3), - Instruction("eor", AddrMode.Zp, 3), - Instruction("lsr", AddrMode.Zp, 5), - Instruction("sre", AddrMode.Zp, 5), - Instruction("pha", AddrMode.Imp, 3), - Instruction("eor", AddrMode.Imm, 2), - Instruction("lsr", AddrMode.Acc, 2), - Instruction("alr", AddrMode.Imm, 2), - Instruction("jmp", AddrMode.Abs, 3), - Instruction("eor", AddrMode.Abs, 4), - Instruction("lsr", AddrMode.Abs, 6), - Instruction("sre", AddrMode.Abs, 6), - Instruction("bvc", AddrMode.Rel, 2), - Instruction("eor", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("sre", AddrMode.IzY, 8), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("eor", AddrMode.ZpX, 4), - Instruction("lsr", AddrMode.ZpX, 6), - Instruction("sre", AddrMode.ZpX, 6), - Instruction("cli", AddrMode.Imp, 2), - Instruction("eor", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("sre", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("eor", AddrMode.AbsX, 4), - Instruction("lsr", AddrMode.AbsX, 7), - Instruction("sre", AddrMode.AbsX, 7), - Instruction("rts", AddrMode.Imp, 6), - Instruction("adc", AddrMode.IzX, 6), - Instruction("???", AddrMode.Imp, 0), - Instruction("rra", AddrMode.IzX, 8), - Instruction("nop", AddrMode.Zp, 3), - Instruction("adc", AddrMode.Zp, 3), - Instruction("ror", AddrMode.Zp, 5), - Instruction("rra", AddrMode.Zp, 5), - Instruction("pla", AddrMode.Imp, 4), - Instruction("adc", AddrMode.Imm, 2), - Instruction("ror", AddrMode.Acc, 2), - Instruction("arr", AddrMode.Imm, 2), - Instruction("jmp", AddrMode.Ind, 5), - Instruction("adc", AddrMode.Abs, 4), - Instruction("ror", AddrMode.Abs, 6), - Instruction("rra", AddrMode.Abs, 6), - Instruction("bvs", AddrMode.Rel, 2), - Instruction("adc", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("rra", AddrMode.IzY, 8), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("adc", AddrMode.ZpX, 4), - Instruction("ror", AddrMode.ZpX, 6), - Instruction("rra", AddrMode.ZpX, 6), - Instruction("sei", AddrMode.Imp, 2), - Instruction("adc", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("rra", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("adc", AddrMode.AbsX, 4), - Instruction("ror", AddrMode.AbsX, 7), - Instruction("rra", AddrMode.AbsX, 7), - Instruction("nop", AddrMode.Imm, 2), - Instruction("sta", AddrMode.IzX, 6), - Instruction("nop", AddrMode.Imm, 2), - Instruction("sax", AddrMode.IzX, 6), - Instruction("sty", AddrMode.Zp, 3), - Instruction("sta", AddrMode.Zp, 3), - Instruction("stx", AddrMode.Zp, 3), - Instruction("sax", AddrMode.Zp, 3), - Instruction("dey", AddrMode.Imp, 2), - Instruction("nop", AddrMode.Imm, 2), - Instruction("txa", AddrMode.Imp, 2), - Instruction("xaa", AddrMode.Imm, 2), - Instruction("sty", AddrMode.Abs, 4), - Instruction("sta", AddrMode.Abs, 4), - Instruction("stx", AddrMode.Abs, 4), - Instruction("sax", AddrMode.Abs, 4), - Instruction("bcc", AddrMode.Rel, 2), - Instruction("sta", AddrMode.IzY, 6), - Instruction("???", AddrMode.Imp, 0), - Instruction("ahx", AddrMode.IzY, 6), - Instruction("sty", AddrMode.ZpX, 4), - Instruction("sta", AddrMode.ZpX, 4), - Instruction("stx", AddrMode.ZpY, 4), - Instruction("sax", AddrMode.ZpY, 4), - Instruction("tya", AddrMode.Imp, 2), - Instruction("sta", AddrMode.AbsY, 5), - Instruction("txs", AddrMode.Imp, 2), - Instruction("tas", AddrMode.AbsY, 5), - Instruction("shy", AddrMode.AbsX, 5), - Instruction("sta", AddrMode.AbsX, 5), - Instruction("shx", AddrMode.AbsY, 5), - Instruction("ahx", AddrMode.AbsY, 5), - Instruction("ldy", AddrMode.Imm, 2), - Instruction("lda", AddrMode.IzX, 6), - Instruction("ldx", AddrMode.Imm, 2), - Instruction("lax", AddrMode.IzX, 6), - Instruction("ldy", AddrMode.Zp, 3), - Instruction("lda", AddrMode.Zp, 3), - Instruction("ldx", AddrMode.Zp, 3), - Instruction("lax", AddrMode.Zp, 3), - Instruction("tay", AddrMode.Imp, 2), - Instruction("lda", AddrMode.Imm, 2), - Instruction("tax", AddrMode.Imp, 2), - Instruction("lax", AddrMode.Imm, 2), - Instruction("ldy", AddrMode.Abs, 4), - Instruction("lda", AddrMode.Abs, 4), - Instruction("ldx", AddrMode.Abs, 4), - Instruction("lax", AddrMode.Abs, 4), - Instruction("bcs", AddrMode.Rel, 2), - Instruction("lda", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("lax", AddrMode.IzY, 5), - Instruction("ldy", AddrMode.ZpX, 4), - Instruction("lda", AddrMode.ZpX, 4), - Instruction("ldx", AddrMode.ZpY, 4), - Instruction("lax", AddrMode.ZpY, 4), - Instruction("clv", AddrMode.Imp, 2), - Instruction("lda", AddrMode.AbsY, 4), - Instruction("tsx", AddrMode.Imp, 2), - Instruction("las", AddrMode.AbsY, 4), - Instruction("ldy", AddrMode.AbsX, 4), - Instruction("lda", AddrMode.AbsX, 4), - Instruction("ldx", AddrMode.AbsY, 4), - Instruction("lax", AddrMode.AbsY, 4), - Instruction("cpy", AddrMode.Imm, 2), - Instruction("cmp", AddrMode.IzX, 6), - Instruction("nop", AddrMode.Imm, 2), - Instruction("dcp", AddrMode.IzX, 8), - Instruction("cpy", AddrMode.Zp, 3), - Instruction("cmp", AddrMode.Zp, 3), - Instruction("dec", AddrMode.Zp, 5), - Instruction("dcp", AddrMode.Zp, 5), - Instruction("iny", AddrMode.Imp, 2), - Instruction("cmp", AddrMode.Imm, 2), - Instruction("dex", AddrMode.Imp, 2), - Instruction("axs", AddrMode.Imm, 2), - Instruction("cpy", AddrMode.Abs, 4), - Instruction("cmp", AddrMode.Abs, 4), - Instruction("dec", AddrMode.Abs, 6), - Instruction("dcp", AddrMode.Abs, 6), - Instruction("bne", AddrMode.Rel, 2), - Instruction("cmp", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("dcp", AddrMode.IzY, 8), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("cmp", AddrMode.ZpX, 4), - Instruction("dec", AddrMode.ZpX, 6), - Instruction("dcp", AddrMode.ZpX, 6), - Instruction("cld", AddrMode.Imp, 2), - Instruction("cmp", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("dcp", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("cmp", AddrMode.AbsX, 4), - Instruction("dec", AddrMode.AbsX, 7), - Instruction("dcp", AddrMode.AbsX, 7), - Instruction("cpx", AddrMode.Imm, 2), - Instruction("sbc", AddrMode.IzX, 6), - Instruction("nop", AddrMode.Imm, 2), - Instruction("isc", AddrMode.IzX, 8), - Instruction("cpx", AddrMode.Zp, 3), - Instruction("sbc", AddrMode.Zp, 3), - Instruction("inc", AddrMode.Zp, 5), - Instruction("isc", AddrMode.Zp, 5), - Instruction("inx", AddrMode.Imp, 2), - Instruction("sbc", AddrMode.Imm, 2), - Instruction("nop", AddrMode.Imp, 2), - Instruction("sbc", AddrMode.Imm, 2), - Instruction("cpx", AddrMode.Abs, 4), - Instruction("sbc", AddrMode.Abs, 4), - Instruction("inc", AddrMode.Abs, 6), - Instruction("isc", AddrMode.Abs, 6), - Instruction("beq", AddrMode.Rel, 2), - Instruction("sbc", AddrMode.IzY, 5), - Instruction("???", AddrMode.Imp, 0), - Instruction("isc", AddrMode.IzY, 8), - Instruction("nop", AddrMode.ZpX, 4), - Instruction("sbc", AddrMode.ZpX, 4), - Instruction("inc", AddrMode.ZpX, 6), - Instruction("isc", AddrMode.ZpX, 6), - Instruction("sed", AddrMode.Imp, 2), - Instruction("sbc", AddrMode.AbsY, 4), - Instruction("nop", AddrMode.Imp, 2), - Instruction("isc", AddrMode.AbsY, 7), - Instruction("nop", AddrMode.AbsX, 4), - Instruction("sbc", AddrMode.AbsX, 4), - Instruction("inc", AddrMode.AbsX, 7), - Instruction("isc", AddrMode.AbsX, 7) - ).toTypedArray() + protected open val instructions: Array by lazy { + listOf( + /* 00 */ Instruction("brk", AddrMode.Imp, 7), + /* 01 */ Instruction("ora", AddrMode.IzX, 6), + /* 02 */ Instruction("???", AddrMode.Imp, 2), + /* 03 */ Instruction("slo", AddrMode.IzX, 8), + /* 04 */ Instruction("nop", AddrMode.Zp, 3), + /* 05 */ Instruction("ora", AddrMode.Zp, 3), + /* 06 */ Instruction("asl", AddrMode.Zp, 5), + /* 07 */ Instruction("slo", AddrMode.Zp, 5), + /* 08 */ Instruction("php", AddrMode.Imp, 3), + /* 09 */ Instruction("ora", AddrMode.Imm, 2), + /* 0a */ Instruction("asl", AddrMode.Acc, 2), + /* 0b */ Instruction("anc", AddrMode.Imm, 2), + /* 0c */ Instruction("nop", AddrMode.Abs, 4), + /* 0d */ Instruction("ora", AddrMode.Abs, 4), + /* 0e */ Instruction("asl", AddrMode.Abs, 6), + /* 0f */ Instruction("slo", AddrMode.Abs, 6), + /* 10 */ Instruction("bpl", AddrMode.Rel, 2), + /* 11 */ Instruction("ora", AddrMode.IzY, 5), + /* 12 */ Instruction("???", AddrMode.Imp, 2), + /* 13 */ Instruction("slo", AddrMode.IzY, 8), + /* 14 */ Instruction("nop", AddrMode.ZpX, 4), + /* 15 */ Instruction("ora", AddrMode.ZpX, 4), + /* 16 */ Instruction("asl", AddrMode.ZpX, 6), + /* 17 */ Instruction("slo", AddrMode.ZpX, 6), + /* 18 */ Instruction("clc", AddrMode.Imp, 2), + /* 19 */ Instruction("ora", AddrMode.AbsY, 4), + /* 1a */ Instruction("nop", AddrMode.Imp, 2), + /* 1b */ Instruction("slo", AddrMode.AbsY, 7), + /* 1c */ Instruction("nop", AddrMode.AbsX, 4), + /* 1d */ Instruction("ora", AddrMode.AbsX, 4), + /* 1e */ Instruction("asl", AddrMode.AbsX, 7), + /* 1f */ Instruction("slo", AddrMode.AbsX, 7), + /* 20 */ Instruction("jsr", AddrMode.Abs, 6), + /* 21 */ Instruction("and", AddrMode.IzX, 6), + /* 22 */ Instruction("???", AddrMode.Imp, 2), + /* 23 */ Instruction("rla", AddrMode.IzX, 8), + /* 24 */ Instruction("bit", AddrMode.Zp, 3), + /* 25 */ Instruction("and", AddrMode.Zp, 3), + /* 26 */ Instruction("rol", AddrMode.Zp, 5), + /* 27 */ Instruction("rla", AddrMode.Zp, 5), + /* 28 */ Instruction("plp", AddrMode.Imp, 4), + /* 29 */ Instruction("and", AddrMode.Imm, 2), + /* 2a */ Instruction("rol", AddrMode.Acc, 2), + /* 2b */ Instruction("anc", AddrMode.Imm, 2), + /* 2c */ Instruction("bit", AddrMode.Abs, 4), + /* 2d */ Instruction("and", AddrMode.Abs, 4), + /* 2e */ Instruction("rol", AddrMode.Abs, 6), + /* 2f */ Instruction("rla", AddrMode.Abs, 6), + /* 30 */ Instruction("bmi", AddrMode.Rel, 2), + /* 31 */ Instruction("and", AddrMode.IzY, 5), + /* 32 */ Instruction("???", AddrMode.Imp, 2), + /* 33 */ Instruction("rla", AddrMode.IzY, 8), + /* 34 */ Instruction("nop", AddrMode.ZpX, 4), + /* 35 */ Instruction("and", AddrMode.ZpX, 4), + /* 36 */ Instruction("rol", AddrMode.ZpX, 6), + /* 37 */ Instruction("rla", AddrMode.ZpX, 6), + /* 38 */ Instruction("sec", AddrMode.Imp, 2), + /* 39 */ Instruction("and", AddrMode.AbsY, 4), + /* 3a */ Instruction("nop", AddrMode.Imp, 2), + /* 3b */ Instruction("rla", AddrMode.AbsY, 7), + /* 3c */ Instruction("nop", AddrMode.AbsX, 4), + /* 3d */ Instruction("and", AddrMode.AbsX, 4), + /* 3e */ Instruction("rol", AddrMode.AbsX, 7), + /* 3f */ Instruction("rla", AddrMode.AbsX, 7), + /* 40 */ Instruction("rti", AddrMode.Imp, 6), + /* 41 */ Instruction("eor", AddrMode.IzX, 6), + /* 42 */ Instruction("???", AddrMode.Imp, 2), + /* 43 */ Instruction("sre", AddrMode.IzX, 8), + /* 44 */ Instruction("nop", AddrMode.Zp, 3), + /* 45 */ Instruction("eor", AddrMode.Zp, 3), + /* 46 */ Instruction("lsr", AddrMode.Zp, 5), + /* 47 */ Instruction("sre", AddrMode.Zp, 5), + /* 48 */ Instruction("pha", AddrMode.Imp, 3), + /* 49 */ Instruction("eor", AddrMode.Imm, 2), + /* 4a */ Instruction("lsr", AddrMode.Acc, 2), + /* 4b */ Instruction("alr", AddrMode.Imm, 2), + /* 4c */ Instruction("jmp", AddrMode.Abs, 3), + /* 4d */ Instruction("eor", AddrMode.Abs, 4), + /* 4e */ Instruction("lsr", AddrMode.Abs, 6), + /* 4f */ Instruction("sre", AddrMode.Abs, 6), + /* 50 */ Instruction("bvc", AddrMode.Rel, 2), + /* 51 */ Instruction("eor", AddrMode.IzY, 5), + /* 52 */ Instruction("???", AddrMode.Imp, 2), + /* 53 */ Instruction("sre", AddrMode.IzY, 8), + /* 54 */ Instruction("nop", AddrMode.ZpX, 4), + /* 55 */ Instruction("eor", AddrMode.ZpX, 4), + /* 56 */ Instruction("lsr", AddrMode.ZpX, 6), + /* 57 */ Instruction("sre", AddrMode.ZpX, 6), + /* 58 */ Instruction("cli", AddrMode.Imp, 2), + /* 59 */ Instruction("eor", AddrMode.AbsY, 4), + /* 5a */ Instruction("nop", AddrMode.Imp, 2), + /* 5b */ Instruction("sre", AddrMode.AbsY, 7), + /* 5c */ Instruction("nop", AddrMode.AbsX, 4), + /* 5d */ Instruction("eor", AddrMode.AbsX, 4), + /* 5e */ Instruction("lsr", AddrMode.AbsX, 7), + /* 5f */ Instruction("sre", AddrMode.AbsX, 7), + /* 60 */ Instruction("rts", AddrMode.Imp, 6), + /* 61 */ Instruction("adc", AddrMode.IzX, 6), + /* 62 */ Instruction("???", AddrMode.Imp, 2), + /* 63 */ Instruction("rra", AddrMode.IzX, 8), + /* 64 */ Instruction("nop", AddrMode.Zp, 3), + /* 65 */ Instruction("adc", AddrMode.Zp, 3), + /* 66 */ Instruction("ror", AddrMode.Zp, 5), + /* 67 */ Instruction("rra", AddrMode.Zp, 5), + /* 68 */ Instruction("pla", AddrMode.Imp, 4), + /* 69 */ Instruction("adc", AddrMode.Imm, 2), + /* 6a */ Instruction("ror", AddrMode.Acc, 2), + /* 6b */ Instruction("arr", AddrMode.Imm, 2), + /* 6c */ Instruction("jmp", AddrMode.Ind, 5), + /* 6d */ Instruction("adc", AddrMode.Abs, 4), + /* 6e */ Instruction("ror", AddrMode.Abs, 6), + /* 6f */ Instruction("rra", AddrMode.Abs, 6), + /* 70 */ Instruction("bvs", AddrMode.Rel, 2), + /* 71 */ Instruction("adc", AddrMode.IzY, 5), + /* 72 */ Instruction("???", AddrMode.Imp, 2), + /* 73 */ Instruction("rra", AddrMode.IzY, 8), + /* 74 */ Instruction("nop", AddrMode.ZpX, 4), + /* 75 */ Instruction("adc", AddrMode.ZpX, 4), + /* 76 */ Instruction("ror", AddrMode.ZpX, 6), + /* 77 */ Instruction("rra", AddrMode.ZpX, 6), + /* 78 */ Instruction("sei", AddrMode.Imp, 2), + /* 79 */ Instruction("adc", AddrMode.AbsY, 4), + /* 7a */ Instruction("nop", AddrMode.Imp, 2), + /* 7b */ Instruction("rra", AddrMode.AbsY, 7), + /* 7c */ Instruction("nop", AddrMode.AbsX, 4), + /* 7d */ Instruction("adc", AddrMode.AbsX, 4), + /* 7e */ Instruction("ror", AddrMode.AbsX, 7), + /* 7f */ Instruction("rra", AddrMode.AbsX, 7), + /* 80 */ Instruction("nop", AddrMode.Imm, 2), + /* 81 */ Instruction("sta", AddrMode.IzX, 6), + /* 82 */ Instruction("nop", AddrMode.Imm, 2), + /* 83 */ Instruction("sax", AddrMode.IzX, 6), + /* 84 */ Instruction("sty", AddrMode.Zp, 3), + /* 85 */ Instruction("sta", AddrMode.Zp, 3), + /* 86 */ Instruction("stx", AddrMode.Zp, 3), + /* 87 */ Instruction("sax", AddrMode.Zp, 3), + /* 88 */ Instruction("dey", AddrMode.Imp, 2), + /* 89 */ Instruction("nop", AddrMode.Imm, 2), + /* 8a */ Instruction("txa", AddrMode.Imp, 2), + /* 8b */ Instruction("xaa", AddrMode.Imm, 2), + /* 8c */ Instruction("sty", AddrMode.Abs, 4), + /* 8d */ Instruction("sta", AddrMode.Abs, 4), + /* 8e */ Instruction("stx", AddrMode.Abs, 4), + /* 8f */ Instruction("sax", AddrMode.Abs, 4), + /* 90 */ Instruction("bcc", AddrMode.Rel, 2), + /* 91 */ Instruction("sta", AddrMode.IzY, 6), + /* 92 */ Instruction("???", AddrMode.Imp, 2), + /* 93 */ Instruction("ahx", AddrMode.IzY, 6), + /* 94 */ Instruction("sty", AddrMode.ZpX, 4), + /* 95 */ Instruction("sta", AddrMode.ZpX, 4), + /* 96 */ Instruction("stx", AddrMode.ZpY, 4), + /* 97 */ Instruction("sax", AddrMode.ZpY, 4), + /* 98 */ Instruction("tya", AddrMode.Imp, 2), + /* 99 */ Instruction("sta", AddrMode.AbsY, 5), + /* 9a */ Instruction("txs", AddrMode.Imp, 2), + /* 9b */ Instruction("tas", AddrMode.AbsY, 5), + /* 9c */ Instruction("shy", AddrMode.AbsX, 5), + /* 9d */ Instruction("sta", AddrMode.AbsX, 5), + /* 9e */ Instruction("shx", AddrMode.AbsY, 5), + /* 9f */ Instruction("ahx", AddrMode.AbsY, 5), + /* a0 */ Instruction("ldy", AddrMode.Imm, 2), + /* a1 */ Instruction("lda", AddrMode.IzX, 6), + /* a2 */ Instruction("ldx", AddrMode.Imm, 2), + /* a3 */ Instruction("lax", AddrMode.IzX, 6), + /* a4 */ Instruction("ldy", AddrMode.Zp, 3), + /* a5 */ Instruction("lda", AddrMode.Zp, 3), + /* a6 */ Instruction("ldx", AddrMode.Zp, 3), + /* a7 */ Instruction("lax", AddrMode.Zp, 3), + /* a8 */ Instruction("tay", AddrMode.Imp, 2), + /* a9 */ Instruction("lda", AddrMode.Imm, 2), + /* aa */ Instruction("tax", AddrMode.Imp, 2), + /* ab */ Instruction("lax", AddrMode.Imm, 2), + /* ac */ Instruction("ldy", AddrMode.Abs, 4), + /* ad */ Instruction("lda", AddrMode.Abs, 4), + /* ae */ Instruction("ldx", AddrMode.Abs, 4), + /* af */ Instruction("lax", AddrMode.Abs, 4), + /* b0 */ Instruction("bcs", AddrMode.Rel, 2), + /* b1 */ Instruction("lda", AddrMode.IzY, 5), + /* b2 */ Instruction("???", AddrMode.Imp, 2), + /* b3 */ Instruction("lax", AddrMode.IzY, 5), + /* b4 */ Instruction("ldy", AddrMode.ZpX, 4), + /* b5 */ Instruction("lda", AddrMode.ZpX, 4), + /* b6 */ Instruction("ldx", AddrMode.ZpY, 4), + /* b7 */ Instruction("lax", AddrMode.ZpY, 4), + /* b8 */ Instruction("clv", AddrMode.Imp, 2), + /* b9 */ Instruction("lda", AddrMode.AbsY, 4), + /* ba */ Instruction("tsx", AddrMode.Imp, 2), + /* bb */ Instruction("las", AddrMode.AbsY, 4), + /* bc */ Instruction("ldy", AddrMode.AbsX, 4), + /* bd */ Instruction("lda", AddrMode.AbsX, 4), + /* be */ Instruction("ldx", AddrMode.AbsY, 4), + /* bf */ Instruction("lax", AddrMode.AbsY, 4), + /* c0 */ Instruction("cpy", AddrMode.Imm, 2), + /* c1 */ Instruction("cmp", AddrMode.IzX, 6), + /* c2 */ Instruction("nop", AddrMode.Imm, 2), + /* c3 */ Instruction("dcp", AddrMode.IzX, 8), + /* c4 */ Instruction("cpy", AddrMode.Zp, 3), + /* c5 */ Instruction("cmp", AddrMode.Zp, 3), + /* c6 */ Instruction("dec", AddrMode.Zp, 5), + /* c7 */ Instruction("dcp", AddrMode.Zp, 5), + /* c8 */ Instruction("iny", AddrMode.Imp, 2), + /* c9 */ Instruction("cmp", AddrMode.Imm, 2), + /* ca */ Instruction("dex", AddrMode.Imp, 2), + /* cb */ Instruction("axs", AddrMode.Imm, 2), + /* cc */ Instruction("cpy", AddrMode.Abs, 4), + /* cd */ Instruction("cmp", AddrMode.Abs, 4), + /* ce */ Instruction("dec", AddrMode.Abs, 6), + /* cf */ Instruction("dcp", AddrMode.Abs, 6), + /* d0 */ Instruction("bne", AddrMode.Rel, 2), + /* d1 */ Instruction("cmp", AddrMode.IzY, 5), + /* d2 */ Instruction("???", AddrMode.Imp, 2), + /* d3 */ Instruction("dcp", AddrMode.IzY, 8), + /* d4 */ Instruction("nop", AddrMode.ZpX, 4), + /* d5 */ Instruction("cmp", AddrMode.ZpX, 4), + /* d6 */ Instruction("dec", AddrMode.ZpX, 6), + /* d7 */ Instruction("dcp", AddrMode.ZpX, 6), + /* d8 */ Instruction("cld", AddrMode.Imp, 2), + /* d9 */ Instruction("cmp", AddrMode.AbsY, 4), + /* da */ Instruction("nop", AddrMode.Imp, 2), + /* db */ Instruction("dcp", AddrMode.AbsY, 7), + /* dc */ Instruction("nop", AddrMode.AbsX, 4), + /* dd */ Instruction("cmp", AddrMode.AbsX, 4), + /* de */ Instruction("dec", AddrMode.AbsX, 7), + /* df */ Instruction("dcp", AddrMode.AbsX, 7), + /* e0 */ Instruction("cpx", AddrMode.Imm, 2), + /* e1 */ Instruction("sbc", AddrMode.IzX, 6), + /* e2 */ Instruction("nop", AddrMode.Imm, 2), + /* e3 */ Instruction("isc", AddrMode.IzX, 8), + /* e4 */ Instruction("cpx", AddrMode.Zp, 3), + /* e5 */ Instruction("sbc", AddrMode.Zp, 3), + /* e6 */ Instruction("inc", AddrMode.Zp, 5), + /* e7 */ Instruction("isc", AddrMode.Zp, 5), + /* e8 */ Instruction("inx", AddrMode.Imp, 2), + /* e9 */ Instruction("sbc", AddrMode.Imm, 2), + /* ea */ Instruction("nop", AddrMode.Imp, 2), + /* eb */ Instruction("sbc", AddrMode.Imm, 2), + /* ec */ Instruction("cpx", AddrMode.Abs, 4), + /* ed */ Instruction("sbc", AddrMode.Abs, 4), + /* ee */ Instruction("inc", AddrMode.Abs, 6), + /* ef */ Instruction("isc", AddrMode.Abs, 6), + /* f0 */ Instruction("beq", AddrMode.Rel, 2), + /* f1 */ Instruction("sbc", AddrMode.IzY, 5), + /* f2 */ Instruction("???", AddrMode.Imp, 2), + /* f3 */ Instruction("isc", AddrMode.IzY, 8), + /* f4 */ Instruction("nop", AddrMode.ZpX, 4), + /* f5 */ Instruction("sbc", AddrMode.ZpX, 4), + /* f6 */ Instruction("inc", AddrMode.ZpX, 6), + /* f7 */ Instruction("isc", AddrMode.ZpX, 6), + /* f8 */ Instruction("sed", AddrMode.Imp, 2), + /* f9 */ Instruction("sbc", AddrMode.AbsY, 4), + /* fa */ Instruction("nop", AddrMode.Imp, 2), + /* fb */ Instruction("isc", AddrMode.AbsY, 7), + /* fc */ Instruction("nop", AddrMode.AbsX, 4), + /* fd */ Instruction("sbc", AddrMode.AbsX, 4), + /* fe */ Instruction("inc", AddrMode.AbsX, 7), + /* ff */ Instruction("isc", AddrMode.AbsX, 7) + ).toTypedArray() + } - private fun applyAddressingMode(addrMode: AddrMode) { + protected open fun applyAddressingMode(addrMode: AddrMode) { when (addrMode) { AddrMode.Imp, AddrMode.Acc -> { fetchedData = A @@ -707,6 +722,10 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { val hi = read((fetchedAddress + 1) and 0xff) fetchedAddress = Y + (lo or (hi shl 8)) and 0xffff } + AddrMode.Zpr, AddrMode.Izp -> { + // addressing mode used by the 65C02 only + throw InstructionError("65c02 addressing mode not implemented on 6502") + } } } @@ -968,7 +987,8 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { 0xfd -> iSbc() 0xfe -> iInc() 0xff -> iIsc() - else -> { /* can't occur */ } + else -> { /* can't occur */ + } } } @@ -1060,7 +1080,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { if (!Status.N) PC = fetchedAddress } - protected fun iBrk() { + protected open fun iBrk() { // handle BRK ('software interrupt') or a real hardware IRQ val interrupt = pendingInterrupt val nmi = interrupt?.first == true @@ -1073,7 +1093,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { Status.B = interrupt == null pushStack(Status) Status.I = true // interrupts are now disabled - // NMOS 6502 doesn't clear the D flag (CMOS version does...) + // NMOS 6502 doesn't clear the D flag (CMOS 65C02 version does...) PC = readWord(if (nmi) NMI_vector else IRQ_vector) pendingInterrupt = null } @@ -1123,7 +1143,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { Status.N = ((Y - fetched) and 0b10000000) != 0 } - protected fun iDec() { + protected open fun iDec() { val data = (read(fetchedAddress) - 1) and 0xff write(fetchedAddress, data) Status.Z = data == 0 @@ -1148,7 +1168,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() { Status.N = (A and 0b10000000) != 0 } - protected fun iInc() { + protected open fun iInc() { val data = (read(fetchedAddress) + 1) and 0xff write(fetchedAddress, data) Status.Z = data == 0 diff --git a/src/main/kotlin/razorvine/ksim65/components/Cpu65C02.kt b/src/main/kotlin/razorvine/ksim65/components/Cpu65C02.kt index b9f0080..0e588b7 100644 --- a/src/main/kotlin/razorvine/ksim65/components/Cpu65C02.kt +++ b/src/main/kotlin/razorvine/ksim65/components/Cpu65C02.kt @@ -1,5 +1,8 @@ package razorvine.ksim65.components +/** + * 65C02 cpu simulation (the CMOS version of the 6502). + */ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { enum class Wait { @@ -10,8 +13,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { var waiting: Wait = Wait.Normal - // TODO implement this CPU type 65C02, and re-enable the unit tests for that - companion object { const val NMI_vector = Cpu6502.NMI_vector const val RESET_vector = Cpu6502.RESET_vector @@ -20,17 +21,17 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { } override fun clock() { - when(waiting) { + when (waiting) { Wait.Normal -> super.clock() Wait.Waiting -> { - if(pendingInterrupt!=null) { + if (pendingInterrupt != null) { // continue execution after hardware interrupt waiting = Wait.Normal instrCycles = 1 } } Wait.Stopped -> { - if(pendingInterrupt!=null) { + if (pendingInterrupt != null) { // jump to reset vector after hardware interrupt PC = readWord(RESET_vector) } @@ -38,7 +39,46 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { } } - // opcode list: http://www.oxyron.de/html/opcodesc02.html + override fun step() { + // step a whole instruction + if (waiting == Wait.Normal) { + while (instrCycles > 0) clock() // remaining instruction subcycles from the previous instruction + clock() // the actual instruction execution cycle + if (waiting == Wait.Normal) + while (instrCycles > 0) clock() // instruction subcycles + else { + totalCycles += instrCycles + instrCycles = 0 + } + } + } + + override fun applyAddressingMode(addrMode: AddrMode) { + when (addrMode) { + AddrMode.Imp, AddrMode.Acc, AddrMode.Imm, + AddrMode.Zp, AddrMode.ZpX, AddrMode.ZpY, + AddrMode.Rel, AddrMode.Abs, AddrMode.AbsX, AddrMode.AbsY, + AddrMode.IzX, AddrMode.IzY-> { + super.applyAddressingMode(addrMode) + } + AddrMode.Ind -> { + // not able to fetch an address which crosses the page boundary (6502, fixed in 65C02) + TODO("IND addrmode fixed for 65c02") + } + AddrMode.Zpr -> { + // addressing mode used by the 65C02 only + TODO("ZPR addressing mode") + } + AddrMode.Izp -> { + // addressing mode used by the 65C02 only + fetchedAddress = readPc() + val lo = read((fetchedAddress) and 0xff) + val hi = read((fetchedAddress + 1) and 0xff) + fetchedAddress = lo or (hi shl 8) + } + } + } + override fun dispatchOpcode(opcode: Int) { when (opcode) { 0x00 -> iBrk() @@ -56,8 +96,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x0c -> iTsb() 0x0d -> iOra() 0x0e -> iAsl() - 0x0f -> iBrr0() - + 0x0f -> iBbr0() 0x10 -> iBpl() 0x11 -> iOra() 0x12 -> iOra() @@ -73,8 +112,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x1c -> iTrb() 0x1d -> iOra() 0x1e -> iAsl() - 0x1f -> iBrr1() - + 0x1f -> iBbr1() 0x20 -> iJsr() 0x21 -> iAnd() 0x22 -> iNop() @@ -90,8 +128,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x2c -> iBit() 0x2d -> iAnd() 0x2e -> iRol() - 0x2f -> iBrr2() - + 0x2f -> iBbr2() 0x30 -> iBmi() 0x31 -> iAnd() 0x32 -> iAnd() @@ -107,8 +144,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x3c -> iBit() 0x3d -> iAnd() 0x3e -> iRol() - 0x3f -> iBrr3() - + 0x3f -> iBbr3() 0x40 -> iRti() 0x41 -> iEor() 0x42 -> iNop() @@ -124,8 +160,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x4c -> iJmp() 0x4d -> iEor() 0x4e -> iLsr() - 0x4f -> iBrr4() - + 0x4f -> iBbr4() 0x50 -> iBvc() 0x51 -> iEor() 0x52 -> iEor() @@ -141,8 +176,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x5c -> iNop() 0x5d -> iEor() 0x5e -> iLsr() - 0x5f -> iBrr5() - + 0x5f -> iBbr5() 0x60 -> iRts() 0x61 -> iAdc() 0x62 -> iNop() @@ -158,8 +192,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x6c -> iJmp() 0x6d -> iAdc() 0x6e -> iRor() - 0x6f -> iBrr6() - + 0x6f -> iBbr6() 0x70 -> iBvs() 0x71 -> iAdc() 0x72 -> iAdc() @@ -175,8 +208,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x7c -> iJmp() 0x7d -> iAdc() 0x7e -> iRor() - 0x7f -> iBrr7() - + 0x7f -> iBbr7() 0x80 -> iBra() 0x81 -> iSta() 0x82 -> iNop() @@ -193,7 +225,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x8d -> iSta() 0x8e -> iStx() 0x8f -> iBbs0() - 0x90 -> iBcc() 0x91 -> iSta() 0x92 -> iSta() @@ -210,7 +241,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0x9d -> iSta() 0x9e -> iStz() 0x9f -> iBbs1() - 0xa0 -> iLdy() 0xa1 -> iLda() 0xa2 -> iLdx() @@ -227,7 +257,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0xad -> iLda() 0xae -> iLdx() 0xaf -> iBbs2() - 0xb0 -> iBcs() 0xb1 -> iLda() 0xb2 -> iLda() @@ -244,7 +273,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0xbd -> iLda() 0xbe -> iLdx() 0xbf -> iBbs3() - 0xc0 -> iCpy() 0xc1 -> iCmp() 0xc2 -> iNop() @@ -261,7 +289,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0xcd -> iCmp() 0xce -> iDec() 0xcf -> iBbs4() - 0xd0 -> iBne() 0xd1 -> iCmp() 0xd2 -> iCmp() @@ -278,7 +305,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0xdd -> iCmp() 0xde -> iDec() 0xdf -> iBbs5() - 0xe0 -> iCpx() 0xe1 -> iSbc() 0xe2 -> iNop() @@ -295,7 +321,6 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { 0xed -> iSbc() 0xee -> iInc() 0xef -> iBbs6() - 0xf0 -> iBeq() 0xf1 -> iSbc() 0xf2 -> iSbc() @@ -317,8 +342,309 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { } } + // opcode list: http://www.oxyron.de/html/opcodesc02.html + // TODO fix cycle counts + // TODO add optional additional cycles + override val instructions: Array by lazy { + listOf( + /* 00 */ Instruction("brk", AddrMode.Imp, 7), + /* 01 */ Instruction("ora", AddrMode.IzX, 6), + /* 02 */ Instruction("nop", AddrMode.Imm, 2), + /* 03 */ Instruction("nop", AddrMode.Imp, 1), + /* 04 */ Instruction("tsb", AddrMode.Zp, 5), + /* 05 */ Instruction("ora", AddrMode.Zp, 3), + /* 06 */ Instruction("asl", AddrMode.Zp, 5), + /* 07 */ Instruction("rmb0", AddrMode.Zp, 5), + /* 08 */ Instruction("php", AddrMode.Imp, 3), + /* 09 */ Instruction("ora", AddrMode.Imm, 2), + /* 0a */ Instruction("asl", AddrMode.Acc, 2), + /* 0b */ Instruction("nop", AddrMode.Imp, 1), + /* 0c */ Instruction("tsb", AddrMode.Abs, 6), + /* 0d */ Instruction("ora", AddrMode.Abs, 4), + /* 0e */ Instruction("asl", AddrMode.Abs, 6), + /* 0f */ Instruction("bbr0", AddrMode.Zpr, 5), + /* 10 */ Instruction("bpl", AddrMode.Rel, 2), + /* 11 */ Instruction("ora", AddrMode.IzY, 5), + /* 12 */ Instruction("ora", AddrMode.Izp, 5), + /* 13 */ Instruction("nop", AddrMode.Imp, 1), + /* 14 */ Instruction("trb", AddrMode.Zp, 5), + /* 15 */ Instruction("ora", AddrMode.ZpX, 4), + /* 16 */ Instruction("asl", AddrMode.ZpX, 6), + /* 17 */ Instruction("rmb1", AddrMode.Zp, 5), + /* 18 */ Instruction("clc", AddrMode.Imp, 2), + /* 19 */ Instruction("ora", AddrMode.AbsY, 4), + /* 1a */ Instruction("inc", AddrMode.Acc, 2), + /* 1b */ Instruction("nop", AddrMode.Imp, 1), + /* 1c */ Instruction("trb", AddrMode.Abs, 6), + /* 1d */ Instruction("ora", AddrMode.AbsX, 4), + /* 1e */ Instruction("asl", AddrMode.AbsX, 7), + /* 1f */ Instruction("bbr1", AddrMode.Zpr, 5), + /* 20 */ Instruction("jsr", AddrMode.Abs, 6), + /* 21 */ Instruction("and", AddrMode.IzX, 6), + /* 22 */ Instruction("nop", AddrMode.Imm, 2), + /* 23 */ Instruction("nop", AddrMode.Imp, 1), + /* 24 */ Instruction("bit", AddrMode.Zp, 3), + /* 25 */ Instruction("and", AddrMode.Zp, 3), + /* 26 */ Instruction("rol", AddrMode.Zp, 5), + /* 27 */ Instruction("rmb2", AddrMode.Zp, 5), + /* 28 */ Instruction("plp", AddrMode.Imp, 4), + /* 29 */ Instruction("and", AddrMode.Imm, 2), + /* 2a */ Instruction("rol", AddrMode.Acc, 2), + /* 2b */ Instruction("nop", AddrMode.Imp, 1), + /* 2c */ Instruction("bit", AddrMode.Abs, 4), + /* 2d */ Instruction("and", AddrMode.Abs, 4), + /* 2e */ Instruction("rol", AddrMode.Abs, 6), + /* 2f */ Instruction("bbr2", AddrMode.Zpr, 5), + /* 30 */ Instruction("bmi", AddrMode.Rel, 2), + /* 31 */ Instruction("and", AddrMode.IzY, 5), + /* 32 */ Instruction("and", AddrMode.Izp, 5), + /* 33 */ Instruction("nop", AddrMode.Imp, 1), + /* 34 */ Instruction("bit", AddrMode.ZpX, 4), + /* 35 */ Instruction("and", AddrMode.ZpX, 4), + /* 36 */ Instruction("rol", AddrMode.ZpX, 6), + /* 37 */ Instruction("rmb3", AddrMode.Zp, 5), + /* 38 */ Instruction("sec", AddrMode.Imp, 2), + /* 39 */ Instruction("and", AddrMode.AbsY, 4), + /* 3a */ Instruction("dec", AddrMode.Acc, 2), + /* 3b */ Instruction("nop", AddrMode.Imp, 1), + /* 3c */ Instruction("bit", AddrMode.AbsX, 4), + /* 3d */ Instruction("and", AddrMode.AbsX, 4), + /* 3e */ Instruction("rol", AddrMode.AbsX, 7), + /* 3f */ Instruction("bbr3", AddrMode.Zpr, 5), + /* 40 */ Instruction("rti", AddrMode.Imp, 6), + /* 41 */ Instruction("eor", AddrMode.IzX, 6), + /* 42 */ Instruction("nop", AddrMode.Imm, 2), + /* 43 */ Instruction("nop", AddrMode.Imp, 1), + /* 44 */ Instruction("nop", AddrMode.Zp, 3), + /* 45 */ Instruction("eor", AddrMode.Zp, 3), + /* 46 */ Instruction("lsr", AddrMode.Zp, 5), + /* 47 */ Instruction("rmb4", AddrMode.Zp, 5), + /* 48 */ Instruction("pha", AddrMode.Imp, 3), + /* 49 */ Instruction("eor", AddrMode.Imm, 2), + /* 4a */ Instruction("lsr", AddrMode.Acc, 2), + /* 4b */ Instruction("nop", AddrMode.Imp, 1), + /* 4c */ Instruction("jmp", AddrMode.Abs, 3), + /* 4d */ Instruction("eor", AddrMode.Abs, 4), + /* 4e */ Instruction("lsr", AddrMode.Abs, 6), + /* 4f */ Instruction("bbr4", AddrMode.Zpr, 5), + /* 50 */ Instruction("bvc", AddrMode.Rel, 2), + /* 51 */ Instruction("eor", AddrMode.IzY, 5), + /* 52 */ Instruction("eor", AddrMode.Izp, 5), + /* 53 */ Instruction("nop", AddrMode.Imp, 1), + /* 54 */ Instruction("nop", AddrMode.ZpX, 4), + /* 55 */ Instruction("eor", AddrMode.ZpX, 4), + /* 56 */ Instruction("lsr", AddrMode.ZpX, 6), + /* 57 */ Instruction("rmb5", AddrMode.Zp, 5), + /* 58 */ Instruction("cli", AddrMode.Imp, 2), + /* 59 */ Instruction("eor", AddrMode.AbsY, 4), + /* 5a */ Instruction("phy", AddrMode.Imp, 3), + /* 5b */ Instruction("nop", AddrMode.Imp, 1), + /* 5c */ Instruction("nop", AddrMode.Abs, 8), + /* 5d */ Instruction("eor", AddrMode.AbsX, 4), + /* 5e */ Instruction("lsr", AddrMode.AbsX, 7), + /* 5f */ Instruction("bbr5", AddrMode.Zpr, 5), + /* 60 */ Instruction("rts", AddrMode.Imp, 6), + /* 61 */ Instruction("adc", AddrMode.IzX, 6), + /* 62 */ Instruction("nop", AddrMode.Imm, 2), + /* 63 */ Instruction("nop", AddrMode.Imp, 1), + /* 64 */ Instruction("stz", AddrMode.Zp, 3), + /* 65 */ Instruction("adc", AddrMode.Zp, 3), + /* 66 */ Instruction("ror", AddrMode.Zp, 5), + /* 67 */ Instruction("rmb6", AddrMode.Zp, 5), + /* 68 */ Instruction("pla", AddrMode.Imp, 4), + /* 69 */ Instruction("adc", AddrMode.Imm, 2), + /* 6a */ Instruction("ror", AddrMode.Acc, 2), + /* 6b */ Instruction("nop", AddrMode.Imp, 1), + /* 6c */ Instruction("jmp", AddrMode.Ind, 5), + /* 6d */ Instruction("adc", AddrMode.Abs, 4), + /* 6e */ Instruction("ror", AddrMode.Abs, 6), + /* 6f */ Instruction("bbr6", AddrMode.Zpr, 5), + /* 70 */ Instruction("bvs", AddrMode.Rel, 2), + /* 71 */ Instruction("adc", AddrMode.IzY, 5), + /* 72 */ Instruction("adc", AddrMode.Izp, 5), + /* 73 */ Instruction("nop", AddrMode.Imp, 1), + /* 74 */ Instruction("stz", AddrMode.ZpX, 4), + /* 75 */ Instruction("adc", AddrMode.ZpX, 4), + /* 76 */ Instruction("ror", AddrMode.ZpX, 6), + /* 77 */ Instruction("rmb7", AddrMode.Zp, 5), + /* 78 */ Instruction("sei", AddrMode.Imp, 2), + /* 79 */ Instruction("adc", AddrMode.AbsY, 4), + /* 7a */ Instruction("ply", AddrMode.Imp, 2), + /* 7b */ Instruction("nop", AddrMode.Imp, 1), + /* 7c */ Instruction("jmp", AddrMode.AbsX, 4), + /* 7d */ Instruction("adc", AddrMode.AbsX, 4), + /* 7e */ Instruction("ror", AddrMode.AbsX, 7), + /* 7f */ Instruction("bbr7", AddrMode.Zpr, 5), + /* 80 */ Instruction("bra", AddrMode.Rel, 3), + /* 81 */ Instruction("sta", AddrMode.IzX, 6), + /* 82 */ Instruction("nop", AddrMode.Imm, 2), + /* 83 */ Instruction("nop", AddrMode.Imp, 1), + /* 84 */ Instruction("sty", AddrMode.Zp, 3), + /* 85 */ Instruction("sta", AddrMode.Zp, 3), + /* 86 */ Instruction("stx", AddrMode.Zp, 3), + /* 87 */ Instruction("smb0", AddrMode.Zp, 5), + /* 88 */ Instruction("dey", AddrMode.Imp, 2), + /* 89 */ Instruction("bit", AddrMode.Imm, 2), + /* 8a */ Instruction("txa", AddrMode.Imp, 2), + /* 8b */ Instruction("nop", AddrMode.Imp, 1), + /* 8c */ Instruction("sty", AddrMode.Abs, 4), + /* 8d */ Instruction("sta", AddrMode.Abs, 4), + /* 8e */ Instruction("stx", AddrMode.Abs, 4), + /* 8f */ Instruction("bbs0", AddrMode.Zpr, 5), + /* 90 */ Instruction("bcc", AddrMode.Rel, 2), + /* 91 */ Instruction("sta", AddrMode.IzY, 6), + /* 92 */ Instruction("sta", AddrMode.Izp, 5), + /* 93 */ Instruction("nop", AddrMode.Imp, 1), + /* 94 */ Instruction("sty", AddrMode.ZpX, 4), + /* 95 */ Instruction("sta", AddrMode.ZpX, 4), + /* 96 */ Instruction("stx", AddrMode.ZpY, 4), + /* 97 */ Instruction("smb1", AddrMode.Zp, 5), + /* 98 */ Instruction("tya", AddrMode.Imp, 2), + /* 99 */ Instruction("sta", AddrMode.AbsY, 5), + /* 9a */ Instruction("txs", AddrMode.Imp, 2), + /* 9b */ Instruction("nop", AddrMode.Imp, 1), + /* 9c */ Instruction("stz", AddrMode.Abs, 4), + /* 9d */ Instruction("sta", AddrMode.AbsX, 5), + /* 9e */ Instruction("stz", AddrMode.AbsX, 5), + /* 9f */ Instruction("bbs1", AddrMode.Zpr, 5), + /* a0 */ Instruction("ldy", AddrMode.Imm, 2), + /* a1 */ Instruction("lda", AddrMode.IzX, 6), + /* a2 */ Instruction("ldx", AddrMode.Imm, 2), + /* a3 */ Instruction("nop", AddrMode.Imp, 1), + /* a4 */ Instruction("ldy", AddrMode.Zp, 3), + /* a5 */ Instruction("lda", AddrMode.Zp, 3), + /* a6 */ Instruction("ldx", AddrMode.Zp, 3), + /* a7 */ Instruction("smb2", AddrMode.Zp, 5), + /* a8 */ Instruction("tay", AddrMode.Imp, 2), + /* a9 */ Instruction("lda", AddrMode.Imm, 2), + /* aa */ Instruction("tax", AddrMode.Imp, 2), + /* ab */ Instruction("nop", AddrMode.Imp, 1), + /* ac */ Instruction("ldy", AddrMode.Abs, 4), + /* ad */ Instruction("lda", AddrMode.Abs, 4), + /* ae */ Instruction("ldx", AddrMode.Abs, 4), + /* af */ Instruction("bbs2", AddrMode.Zpr, 5), + /* b0 */ Instruction("bcs", AddrMode.Rel, 2), + /* b1 */ Instruction("lda", AddrMode.IzY, 5), + /* b2 */ Instruction("lda", AddrMode.Izp, 5), + /* b3 */ Instruction("nop", AddrMode.Imp, 1), + /* b4 */ Instruction("ldy", AddrMode.ZpX, 4), + /* b5 */ Instruction("lda", AddrMode.ZpX, 4), + /* b6 */ Instruction("ldx", AddrMode.ZpY, 4), + /* b7 */ Instruction("smb3", AddrMode.Zp, 5), + /* b8 */ Instruction("clv", AddrMode.Imp, 2), + /* b9 */ Instruction("lda", AddrMode.AbsY, 4), + /* ba */ Instruction("tsx", AddrMode.Imp, 2), + /* bb */ Instruction("nop", AddrMode.Imp, 1), + /* bc */ Instruction("ldy", AddrMode.AbsX, 4), + /* bd */ Instruction("lda", AddrMode.AbsX, 4), + /* be */ Instruction("ldx", AddrMode.AbsY, 4), + /* bf */ Instruction("bbs3", AddrMode.Zpr, 5), + /* c0 */ Instruction("cpy", AddrMode.Imm, 2), + /* c1 */ Instruction("cmp", AddrMode.IzX, 6), + /* c2 */ Instruction("nop", AddrMode.Imm, 2), + /* c3 */ Instruction("nop", AddrMode.Imp, 1), + /* c4 */ Instruction("cpy", AddrMode.Zp, 3), + /* c5 */ Instruction("cmp", AddrMode.Zp, 3), + /* c6 */ Instruction("dec", AddrMode.Zp, 5), + /* c7 */ Instruction("smb4", AddrMode.Zp, 5), + /* c8 */ Instruction("iny", AddrMode.Imp, 2), + /* c9 */ Instruction("cmp", AddrMode.Imm, 2), + /* ca */ Instruction("dex", AddrMode.Imp, 2), + /* cb */ Instruction("wai", AddrMode.Imp, 3), + /* cc */ Instruction("cpy", AddrMode.Abs, 4), + /* cd */ Instruction("cmp", AddrMode.Abs, 4), + /* ce */ Instruction("dec", AddrMode.Abs, 6), + /* cf */ Instruction("bbs4", AddrMode.Zpr, 5), + /* d0 */ Instruction("bne", AddrMode.Rel, 2), + /* d1 */ Instruction("cmp", AddrMode.IzY, 5), + /* d2 */ Instruction("cmp", AddrMode.Izp, 5), + /* d3 */ Instruction("nop", AddrMode.Imp, 1), + /* d4 */ Instruction("nop", AddrMode.ZpX, 4), + /* d5 */ Instruction("cmp", AddrMode.ZpX, 4), + /* d6 */ Instruction("dec", AddrMode.ZpX, 6), + /* d7 */ Instruction("smb5", AddrMode.Zp, 5), + /* d8 */ Instruction("cld", AddrMode.Imp, 2), + /* d9 */ Instruction("cmp", AddrMode.AbsY, 4), + /* da */ Instruction("phx", AddrMode.Imp, 3), + /* db */ Instruction("stp", AddrMode.Imp, 3), + /* dc */ Instruction("nop", AddrMode.Abs, 4), + /* dd */ Instruction("cmp", AddrMode.AbsX, 4), + /* de */ Instruction("dec", AddrMode.AbsX, 7), + /* df */ Instruction("bbs5", AddrMode.Zpr, 5), + /* e0 */ Instruction("cpx", AddrMode.Imm, 2), + /* e1 */ Instruction("sbc", AddrMode.IzX, 6), + /* e2 */ Instruction("nop", AddrMode.Imm, 2), + /* e3 */ Instruction("nop", AddrMode.Imp, 1), + /* e4 */ Instruction("cpx", AddrMode.Zp, 3), + /* e5 */ Instruction("sbc", AddrMode.Zp, 3), + /* e6 */ Instruction("inc", AddrMode.Zp, 5), + /* e7 */ Instruction("smb6", AddrMode.Zp, 5), + /* e8 */ Instruction("inx", AddrMode.Imp, 2), + /* e9 */ Instruction("sbc", AddrMode.Imm, 2), + /* ea */ Instruction("nop", AddrMode.Imp, 2), + /* eb */ Instruction("nop", AddrMode.Imp, 1), + /* ec */ Instruction("cpx", AddrMode.Abs, 4), + /* ed */ Instruction("sbc", AddrMode.Abs, 4), + /* ee */ Instruction("inc", AddrMode.Abs, 6), + /* ef */ Instruction("bbs6", AddrMode.Zpr, 5), + /* f0 */ Instruction("beq", AddrMode.Rel, 2), + /* f1 */ Instruction("sbc", AddrMode.IzY, 5), + /* f2 */ Instruction("sbc", AddrMode.Izp, 5), + /* f3 */ Instruction("nop", AddrMode.Imp, 1), + /* f4 */ Instruction("nop", AddrMode.ZpX, 4), + /* f5 */ Instruction("sbc", AddrMode.ZpX, 4), + /* f6 */ Instruction("inc", AddrMode.ZpX, 6), + /* f7 */ Instruction("smb7", AddrMode.Zp, 5), + /* f8 */ Instruction("sed", AddrMode.Imp, 2), + /* f9 */ Instruction("sbc", AddrMode.AbsY, 4), + /* fa */ Instruction("plx", AddrMode.Imp, 4), + /* fb */ Instruction("nop", AddrMode.Imp, 1), + /* fc */ Instruction("nop", AddrMode.AbsX, 4), + /* fd */ Instruction("sbc", AddrMode.AbsX, 4), + /* fe */ Instruction("inc", AddrMode.AbsX, 7), + /* ff */ Instruction("bbs7", AddrMode.Zpr, 5) + ).toTypedArray() + } + + override fun iBrk() { + // handle BRK ('software interrupt') or a real hardware IRQ + val interrupt = pendingInterrupt + val nmi = interrupt?.first == true + if (interrupt != null) { + pushStackAddr(PC - 1) + } else { + PC++ + pushStackAddr(PC) + } + Status.B = interrupt == null + pushStack(Status) + Status.I = true // interrupts are now disabled + Status.D = false // this is different from NMOS 6502 + PC = readWord(if (nmi) Cpu6502.NMI_vector else Cpu6502.IRQ_vector) + pendingInterrupt = null + } + + // TODO some opcodes gained a new addressing mode that we have to deal with + + override fun iDec() { + if(currentInstruction.mode==AddrMode.Acc) { + TODO("dec A") +// Status.Z = data == 0 +// Status.N = (data and 0b10000000) != 0 + } else super.iDec() + } + + override fun iInc() { + if(currentInstruction.mode==AddrMode.Acc) { + TODO("inc A") +// Status.Z = data == 0 +// Status.N = (data and 0b10000000) != 0 + } else super.iInc() + } + private fun iBra() { - TODO("bra") + // unconditional branch + PC = fetchedAddress } private fun iTrb() { @@ -330,17 +656,15 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { } private fun iStz() { - TODO("stz") + write(fetchedAddress, 0) } private fun iWai() { waiting = Wait.Waiting - PC-- } private fun iStp() { waiting = Wait.Stopped - PC-- } private fun iPhx() { @@ -363,38 +687,38 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { Status.N = (Y and 0b10000000) != 0 } - private fun iBrr0() { + private fun iBbr0() { TODO("brr0") val x = hexB(2) val y = hexW(2) val z = hexB(3.toShort()) } - private fun iBrr1() { + private fun iBbr1() { TODO("brr1") } - private fun iBrr2() { + private fun iBbr2() { TODO("brr2") } - private fun iBrr3() { + private fun iBbr3() { TODO("brr3") } - private fun iBrr4() { + private fun iBbr4() { TODO("brr4") } - private fun iBrr5() { + private fun iBbr5() { TODO("brr5") } - private fun iBrr6() { + private fun iBbr6() { TODO("brr6") } - private fun iBrr7() { + private fun iBbr7() { TODO("brr7") } @@ -443,7 +767,7 @@ class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) { } private fun iSmb3() { - TODO("sm30") + TODO("smb3") } private fun iSmb4() { diff --git a/src/test/kotlin/Test65C02.kt b/src/test/kotlin/Test65C02.kt index fd38c26..0fbceec 100644 --- a/src/test/kotlin/Test65C02.kt +++ b/src/test/kotlin/Test65C02.kt @@ -65,7 +65,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertFalse(mpu.Status.C) assertFalse(mpu.Status.N) @@ -83,7 +83,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x01, mpu.A) assertFalse(mpu.Status.N) assertFalse(mpu.Status.Z) @@ -100,7 +100,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0xFE mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0xFF, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.C) @@ -117,7 +117,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x01, mpu.A) assertTrue(mpu.Status.C) assertFalse(mpu.Status.N) @@ -212,7 +212,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertTrue(mpu.Status.Z) assertFalse(mpu.Status.N) @@ -228,7 +228,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0xAA mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0xAA, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.Z) @@ -246,7 +246,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertTrue(mpu.Status.N) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -260,7 +260,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertFalse(mpu.Status.N) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -274,7 +274,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertTrue(mpu.Status.V) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -288,7 +288,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertFalse(mpu.Status.V) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -304,7 +304,7 @@ class Test65C02 : TestCommon6502() { assertTrue(mpu.Status.Z) assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0xFEED]) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -320,7 +320,7 @@ class Test65C02 : TestCommon6502() { assertFalse(mpu.Status.Z) // result of AND is non-zero assertEquals(0x01, mpu.A) assertEquals(0x01, memory[0xFEED]) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -336,7 +336,7 @@ class Test65C02 : TestCommon6502() { assertTrue(mpu.Status.Z) // result of AND is zero assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0xFEED]) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x0003, mpu.PC) } @@ -353,7 +353,7 @@ class Test65C02 : TestCommon6502() { assertTrue(mpu.Status.N) assertTrue(mpu.Status.V) assertEquals(0x00, mpu.A) - assertEquals(2, mpu.totalCycles) + assertEquals(2 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x02, mpu.PC) } @@ -366,7 +366,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertTrue(mpu.Status.Z) assertEquals(0x01, mpu.A) - assertEquals(2, mpu.totalCycles) + assertEquals(2 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x02, mpu.PC) } @@ -379,7 +379,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertFalse(mpu.Status.Z) // result of AND is non-zero assertEquals(0x01, mpu.A) - assertEquals(2, mpu.totalCycles) + assertEquals(2 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x02, mpu.PC) } @@ -392,7 +392,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertTrue(mpu.Status.Z) // result of AND is zero assertEquals(0x01, mpu.A) - assertEquals(2, mpu.totalCycles) + assertEquals(2 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x02, mpu.PC) } @@ -408,7 +408,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertTrue(mpu.Status.N) } @@ -422,7 +422,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertFalse(mpu.Status.N) } @@ -436,7 +436,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertTrue(mpu.Status.V) } @@ -450,7 +450,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertFalse(mpu.Status.V) } @@ -465,7 +465,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertTrue(mpu.Status.Z) assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0x0010 + mpu.X]) } @@ -481,7 +481,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertFalse(mpu.Status.Z) // result of AND is non-zero assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x01, mpu.A) assertEquals(0x01, memory[0x0010 + mpu.X]) } @@ -496,7 +496,7 @@ class Test65C02 : TestCommon6502() { mpu.A = 0x01 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertTrue(mpu.Status.Z) // result of AND is zero assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0x0010 + mpu.X]) @@ -527,7 +527,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x42 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x42, mpu.A) assertTrue(mpu.Status.Z) assertFalse(mpu.Status.N) @@ -543,7 +543,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x42 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x43, mpu.A) assertFalse(mpu.Status.Z) assertFalse(mpu.Status.N) @@ -561,7 +561,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertEquals(0xFF, memory[0xABCD]) assertTrue(mpu.Status.Z) @@ -577,7 +577,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0xFF, mpu.A) assertEquals(0xFF, memory[0xABCD]) assertTrue(mpu.Status.N) @@ -628,7 +628,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0, listOf(0x6c, 0xFF, 0x10)) mpu.step() assertEquals(0xABCD, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // JMP Indirect Absolute X-Indexed @@ -642,7 +642,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0xABCF, listOf(0x34, 0x12)) mpu.step() assertEquals(0x1234, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // LDA Zero Page, Indirect @@ -657,7 +657,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x80 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x80, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.Z) @@ -673,7 +673,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertTrue(mpu.Status.Z) assertFalse(mpu.Status.N) @@ -694,7 +694,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertTrue(mpu.Status.Z) } @@ -710,7 +710,7 @@ class Test65C02 : TestCommon6502() { memory[0xABCD] = 0x82 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x83, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.Z) @@ -721,6 +721,7 @@ class Test65C02 : TestCommon6502() { @Test fun test_phx_pushes_x_and_updates_sp() { mpu.X = 0xAB + mpu.SP = 0xff // $0000 PHX memory[0x0000] = 0xDA mpu.step() @@ -728,7 +729,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xAB, mpu.X) assertEquals(0xAB, memory[0x01FF]) assertEquals(0xFE, mpu.SP) - assertEquals(3, mpu.totalCycles) + assertEquals(3 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // PHY @@ -736,6 +737,7 @@ class Test65C02 : TestCommon6502() { @Test fun test_phy_pushes_y_and_updates_sp() { mpu.Y = 0xAB + mpu.SP = 0xff // $0000 PHY memory[0x0000] = 0x5A mpu.step() @@ -743,7 +745,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xAB, mpu.Y) assertEquals(0xAB, memory[0x01FF]) assertEquals(0xFE, mpu.SP) - assertEquals(3, mpu.totalCycles) + assertEquals(3 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // PLX @@ -758,7 +760,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x0001, mpu.PC) assertEquals(0xAB, mpu.X) assertEquals(0xFF, mpu.SP) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // PLY @@ -773,7 +775,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x0001, mpu.PC) assertEquals(0xAB, mpu.Y) assertEquals(0xFF, mpu.SP) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // RMB0 @@ -785,7 +787,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x07, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11111110 assertEquals(expected, memory[0x0043].toInt()) } @@ -810,7 +812,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x17, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11111101 assertEquals(expected, memory[0x0043].toInt()) } @@ -835,7 +837,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x27, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11111011 assertEquals(expected, memory[0x0043].toInt()) @@ -861,7 +863,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x37, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11110111 assertEquals(expected, memory[0x0043].toInt()) } @@ -886,7 +888,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x47, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11101111 assertEquals(expected, memory[0x0043].toInt()) } @@ -911,7 +913,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x57, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b11011111 assertEquals(expected, memory[0x0043].toInt()) } @@ -936,7 +938,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x67, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b10111111 assertEquals(expected, memory[0x0043].toInt()) } @@ -961,7 +963,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x77, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b01111111 assertEquals(expected, memory[0x0043].toInt()) @@ -992,7 +994,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0xFF, memory[0xFEED]) assertEquals(0xFF, mpu.A) assertEquals(flags, mpu.Status.asByte().toInt()) @@ -1010,7 +1012,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, memory[0xFEED]) assertEquals(0x00, mpu.A) assertEquals(flags, mpu.Status.asByte().toInt()) @@ -1025,7 +1027,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x87, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5, mpu.totalCycles.toInt()) val expected = 0b00000001 assertEquals(expected, memory[0x0043].toInt()) } @@ -1050,7 +1052,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x97, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b00000010 assertEquals(expected, memory[0x0043].toInt()) } @@ -1075,7 +1077,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xA7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b00000100 assertEquals(expected, memory[0x0043].toInt()) @@ -1101,7 +1103,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xB7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b00001000 assertEquals(expected, memory[0x0043].toInt()) @@ -1127,7 +1129,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xC7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b00010000 assertEquals(expected, memory[0x0043].toInt()) @@ -1153,7 +1155,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xD7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b00100000 assertEquals(expected, memory[0x0043].toInt()) } @@ -1178,7 +1180,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xE7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b01000000 assertEquals(expected, memory[0x0043].toInt()) } @@ -1203,7 +1205,7 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0xF7, 0x43)) mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) val expected = 0b10000000 assertEquals(expected, memory[0x0043].toInt()) } @@ -1233,7 +1235,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertFalse(mpu.Status.N) assertTrue(mpu.Status.C) @@ -1252,7 +1254,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0x01 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertFalse(mpu.Status.N) assertTrue(mpu.Status.C) @@ -1271,7 +1273,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0x00 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x00, mpu.A) assertFalse(mpu.Status.N) assertTrue(mpu.Status.C) @@ -1290,7 +1292,7 @@ class Test65C02 : TestCommon6502() { memory[0xFEED] = 0x02 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) assertEquals(0x04, mpu.A) assertFalse(mpu.Status.N) assertFalse(mpu.Status.Z) @@ -1309,7 +1311,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertEquals(0x00, memory[0x0032]) assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // STZ Zero Page, X-Indexed @@ -1324,7 +1326,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertEquals(0x00, memory[0x0032]) assertEquals(0x0002, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // STZ Absolute @@ -1338,7 +1340,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertEquals(0x00, memory[0xFEED]) assertEquals(0x0003, mpu.PC) - assertEquals(4, mpu.totalCycles) + assertEquals(4 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // STZ Absolute, X-Indexed @@ -1354,7 +1356,7 @@ class Test65C02 : TestCommon6502() { mpu.step() assertEquals(0x00, memory[0xFEED]) assertEquals(0x0003, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // TSB Zero Page @@ -1370,7 +1372,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xF0, memory[0x00BB]) assertFalse(mpu.Status.Z) assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test @@ -1384,7 +1386,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xE0, memory[0x00BB]) assertTrue(mpu.Status.Z) assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // TSB Absolute @@ -1400,7 +1402,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xF0, memory[0xFEED]) assertFalse(mpu.Status.Z) assertEquals(0x0003, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test @@ -1414,7 +1416,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0xE0, memory[0xFEED]) assertTrue(mpu.Status.Z) assertEquals(0x0003, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // TRB Zero Page @@ -1430,7 +1432,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x80, memory[0x00BB]) assertFalse(mpu.Status.Z) assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test @@ -1444,7 +1446,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x80, memory[0x00BB]) assertTrue(mpu.Status.Z) assertEquals(0x0002, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } // TRB Absolute @@ -1460,7 +1462,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x80, memory[0xFEED]) assertFalse(mpu.Status.Z) assertEquals(0x0003, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test @@ -1474,7 +1476,7 @@ class Test65C02 : TestCommon6502() { assertEquals(0x80, memory[0xFEED]) assertTrue(mpu.Status.Z) assertEquals(0x0003, mpu.PC) - assertEquals(6, mpu.totalCycles) + assertEquals(6 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test @@ -1516,17 +1518,17 @@ class Test65C02 : TestCommon6502() { writeMem(memory, 0x0000, listOf(0x80, 0x10)) mpu.step() assertEquals(0x12, mpu.PC) - assertEquals(2, mpu.totalCycles) + assertEquals(2 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) } @Test fun test_bra_backward() { // $0240 BRA $F0 - writeMem(memory, 0x0000, listOf(0x80, 0xF0)) + writeMem(memory, 0x0204, listOf(0x80, 0xF0)) mpu.PC = 0x0204 mpu.step() assertEquals(0x1F6, mpu.PC) - assertEquals(3, mpu.totalCycles) // Crossed boundry + assertEquals(3 + Cpu65C02.resetCycles, mpu.totalCycles.toInt()) // Crossed boundry } // WAI