mirror of
https://github.com/irmen/prog8.git
synced 2024-12-01 15:52:54 +00:00
separated the 6502 test suite into separate unit tests
This commit is contained in:
parent
28109a39ac
commit
b400010426
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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')}")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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')}")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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
Loading…
Reference in New Issue
Block a user