diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f4..7e1116c63 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/sim65/src/components/Cpu6502.kt b/sim65/src/components/Cpu6502.kt index ca6285f46..3517b78d8 100644 --- a/sim65/src/components/Cpu6502.kt +++ b/sim65/src/components/Cpu6502.kt @@ -34,7 +34,7 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { fun hexW(number: Address, allowSingleByte: Boolean = false): String { val msb = number ushr 8 - val lsb = number and 255 + val lsb = number and 0xff return if (msb == 0 && allowSingleByte) hexB(lsb) else @@ -332,20 +332,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { private fun amZpx() { // note: zeropage index will not leave Zp when page boundray is crossed - fetchedAddress = (readPc() + X) and 255 + fetchedAddress = (readPc() + X) and 0xff } private fun amZpy() { // note: zeropage index will not leave Zp when page boundray is crossed - fetchedAddress = (readPc() + Y) and 255 + fetchedAddress = (readPc() + Y) and 0xff } private fun amRel() { val relative = readPc() - fetchedAddress = if (relative >= 0x80) - PC - (256 - relative) - else - PC + relative + fetchedAddress = if (relative >= 0x80) { + PC - (256 - relative) and 0xffff + } else + PC + relative and 0xffff } private fun amAbs() { @@ -386,8 +386,8 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { private fun amIzx() { // note: not able to fetch an adress which crosses the page boundary fetchedAddress = readPc() - val lo = read((fetchedAddress + X) and 255) - val hi = read((fetchedAddress + X + 1) and 255) + val lo = read((fetchedAddress + X) and 0xff) + val hi = read((fetchedAddress + X + 1) and 0xff) fetchedAddress = lo or (hi shl 8) } @@ -395,23 +395,22 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { // note: not able to fetch an adress which crosses the page boundary fetchedAddress = readPc() val lo = read(fetchedAddress) - val hi = read((fetchedAddress + 1) and 255) - fetchedAddress = Y + (lo or (hi shl 8)) and 65535 + val hi = read((fetchedAddress + 1) and 0xff) + fetchedAddress = Y + (lo or (hi shl 8)) and 0xffff } - private fun getFetched(): Int { - return if (currentInstruction.mode == AddrMode.Imm || - currentInstruction.mode == AddrMode.Acc || - currentInstruction.mode == AddrMode.Imp) - fetchedData - else - read(fetchedAddress) - } + private fun getFetched() = + 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() private fun pushStackAddr(address: Address) { - val lo = address and 255 + val lo = address and 0xff val hi = (address ushr 8) pushStack(hi) pushStack(lo) @@ -717,26 +716,26 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { // and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l598 // (the implementation below is based on the code used by Vice) var tmp = (A and 0xf) + (operand and 0xf) + (if (Status.C) 1 else 0) - if (tmp > 0x9) tmp += 0x6 + if (tmp > 9) tmp += 6 tmp = if (tmp <= 0x0f) { (tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) } else { (tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) + 0x10 } - Status.Z = ((A + operand + (if (Status.C) 1 else 0)) and 0xff) == 0 - Status.N = (tmp and 0b10000000) != 0 - Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) == 0 - if (tmp > 0x90) tmp += 0x60 - Status.C = tmp > 0xf0 - A = tmp and 255 + Status.Z = A + operand + (if (Status.C) 1 else 0) and 0xff == 0 + Status.N = tmp and 0b10000000 != 0 + Status.V = (A xor tmp) and 0x80 != 0 && (A xor operand) and 0b10000000 == 0 + if (tmp and 0x1f0 > 0x90) tmp += 0x60 + Status.C = tmp > 0xf0 // original: (tmp and 0xff0) > 0xf0 + A = tmp and 0xff } else { // normal add val tmp = operand + A + if (Status.C) 1 else 0 Status.N = (tmp and 0b10000000) != 0 - Status.Z = (tmp and 255) == 0 - Status.V = ((A xor operand) and 0x80) == 0 && ((A xor tmp) and 0x80) != 0 - Status.C = tmp > 255 - A = tmp and 255 + Status.Z = (tmp and 0xff) == 0 + Status.V = (A xor operand).inv() and (A xor tmp) and 0b10000000 != 0 + Status.C = tmp > 0xff + A = tmp and 0xff } } @@ -749,13 +748,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { private fun iAsl() { if (currentInstruction.mode == AddrMode.Acc) { Status.C = (A and 0b10000000) != 0 - A = (A shl 1) and 255 + A = (A shl 1) and 0xff Status.Z = A == 0 Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) Status.C = (data and 0b10000000) != 0 - val shifted = (data shl 1) and 255 + val shifted = (data shl 1) and 0xff write(fetchedAddress, shifted) Status.Z = shifted == 0 Status.N = (shifted and 0b10000000) != 0 @@ -848,20 +847,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { } private fun iDec() { - val data = (read(fetchedAddress) - 1) and 255 + val data = (read(fetchedAddress) - 1) and 0xff write(fetchedAddress, data) Status.Z = data == 0 Status.N = (data and 0b10000000) != 0 } private fun iDex() { - X = (X - 1) and 255 + X = (X - 1) and 0xff Status.Z = X == 0 Status.N = (X and 0b10000000) != 0 } private fun iDey() { - Y = (Y - 1) and 255 + Y = (Y - 1) and 0xff Status.Z = Y == 0 Status.N = (Y and 0b10000000) != 0 } @@ -873,20 +872,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { } private fun iInc() { - val data = (read(fetchedAddress) + 1) and 255 + val data = (read(fetchedAddress) + 1) and 0xff write(fetchedAddress, data) Status.Z = data == 0 Status.N = (data and 0b10000000) != 0 } private fun iInx() { - X = (X + 1) and 255 + X = (X + 1) and 0xff Status.Z = X == 0 Status.N = (X and 0b10000000) != 0 } private fun iIny() { - Y = (Y + 1) and 255 + Y = (Y + 1) and 0xff Status.Z = Y == 0 Status.N = (Y and 0b10000000) != 0 } @@ -968,13 +967,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { val oldCarry = Status.C if (currentInstruction.mode == AddrMode.Acc) { Status.C = (A and 0b10000000) != 0 - A = (A shl 1 and 255) or (if (oldCarry) 1 else 0) + A = (A shl 1 and 0xff) or (if (oldCarry) 1 else 0) Status.Z = A == 0 Status.N = (A and 0b10000000) != 0 } else { val data = read(fetchedAddress) Status.C = (data and 0b10000000) != 0 - val shifted = (data shl 1 and 255) or (if (oldCarry) 1 else 0) + val shifted = (data shl 1 and 0xff) or (if (oldCarry) 1 else 0) write(fetchedAddress, shifted) Status.Z = shifted == 0 Status.N = (shifted and 0b10000000) != 0 @@ -1011,29 +1010,29 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { private fun iSbc() { val operand = getFetched() - val tmp = (A - operand - if (Status.C) 0 else 1) and 65535 + val tmp = (A - operand - if (Status.C) 0 else 1) and 0xffff + Status.V = (A xor operand) and (A xor tmp) and 0b10000000 != 0 if (Status.D) { // BCD subtract // see http://www.6502.org/tutorials/decimal_mode.html // and http://nesdev.com/6502.txt // and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l1396 // (the implementation below is based on the code used by Vice) - var tmpA = ((A and 0xf) - (operand and 0xf) - if (Status.C) 0 else 1) and 65535 + var tmpA = ((A and 0xf) - (operand and 0xf) - if (Status.C) 0 else 1) and 0xffff tmpA = if ((tmpA and 0x10) != 0) { ((tmpA - 6) and 0xf) or (A and 0xf0) - (operand and 0xf0) - 0x10 } else { (tmpA and 0xf) or (A and 0xf0) - (operand and 0xf0) } if ((tmpA and 0x100) != 0) tmpA -= 0x60 - A = tmpA and 255 + A = tmpA and 0xff } else { // normal subtract - A = tmp and 255 + A = tmp and 0xff } Status.C = tmp < 0x100 - Status.Z = (tmp and 255) == 0 + Status.Z = (tmp and 0xff) == 0 Status.N = (tmp and 0b10000000) != 0 - Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) != 0 } private fun iSec() { diff --git a/sim65/test/6502_functional_tests b/sim65/test/6502_functional_tests new file mode 160000 index 000000000..fe99e5616 --- /dev/null +++ b/sim65/test/6502_functional_tests @@ -0,0 +1 @@ +Subproject commit fe99e5616243a1bdbceaf5907390ce4443de7db0 diff --git a/sim65/test/Test6502Functional.kt b/sim65/test/Test6502Functional.kt new file mode 100644 index 000000000..2a41e4189 --- /dev/null +++ b/sim65/test/Test6502Functional.kt @@ -0,0 +1,29 @@ +import org.junit.jupiter.api.Test +import sim65.components.Bus +import sim65.components.Cpu6502 +import sim65.components.Ram +import kotlin.test.assertEquals + +class Test6502Functional { + + @Test + fun testFunctional() { + val cpu = Cpu6502(false) + val bus = Bus() + val ram = Ram(0, 0xffff) + ram.load("test/6502_functional_tests/bin_files/6502_functional_test.bin", 0) + bus.add(cpu) + bus.add(ram) + cpu.reset() + cpu.PC = 0x0400 + + while(cpu.totalCycles < 50000000) { + cpu.clock() + } + + cpu.printState() + val d = cpu.disassemble(ram, cpu.PC-20, cpu.PC+20) + println(d.joinToString ("\n")) + } + +} diff --git a/sim65/test/Test6502TestSuite.kt b/sim65/test/Test6502TestSuite.kt index 3bcb6332a..80de88cb0 100644 --- a/sim65/test/Test6502TestSuite.kt +++ b/sim65/test/Test6502TestSuite.kt @@ -23,18 +23,24 @@ class Test6502TestSuite { // create the system bus and add device to it. // note that the order is relevant w.r.t. where reads and writes are going. - ram.set(0x02, 0) - ram.set(0xa002, 0) - ram.set(0xa003, 0x80) - ram.set(Cpu6502.IRQ_vector, 0x48) - ram.set(Cpu6502.IRQ_vector + 1, 0xff) - ram.set(Cpu6502.RESET_vector, 0x01) - ram.set(Cpu6502.RESET_vector + 1, 0x08) - ram.set(0x01fe, 0xff) - ram.set(0x01ff, 0x7f) - ram.set(0x8000, 2) - ram.set(0xa474, 2) + ram[0x02] = 0 + ram[0xa002] = 0 + ram[0xa003] = 0x80 + ram[Cpu6502.IRQ_vector] = 0x48 + ram[Cpu6502.IRQ_vector + 1] = 0xff + ram[Cpu6502.RESET_vector] = 0x01 + ram[Cpu6502.RESET_vector + 1] = 0x08 + ram[0x01fe] = 0xff + ram[0x01ff] = 0x7f + ram[0x8000] = 2 + ram[0xa474] = 2 + // setup the irq/brk routine + for(b in listOf(0x48, 0x8A, 0x48, 0x98, 0x48, 0xBA, 0xBD, 0x04, + 0x01, 0x29, 0x10, 0xF0, 0x03, 0x6C, 0x16, 0x03, + 0x6C, 0x14, 0x03).withIndex()) { + ram[0xff48+b.index] = b.value.toShort() + } bus.add(cpu) bus.add(ram) } @@ -446,11 +452,13 @@ class Test6502TestSuite { } @Test + @Disabled("c64 6510 specific component") fun testCntdef() { runTest("cntdef") } @Test + @Disabled("c64 6510 specific component") fun testCnto2() { runTest("cnto2") } @@ -944,6 +952,7 @@ class Test6502TestSuite { } @Test + @Disabled("c64 specific component") fun testNmi() { runTest("nmi") } diff --git a/sim65/bcd_vice_sim.c b/sim65/test/bcd_vice_sim.c similarity index 100% rename from sim65/bcd_vice_sim.c rename to sim65/test/bcd_vice_sim.c diff --git a/sim65/testprogram.asm b/sim65/testprogram.asm deleted file mode 100644 index 631e6ee12..000000000 --- a/sim65/testprogram.asm +++ /dev/null @@ -1,29 +0,0 @@ - - * = $8000 - - sec - lda #$a0 - sta $2000 - ldx $2000 - txa - tay - iny - sty $2001 - ldy #0 -loop lda text,y - beq end - sta $d000 - inc $d001 - iny - jmp loop -end nop - bvs loop - - .byte $02 ; invalid opcode - .byte $02 ; invalid opcode - .byte $02 ; invalid opcode - - -text .enc "screen" - .text "hello!",0 - .enc "none"