separated the 6502 test suite into separate unit tests

This commit is contained in:
Irmen de Jong 2019-09-08 19:11:06 +02:00
parent 28109a39ac
commit b400010426
275 changed files with 1501 additions and 177 deletions

View File

@ -97,8 +97,11 @@ test {
// Show test results. // Show test results.
testLogging { testLogging {
events "passed", "skipped", "failed" events "failed"
} }
systemProperties['junit.jupiter.execution.parallel.enabled'] = true
systemProperties['junit.jupiter.execution.parallel.mode.default'] = 'concurrent'
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
} }

View File

@ -1,47 +0,0 @@
package sim65
import sim65.components.Address
import sim65.components.Cpu6502
import sim65.components.ICpu
import sim65.components.Ram
import kotlin.system.exitProcess
object C64KernalStubs {
lateinit var ram: Ram
fun handleBreakpoint(cpu: ICpu, pc: Address) {
cpu as Cpu6502
when(pc) {
0xffd2 -> {
// CHROUT
ram[0x030c] = 0
val char = Petscii.decodePetscii(listOf(cpu.A.toShort()), true).first()
if(char==13.toChar())
println()
else if(char in ' '..'~')
print(char)
cpu.currentOpcode = 0x60 // rts to end the stub
}
0xffe4 -> {
// GETIN
print("[Input required:] ")
val s = readLine()
if(s.isNullOrEmpty())
cpu.A = 3
else
cpu.A = Petscii.encodePetscii(s, true).first().toInt()
cpu.currentOpcode = 0x60 // rts to end the stub
}
0xe16f -> {
// LOAD/VERIFY
val loc = ram[0xbb].toInt() or (this.ram[0xbc].toInt() shl 8)
val len = ram[0xb7].toInt()
val filename = Petscii.decodePetscii((loc until loc+len).map { ram[it] }.toList(), true).toLowerCase()
ram.loadPrg("c64tests/$filename")
cpu.popStackAddr()
cpu.PC = 0x0816 // continue in next module
}
}
}
}

View File

@ -1,63 +1,89 @@
package sim65 package sim65
import kotlinx.cli.* import kotlinx.cli.*
import sim65.C64KernalStubs.handleBreakpoint
import sim65.components.* import sim65.components.*
import sim65.components.Cpu6502.Companion.IRQ_vector import sim65.components.Cpu6502.Companion.hexB
import sim65.components.Cpu6502.Companion.RESET_vector
import kotlin.system.exitProcess import kotlin.system.exitProcess
fun main(args: Array<String>) { fun main(args: Array<String>) {
printSoftwareHeader() printSoftwareHeader2()
startSimulator(args) startSimulator2(args)
} }
internal fun printSoftwareHeader() { internal fun printSoftwareHeader2() {
val buildVersion = object {}.javaClass.getResource("/version.txt").readText().trim() val buildVersion = object {}.javaClass.getResource("/version.txt").readText().trim()
println("\nSim65 6502 cpu simulator v$buildVersion by Irmen de Jong (irmen@razorvine.net)") println("\nSim65 6502 cpu simulator v$buildVersion by Irmen de Jong (irmen@razorvine.net)")
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n") println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
} }
private fun startSimulator(args: Array<String>) { private fun startSimulator2(args: Array<String>) {
val bootRom = listOf<UByte>(
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0x00,0x90, // NMI vector
0x00,0x10, // RESET vector
0x00,0xa0 // IRQ vector
).toTypedArray()
val cpu = Cpu6502(stopOnBrk = false) val cpu = Cpu6502(true)
cpu.tracing = false cpu.tracing = true
cpu.breakpoint(0xffd2, ::handleBreakpoint)
cpu.breakpoint(0xffe4, ::handleBreakpoint)
cpu.breakpoint(0xe16f, ::handleBreakpoint)
// create the system bus and add device to it. // create the system bus and add device to it.
// note that the order is relevant w.r.t. where reads and writes are going. // note that the order is relevant w.r.t. where reads and writes are going.
val ram = Ram(0, 0xffff)
ram.set(0x02, 0)
ram.set(0xa002, 0)
ram.set(0xa003, 0x80)
ram.set(IRQ_vector, 0x48)
ram.set(IRQ_vector+1, 0xff)
ram.set(RESET_vector, 0x01)
ram.set(RESET_vector+1, 0x08)
ram.set(0x01fe, 0xff)
ram.set(0x01ff, 0x7f)
ram.set(0x8000, 2)
ram.set(0xa474, 2)
ram.loadPrg("c64tests/nopn")
C64KernalStubs.ram = ram
val bus = Bus() val bus = Bus()
bus.add(cpu) bus.add(cpu)
bus.add(Rom(0xff00, 0xffff, bootRom))
bus.add(Parallel(0xd000, 0xd001))
bus.add(Timer(0xd100, 0xd103))
val ram = Ram(0, 0xffff)
bus.add(ram) bus.add(ram)
bus.reset() bus.reset()
require(cpu.SP==0xfd) ram.load("sim65/test/testfiles/ram.bin", 0x8000)
require(cpu.Status.asByte().toInt()==0b00100100) ram.load("sim65/test/testfiles/bcdtest.bin", 0x1000)
//ram.dump(0x8000, 0x802f)
//cpu.disassemble(ram, 0x8000, 0x802f)
try { try {
while (true) { while (true) {
bus.clock() bus.clock()
} }
} catch(e: InstructionError) { } catch(e: InstructionError) {
println(">>> INSTRUCTION ERROR: ${e.message}")
} }
if(ram[0x0400] ==0.toShort())
println("BCD TEST: OK!")
else {
val code = ram[0x0400]
val v1 = ram[0x0401]
val v2 = ram[0x0402]
val predictedA = ram[0x00fc]
val actualA = ram[0x00fd]
val predictedF = ram[0x00fe]
val actualF = ram[0x00ff]
println("BCD TEST: FAIL!! code=${hexB(code)} value1=${hexB(v1)} value2=${hexB(v2)}")
println(" predictedA=${hexB(predictedA)}")
println(" actualA=${hexB(actualA)}")
println(" predictedF=${predictedF.toString(2).padStart(8,'0')}")
println(" actualF=${actualF.toString(2).padStart(8,'0')}")
}
} }

