From 900c2aea2373df059effc48cace9e8ff0561bfa1 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 5 Sep 2019 01:26:01 +0200 Subject: [PATCH] fixed all instructions except BCD arithmetic --- sim65/src/components/Cpu6502.kt | 177 ++++++++++++++------------------ sim65/src/components/Ram.kt | 4 + sim65/test/Test6502.kt | 3 +- sim65/test/TestCommon6502.kt | 106 ++++++++++--------- 4 files changed, 135 insertions(+), 155 deletions(-) diff --git a/sim65/src/components/Cpu6502.kt b/sim65/src/components/Cpu6502.kt index 961e73adb..7bc30e9cb 100644 --- a/sim65/src/components/Cpu6502.kt +++ b/sim65/src/components/Cpu6502.kt @@ -17,8 +17,7 @@ interface ICpu { } // TODO: add additional cycles to certain instructions and addressing modes -// TODO: test all opcodes and fix bugs - +// TODO: fix sbc and adc with BCD arithmetic. class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu { override var tracing: Boolean = false @@ -29,6 +28,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu const val NMI_vector = 0xfffa const val RESET_vector = 0xfffc const val IRQ_vector = 0xfffe + const val resetCycles = 8 fun hexW(number: Address, allowSingleByte: Boolean = false): String { val msb = number ushr 8 @@ -241,12 +241,12 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu Y = 0 Status.C = false Status.Z = false - Status.I = false + Status.I = true Status.D = false Status.B = false Status.V = false Status.N = false - instrCycles = 8 + instrCycles = resetCycles // a reset takes time as well currentOpcode = 0 currentInstruction = opcodes[0] waiting = false @@ -276,8 +276,9 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu override fun step() { // step a whole instruction - while(instrCycles>0) clock() // instruction subcycles + while(instrCycles>0) clock() // remaining instruction subcycles from the previous instruction clock() // the actual instruction execution cycle + while(instrCycles>0) clock() // instruction subcycles } fun printState() { @@ -324,7 +325,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun amRel() { - val relative = readPc().toByte() + val relative = readPc() fetchedAddress = if (relative >= 0x80) PC - (256 - relative) else @@ -368,9 +369,9 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu private fun amIzx() { // note: not able to fetch an adress which crosses the page boundary - fetchedAddress = readPc() + X - val lo = read(fetchedAddress) - val hi = read((fetchedAddress + 1) and 255) + fetchedAddress = readPc() + val lo = read((fetchedAddress + X) and 255) + val hi = read((fetchedAddress + X + 1) and 255) fetchedAddress = lo or (hi shl 8) } @@ -379,7 +380,16 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu fetchedAddress = readPc() val lo = read(fetchedAddress) val hi = read((fetchedAddress + 1) and 255) - fetchedAddress = Y + (lo or (hi shl 8)) + fetchedAddress = (Y + lo or (hi shl 8)) and 65535 + } + + private fun getFetched(): Int { + return if(currentInstruction.mode==AddrMode.Imm || + currentInstruction.mode==AddrMode.Acc || + currentInstruction.mode==AddrMode.Imp) + fetchedData + else + read(fetchedAddress) } private fun readPc(): Int = bus.read(PC++).toInt() @@ -408,7 +418,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu private fun popStackAddr(): Address { val lo = popStack() val hi = popStack() - return lo + hi ushr 8 + return lo or (hi shl 8) } private fun read(address: Address): Int = bus.read(address).toInt() @@ -683,11 +693,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu // official instructions private fun iAdc() { - val operand = if (currentInstruction.mode == AddrMode.Imm) { - fetchedData - } else { - read(fetchedAddress) - } + val operand = getFetched() if (Status.D) { // BCD add var lo = (A and 0x0f) + (operand and 0x0f) + if (Status.C) 1 else 0 @@ -712,24 +718,24 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iAnd() { - A = A and fetchedData + A = A and getFetched() Status.Z = A == 0 Status.N = (A and 0b10000000) != 0 } private fun iAsl() { if (currentInstruction.mode == AddrMode.Acc) { - Status.C = (A and 0b10000000) == 1 + Status.C = (A and 0b10000000) != 0 A = (A shl 1) and 255 Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) - Status.C = (data and 0b10000000) == 1 + Status.C = (data and 0b10000000) != 0 val shifted = (data shl 1) and 255 write(fetchedAddress, shifted) Status.Z = shifted == 0 - Status.N = (shifted and 0b10000000) == 1 + Status.N = (shifted and 0b10000000) != 0 } } @@ -746,9 +752,10 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iBit() { - Status.Z = (A and fetchedData) == 0 - Status.V = (fetchedData and 0b01000000) != 0 - Status.N = (fetchedData and 0b10000000) != 0 + val operand = getFetched() + Status.Z = (A and operand) == 0 + Status.V = (operand and 0b01000000) != 0 + Status.N = (operand and 0b10000000) != 0 } private fun iBmi() { @@ -765,11 +772,10 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu private fun iBrk() { PC++ - Status.I = true - Status.B = true pushStackAddr(PC) + Status.B = true pushStack(Status) - Status.B = false + Status.I = true PC = readWord(IRQ_vector) } @@ -798,87 +804,68 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iCmp() { - val fetched = - if (currentInstruction.mode == AddrMode.Imm) { - fetchedData - } else { - read(fetchedAddress) - } + val fetched = getFetched() Status.C = A >= fetched Status.Z = A == fetched - Status.N = ((A - fetched) and 0b10000000) == 1 + Status.N = ((A - fetched) and 0b10000000) != 0 } private fun iCpx() { - val fetched = - if (currentInstruction.mode == AddrMode.Imm) { - fetchedData - } else { - read(fetchedAddress) - } + val fetched = getFetched() Status.C = X >= fetched Status.Z = X == fetched - Status.N = ((X - fetched) and 0b10000000) == 1 + Status.N = ((X - fetched) and 0b10000000) != 0 } private fun iCpy() { - val fetched = - if (currentInstruction.mode == AddrMode.Imm) { - fetchedData - } else { - read(fetchedAddress) - } + val fetched = getFetched() Status.C = Y >= fetched Status.Z = Y == fetched - Status.N = ((Y - fetched) and 0b10000000) == 1 + Status.N = ((Y - fetched) and 0b10000000) != 0 } private fun iDec() { val data = (read(fetchedAddress) - 1) and 255 write(fetchedAddress, data) Status.Z = data == 0 - Status.N = (data and 0b10000000) == 1 + Status.N = (data and 0b10000000) != 0 } private fun iDex() { X = (X - 1) and 255 Status.Z = X == 0 - Status.N = (X and 0b10000000) == 1 + Status.N = (X and 0b10000000) != 0 } private fun iDey() { Y = (Y - 1) and 255 Status.Z = Y == 0 - Status.N = (Y and 0b10000000) == 1 + Status.N = (Y and 0b10000000) != 0 } private fun iEor() { - A = if (currentInstruction.mode == AddrMode.Imm) { - A xor fetchedData - } else { - A xor read(fetchedAddress) - } + A = A xor getFetched() Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } private fun iInc() { val data = (read(fetchedAddress) + 1) and 255 write(fetchedAddress, data) Status.Z = data == 0 - Status.N = (data and 0b10000000) == 1 + Status.N = (data and 0b10000000) != 0 } private fun iInx() { X = (X + 1) and 255 Status.Z = X == 0 - Status.N = (X and 0b10000000) == 1 + Status.N = (X and 0b10000000) != 0 } private fun iIny() { Y = (Y + 1) and 255 Status.Z = Y == 0 - Status.N = (Y and 0b10000000) == 1 + Status.N = (Y and 0b10000000) != 0 } private fun iJmp() { @@ -886,35 +873,26 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iJsr() { - pushStackAddr(PC) + pushStackAddr(PC-1) PC = fetchedAddress } private fun iLda() { - A = if (currentInstruction.mode == AddrMode.Imm) - fetchedData - else - read(fetchedAddress) + A = getFetched() Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } private fun iLdx() { - X = if (currentInstruction.mode == AddrMode.Imm) - fetchedData - else - read(fetchedAddress) + X = getFetched() Status.Z = X == 0 - Status.N = (X and 0b10000000) == 1 + Status.N = (X and 0b10000000) != 0 } private fun iLdy() { - Y = if (currentInstruction.mode == AddrMode.Imm) - fetchedData - else - read(fetchedAddress) + Y = getFetched() Status.Z = Y == 0 - Status.N = (Y and 0b10000000) == 1 + Status.N = (Y and 0b10000000) != 0 } private fun iLsr() { @@ -922,26 +900,23 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu Status.C = (A and 1) == 1 A = A ushr 1 Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) Status.C = (data and 1) == 1 val shifted = data ushr 1 write(fetchedAddress, shifted) Status.Z = shifted == 0 - Status.N = (shifted and 0b10000000) == 1 + Status.N = (shifted and 0b10000000) != 0 } } private fun iNop() {} private fun iOra() { - A = if (currentInstruction.mode == AddrMode.Imm) - A or fetchedData - else - A or read(fetchedAddress) + A = A or getFetched() Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } private fun iPha() { @@ -949,33 +924,37 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iPhp() { + val origBreakflag = Status.B + Status.B = true pushStack(Status) + Status.B = origBreakflag } private fun iPla() { A = popStack() Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } private fun iPlp() { Status.fromByte(popStack()) + Status.B = true // break is always 1 except when pushing on stack } private fun iRol() { val oldCarry = Status.C if (currentInstruction.mode == AddrMode.Acc) { - Status.C = (A and 0b10000000) == 1 - A = (A shl 1) or (if (oldCarry) 1 else 0) + Status.C = (A and 0b10000000) != 0 + A = (A shl 1 and 255) or (if (oldCarry) 1 else 0) Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) - Status.C = (data and 0b10000000) == 1 - val shifted = (data shl 1) or (if (oldCarry) 1 else 0) and 255 + Status.C = (data and 0b10000000) != 0 + val shifted = (data shl 1 and 255) or (if (oldCarry) 1 else 0) write(fetchedAddress, shifted) Status.Z = shifted == 0 - Status.N = (shifted and 0b10000000) == 1 + Status.N = (shifted and 0b10000000) != 0 } } @@ -985,38 +964,36 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu Status.C = (A and 1) == 1 A = (A ushr 1) or (if (oldCarry) 0b10000000 else 0) Status.Z = A == 0 - Status.N = (A and 0b10000000) == 1 + Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) Status.C = (data and 1) == 1 val shifted = (data ushr 1) or (if (oldCarry) 0b10000000 else 0) write(fetchedAddress, shifted) Status.Z = shifted == 0 - Status.N = (shifted and 0b10000000) == 1 + Status.N = (shifted and 0b10000000) != 0 } } private fun iRti() { Status.fromByte(popStack()) + Status.B = true // break is always 1 except when pushing on stack PC = popStackAddr() } private fun iRts() { PC = popStackAddr() + PC = (PC+1) and 0xffff } private fun iSbc() { - val operand = if (currentInstruction.mode == AddrMode.Imm) { - fetchedData - } else { - read(fetchedAddress) - } + val operand = getFetched() if (Status.D) { var lo = (A and 0x0f) - (operand and 0x0f) - if (Status.C) 0 else 1 if (lo and 0x10 != 0) lo -= 6 var h = (A shr 4) - (operand shr 4) - if (lo and 0x10 != 0) 1 else 0 if (h and 0x10 != 0) h -= 6 - val result = lo and 0x0f or (h shl 4 and 0xff) + val result = lo and 0x0f or ((h shl 4) and 0xff) Status.C = h and 255 < 15 Status.Z = result == 0 Status.V = false // BCD never sets overflow flag @@ -1071,7 +1048,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iTsx() { - X = Status.asByte().toInt() + X = SP Status.Z = X == 0 Status.N = (X and 0b10000000) != 0 } @@ -1083,7 +1060,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iTxs() { - Status.fromByte(X) + SP = X } private fun iTya() { diff --git a/sim65/src/components/Ram.kt b/sim65/src/components/Ram.kt index 9353eba5d..bef50049d 100644 --- a/sim65/src/components/Ram.kt +++ b/sim65/src/components/Ram.kt @@ -20,6 +20,10 @@ class Ram(startAddress: Address, endAddress: Address): MemMappedComponent(startA override fun reset() { memory.fill(0) } + fun fill(data: UByte) { + memory.fill(data) + } + fun load(filename: String, address: Address) { val bytes = File(filename).readBytes() bytes.forEachIndexed { index, byte -> diff --git a/sim65/test/Test6502.kt b/sim65/test/Test6502.kt index dc095236a..4e7ab5a0d 100644 --- a/sim65/test/Test6502.kt +++ b/sim65/test/Test6502.kt @@ -1,5 +1,6 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance +import sim65.components.Cpu6502 import kotlin.test.* @@ -274,7 +275,7 @@ class Test6502 : TestCommon6502() { writeMem(memory, 0, listOf(0x6c, 0xff, 0x00)) mpu.step() assertEquals(0x6c00, mpu.PC) - assertEquals(5, mpu.totalCycles) + assertEquals(5+Cpu6502.resetCycles, mpu.totalCycles) } // ORA Indexed, Indirect (Y) diff --git a/sim65/test/TestCommon6502.kt b/sim65/test/TestCommon6502.kt index 8aff7ba45..fcd1b96a6 100644 --- a/sim65/test/TestCommon6502.kt +++ b/sim65/test/TestCommon6502.kt @@ -52,7 +52,11 @@ abstract class TestCommon6502 { init { bus.add(mpu) bus.add(memory) + memory.fill(0xaa) + memory.write(Cpu6502.RESET_vector, 0) + memory.write(Cpu6502.RESET_vector+1, 0) mpu.reset() + mpu.Status.I = false // allow interrupts again } companion object { @@ -79,11 +83,11 @@ abstract class TestCommon6502 { fun test_reset_sets_registers_to_initial_states() { mpu.reset() - assertEquals(0xFF, mpu.SP) + assertEquals(0xFD, mpu.SP) assertEquals(0, mpu.A) assertEquals(0, mpu.X) assertEquals(0, mpu.Y) - assertEquals(Cpu6502.StatusRegister(C = false, Z = false, I = false, D = false, B = true, V = false, N = false), mpu.Status) + assertTrue(mpu.Status.I) // the other status flags are undefined after reset } // ADC Absolute @@ -1339,11 +1343,10 @@ abstract class TestCommon6502 { assertTrue(mpu.Status.N) assertTrue(mpu.Status.V) assertFalse(mpu.Status.Z) - - // AND (Absolute) - } + // AND (Absolute) + @Test fun test_and_absolute_all_zeros_setting_zero_flag() { @@ -1371,11 +1374,10 @@ abstract class TestCommon6502 { assertEquals(0xAA, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.Z) - - // AND (Absolute) - } + // AND (Absolute) + @Test fun test_and_zp_all_zeros_setting_zero_flag() { @@ -1490,7 +1492,6 @@ abstract class TestCommon6502 { @Test fun test_and_abs_y_zeros_and_ones_setting_negative_flag() { - mpu.A = 0xFF mpu.Y = 0x03 // $0000 AND $ABCD,X @@ -1501,11 +1502,10 @@ abstract class TestCommon6502 { assertEquals(0xAA, mpu.A) assertTrue(mpu.Status.N) assertFalse(mpu.Status.Z) - - // AND Indirect, Indexed (X) - } + // AND Indirect, Indexed (X) + @Test fun test_and_ind_indexed_x_all_zeros_setting_zero_flag() { @@ -1950,11 +1950,11 @@ abstract class TestCommon6502 { mpu.Status.C = false mpu.PC = 0x0050 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 // $0000 BCC -6 writeMem(memory, 0x0050, listOf(0x90, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -1987,11 +1987,11 @@ abstract class TestCommon6502 { mpu.Status.C = true mpu.PC = 0x0050 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 // $0000 BCS -6 writeMem(memory, 0x0050, listOf(0xB0, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -2024,11 +2024,11 @@ abstract class TestCommon6502 { mpu.Status.Z = true mpu.PC = 0x0050 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 // $0000 BEQ -6 writeMem(memory, 0x0050, listOf(0xF0, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -2154,7 +2154,7 @@ abstract class TestCommon6502 { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertTrue(mpu.Status.N) } @@ -2169,7 +2169,7 @@ abstract class TestCommon6502 { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertFalse(mpu.Status.N) } @@ -2184,7 +2184,7 @@ abstract class TestCommon6502 { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertTrue(mpu.Status.V) } @@ -2199,7 +2199,7 @@ abstract class TestCommon6502 { mpu.A = 0xFF mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertFalse(mpu.Status.V) } @@ -2214,7 +2214,7 @@ abstract class TestCommon6502 { mpu.A = 0x01 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertTrue(mpu.Status.Z) assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0x0010]) @@ -2231,7 +2231,7 @@ abstract class TestCommon6502 { mpu.A = 0x01 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertFalse(mpu.Status.Z) // result of AND is non-zero assertEquals(0x01, mpu.A) assertEquals(0x01, memory[0x0010]) @@ -2248,7 +2248,7 @@ abstract class TestCommon6502 { mpu.A = 0x01 mpu.step() assertEquals(0x0002, mpu.PC) - assertEquals(3, mpu.totalCycles) + assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles) assertTrue(mpu.Status.Z) // result of AND is zero assertEquals(0x01, mpu.A) assertEquals(0x00, memory[0x0010]) @@ -2274,10 +2274,10 @@ abstract class TestCommon6502 { mpu.Status.N = true mpu.PC = 0x0050 // $0000 BMI -6 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 writeMem(memory, 0x0050, listOf(0x30, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -2311,10 +2311,10 @@ abstract class TestCommon6502 { mpu.Status.Z = false mpu.PC = 0x0050 // $0050 BNE -6 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 writeMem(memory, 0x0050, listOf(0xD0, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -2348,10 +2348,10 @@ abstract class TestCommon6502 { mpu.Status.N = false mpu.PC = 0x0050 // $0050 BPL -6 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 writeMem(memory, 0x0050, listOf(0x10, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -2372,17 +2372,19 @@ abstract class TestCommon6502 { fun test_brk_pushes_pc_plus_2_and_status_then_sets_pc_to_irq_vector() { writeMem(memory, 0xFFFE, listOf(0xCD, 0xAB)) + mpu.SP = 0xff + mpu.Status.I = false + // $C000 BRK memory[0xC000] = 0x00 mpu.PC = 0xC000 mpu.step() assertEquals(0xABCD, mpu.PC) + assertEquals(0xFC, mpu.SP) assertEquals(0xC0, memory[0x1FF]) // PCH assertEquals(0x02, memory[0x1FE]) // PCL - assertEquals(fBREAK or fUNUSED, memory[0x1FD].toInt()) // Status - assertEquals(0xFC, mpu.SP) - + assertEquals(fBREAK or fUNUSED, memory[0x1FD].toInt(), "Status on stack should have no I flag") assertEquals(fBREAK or fUNUSED or fINTERRUPT, mpu.Status.asByte().toInt()) } @@ -2401,11 +2403,11 @@ abstract class TestCommon6502 { fun test_bvc_overflow_clear_branches_relative_backward() { mpu.Status.V = false mpu.PC = 0x0050 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 // $0050 BVC -6 writeMem(memory, 0x0050, listOf(0x50, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @Test @@ -2433,11 +2435,11 @@ abstract class TestCommon6502 { mpu.Status.V = true mpu.PC = 0x0050 - val rel = (0x06 xor 0xFF + 1) // two's complement of 6 + val rel = 256 + (-6) // two's complement of 6 // $0050 BVS -6 writeMem(memory, 0x0050, listOf(0x70, rel.toShort())) mpu.step() - assertEquals(0x0052 + rel, mpu.PC) + assertEquals(0x0052 - 6, mpu.PC) } @@ -3332,18 +3334,16 @@ abstract class TestCommon6502 { @Test fun test_inx_sets_negative_flag_when_incrementing_above_7F() { - mpu.X = 0x7f memory[0x0000] = 0xE8 // => INX mpu.step() assertEquals(0x0001, mpu.PC) assertEquals(0x80, mpu.X) assertTrue(mpu.Status.N) - - // INY - } + // INY + @Test fun test_iny_increments_y() { @@ -3354,7 +3354,6 @@ abstract class TestCommon6502 { assertEquals(0x0A, mpu.Y) assertFalse(mpu.Status.Z) assertFalse(mpu.Status.N) - } @Test @@ -3412,6 +3411,7 @@ abstract class TestCommon6502 { fun test_jsr_pushes_pc_plus_2_and_sets_pc() { // $C000 JSR $FFD2 + mpu.SP = 0xFF writeMem(memory, 0xC000, listOf(0x20, 0xD2, 0xFF)) mpu.PC = 0xC000 mpu.step() @@ -3419,11 +3419,10 @@ abstract class TestCommon6502 { assertEquals(0xFD, mpu.SP) assertEquals(0xC0, memory[0x01FF]) // PCH assertEquals(0x02, memory[0x01FE]) // PCL+2 - - // LDA Absolute - } + // LDA Absolute + @Test fun test_lda_absolute_loads_a_sets_n_flag() { @@ -4604,21 +4603,22 @@ abstract class TestCommon6502 { mpu.step() assertEquals(0x0001, mpu.PC) assertEquals(0xAB, mpu.A) - assertEquals(0xAB, memory[0x01FF]) - assertEquals(0xFE, mpu.SP) + assertEquals(0xFC, mpu.SP) + assertEquals(0xAB, memory[0x01FD]) } // PHP @Test fun test_php_pushes_processor_status_and_updates_sp() { for (flags in 0 until 0x100) { + mpu.reset() mpu.Status.fromByte(flags or fBREAK or fUNUSED) // $0000 PHP memory[0x0000] = 0x08 mpu.step() assertEquals(0x0001, mpu.PC) - assertEquals((flags or fBREAK or fUNUSED), memory[0x1FF].toInt()) - assertEquals(0xFE, mpu.SP) + assertEquals(0xFC, mpu.SP) + assertEquals((flags or fBREAK or fUNUSED), memory[0x1FD].toInt()) } } @@ -4684,7 +4684,6 @@ abstract class TestCommon6502 { assertEquals(0x00, mpu.A) assertTrue(mpu.Status.Z) assertFalse(mpu.Status.N) - } @Test @@ -5442,10 +5441,9 @@ abstract class TestCommon6502 { mpu.SP = 0xFC mpu.step() - assertEquals(0xC003, mpu.PC) - assertEquals(0xFC, mpu.Status.asByte()) assertEquals(0xFF, mpu.SP) - + assertEquals(0xFC, mpu.Status.asByte()) + assertEquals(0xC003, mpu.PC) } @Test