View File

@ -1,89 +0,0 @@
package sim65
import kotlinx.cli.*
import sim65.components.*
import sim65.components.Cpu6502.Companion.hexB
import kotlin.system.exitProcess
fun main(args: Array<String>) {
printSoftwareHeader2()
startSimulator2(args)
}
internal fun printSoftwareHeader2() {
val buildVersion = object {}.javaClass.getResource("/version.txt").readText().trim()
println("\nSim65 6502 cpu simulator v$buildVersion by Irmen de Jong (irmen@razorvine.net)")
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
}
private fun startSimulator2(args: Array<String>) {
val bootRom = listOf<UByte>(
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0x00,0x90, // NMI vector
0x00,0x10, // RESET vector
0x00,0xa0 // IRQ vector
).toTypedArray()
val cpu = Cpu6502(true)
cpu.tracing = true
// create the system bus and add device to it.
// note that the order is relevant w.r.t. where reads and writes are going.
val bus = Bus()
bus.add(cpu)
bus.add(Rom(0xff00, 0xffff, bootRom))
bus.add(Parallel(0xd000, 0xd001))
bus.add(Timer(0xd100, 0xd103))
val ram = Ram(0, 0xffff)
bus.add(ram)
bus.reset()
ram.load("sim65/test/testfiles/ram.bin", 0x8000)
ram.load("sim65/test/testfiles/bcdtest.bin", 0x1000)
//ram.dump(0x8000, 0x802f)
//cpu.disassemble(ram, 0x8000, 0x802f)
try {
while (true) {
bus.clock()
}
} catch(e: InstructionError) {
}
if(ram[0x0400] ==0.toShort())
println("BCD TEST: OK!")
else {
val code = ram[0x0400]
val v1 = ram[0x0401]
val v2 = ram[0x0402]
val predictedA = ram[0x00fc]
val actualA = ram[0x00fd]
val predictedF = ram[0x00fe]
val actualF = ram[0x00ff]
println("BCD TEST: FAIL!! code=${hexB(code)} value1=${hexB(v1)} value2=${hexB(v2)}")
println(" predictedA=${hexB(predictedA)}")
println(" actualA=${hexB(actualA)}")
println(" predictedF=${predictedF.toString(2).padStart(8,'0')}")
println(" actualF=${actualF.toString(2).padStart(8,'0')}")
}
}

View File

@ -13,7 +13,7 @@ interface ICpu {
fun breakpoint(address: Address, action: (cpu: ICpu, pc: Address) -> Unit) fun breakpoint(address: Address, action: (cpu: ICpu, pc: Address) -> Unit)
var tracing: Boolean var tracing: Boolean
val totalCycles: Int val totalCycles: Long
} }
// TODO: add the optional additional cycles to certain instructions and addressing modes // TODO: add the optional additional cycles to certain instructions and addressing modes
@ -23,7 +23,7 @@ interface ICpu {
class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu { class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
override var tracing: Boolean = false override var tracing: Boolean = false
override var totalCycles: Int = 0 override var totalCycles: Long = 0
private set private set
companion object { companion object {

Some files were not shown because too many files have changed in this diff Show More