fixed monitor disassemble and assemble commands

This commit is contained in:
Irmen de Jong 2020-02-16 22:45:54 +01:00
parent 6db5e792d6
commit cc1fb9716b
6 changed files with 51 additions and 69 deletions

View File

@ -215,9 +215,9 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
regPtf.text = "NV-BDIZC\n"+state.P.asInt().toString(2).padStart(8, '0')
regPCtf.text = hexW(state.PC)
regSPtf.text = hexB(state.SP)
val memory = bus.memoryComponentFor(state.PC)
val disassem = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim()
println("${hexW(state.PC)} $disassem") // XXX
val memory = listOf(bus[state.PC], bus[state.PC+1], bus[state.PC+2]).toTypedArray()
val disassem = cpu.disassembleOneInstruction(memory, 0, state.PC).first.substringAfter(' ').trim()
disassemTf.text = disassem
if (zeropageTf.isVisible || stackpageTf.isVisible) {

View File

@ -64,7 +64,4 @@ open class Bus {
it[address-it.startAddress] = data
}
}
fun memoryComponentFor(address: Address) =
memComponents.first { it is MemoryComponent && address >= it.startAddress && address <= it.endAddress } as MemoryComponent
}

View File

@ -2,7 +2,6 @@ package razorvine.ksim65
import razorvine.ksim65.components.Address
import razorvine.ksim65.components.BusComponent
import razorvine.ksim65.components.MemoryComponent
import razorvine.ksim65.components.UByte
@ -129,26 +128,23 @@ open class Cpu6502 : BusComponent() {
fun removeBreakpoint(address: Address) = breakpoints.remove(address)
fun disassemble(memory: MemoryComponent, from: Address, to: Address) = disassemble(memory.data, memory.startAddress, from, to)
fun disassemble(memory: Array<UByte>, baseAddress: Address, from: Address, to: Address): Pair<List<String>, Address> {
var location = from
fun disassemble(memory: Array<UByte>, range: IntRange, baseAddress: Address): Pair<List<String>, Address> {
var offset = range.first
val result = mutableListOf<String>()
while (location <= to) {
val dis = disassembleOneInstruction(memory, location, baseAddress)
while (offset <= range.last) {
val dis = disassembleOneInstruction(memory, offset, baseAddress)
result.add(dis.first)
location += dis.second
offset += dis.second
}
return Pair(result, location)
return Pair(result, offset+baseAddress)
}
fun disassembleOneInstruction(memory: Array<UByte>, address: Address, baseAddress: Address): Pair<String, Int> {
fun disassembleOneInstruction(memory: Array<UByte>, offset: Int, baseAddress: Address): Pair<String, Int> {
val spacing1 = " "
val spacing2 = " "
val spacing3 = " "
val location = address-baseAddress
val byte = memory[location]
val line = "\$${hexW(location+baseAddress)} ${hexB(byte)} "
val byte = memory[offset]
val line = "\$${hexW(offset+baseAddress)} ${hexB(byte)} "
val opcode = instructions[byte.toInt()]
return when (opcode.mode) {
AddrMode.Acc -> {
@ -158,75 +154,75 @@ open class Cpu6502 : BusComponent() {
Pair(line+"$spacing1 ${opcode.mnemonic}", 1)
}
AddrMode.Imm -> {
val value = memory[location+1]
val value = memory[offset+1]
Pair(line+"${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}", 2)
}
AddrMode.Zp -> {
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}", 2)
}
AddrMode.Zpr -> {
// addressing mode used by the 65C02, put here for convenience rather than the subclass
val zpAddr = memory[location+1]
val rel = memory[location+2]
val target = (if (rel <= 0x7f) location+3+rel+baseAddress else location+3-(256-rel)+baseAddress) and 0xffff
val zpAddr = memory[offset+1]
val rel = memory[offset+2]
val target = (if (rel <= 0x7f) offset+3+rel+baseAddress else offset+3-(256-rel)+baseAddress) and 0xffff
Pair(line+"${hexB(zpAddr)} ${hexB(rel)} $spacing3 ${opcode.mnemonic} \$${hexB(zpAddr)}, \$${hexW(target, true)}", 3)
}
AddrMode.Izp -> {
// addressing mode used by the 65C02, put here for convenience rather than the subclass
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$(${hexB(zpAddr)})", 2)
}
AddrMode.IaX -> {
// addressing mode used by the 65C02, put here for convenience rather than the subclass
val lo = memory[location+1]
val hi = memory[location+2]
val lo = memory[offset+1]
val hi = memory[offset+2]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$(${hexW(absAddr)},x)", 3)
}
AddrMode.ZpX -> {
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x", 2)
}
AddrMode.ZpY -> {
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y", 2)
}
AddrMode.Rel -> {
val rel = memory[location+1]
val target = (if (rel <= 0x7f) location+2+rel+baseAddress else location+2-(256-rel)+baseAddress) and 0xffff
val rel = memory[offset+1]
val target = (if (rel <= 0x7f) offset+2+rel+baseAddress else offset+2-(256-rel)+baseAddress) and 0xffff
Pair(line+"${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target, true)}", 2)
}
AddrMode.Abs -> {
val lo = memory[location+1]
val hi = memory[location+2]
val lo = memory[offset+1]
val hi = memory[offset+2]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}", 3)
}
AddrMode.AbsX -> {
val lo = memory[location+1]
val hi = memory[location+2]
val lo = memory[offset+1]
val hi = memory[offset+2]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x", 3)
}
AddrMode.AbsY -> {
val lo = memory[location+1]
val hi = memory[location+2]
val lo = memory[offset+1]
val hi = memory[offset+2]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y", 3)
}
AddrMode.Ind -> {
val lo = memory[location+1]
val hi = memory[location+2]
val lo = memory[offset+1]
val hi = memory[offset+2]
val indirectAddr = lo.toInt() or (hi.toInt() shl 8)
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})", 3)
}
AddrMode.IzX -> {
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)", 2)
}
AddrMode.IzY -> {
val zpAddr = memory[location+1]
val zpAddr = memory[offset+1]
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y", 2)
}
}

View File

@ -1,5 +1,7 @@
package razorvine.ksim65
import kotlin.math.max
class Monitor(val bus: Bus, val cpu: Cpu6502) {
private val instructions by lazy {
@ -94,7 +96,8 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
val addresses = command.substring(1).trim().split(' ')
val start = parseNumber(addresses[0])
val end = if (addresses.size > 1) parseNumber(addresses[1]) else start
val disassem = cpu.disassemble(bus.memoryComponentFor(start), start, end)
val memory = (start .. max(0xffff, end+3)).map {bus[it]}.toTypedArray()
val disassem = cpu.disassemble(memory, 0 .. end-start, start)
IVirtualMachine.MonitorCmdResult(disassem.first.joinToString("\n") { "d$it" }, "d$${hexW(disassem.second)}", false)
}
else -> {
@ -213,18 +216,16 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
} else {
// absolute or absZp
val absAddress = try {
parseRelativeToPC(arg, address)
if(arg.startsWith('*')) parseRelativeToPC(arg, address) else parseNumber(arg)
} catch (x: NumberFormatException) {
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
}
if (absAddress <= 255) {
val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)] ?: return IVirtualMachine.MonitorCmdResult(
"?invalid instruction", command, false)
bus.write(address, absInstr.toShort())
val zpInstruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)]
if (absAddress <= 255 && zpInstruction!=null) {
bus.write(address, zpInstruction.toShort())
bus.write(address+1, absAddress.toShort())
} else {
val absInstr =
instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
bus.write(address, absInstr.toShort())
bus.write(address+1, (absAddress and 255).toShort())
bus.write(address+2, (absAddress ushr 8).toShort())
@ -236,13 +237,14 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
else -> return IVirtualMachine.MonitorCmdResult("?syntax error", command, false)
}
val disassem = cpu.disassemble(bus.memoryComponentFor(address), address, address)
return IVirtualMachine.MonitorCmdResult(disassem.first.single(), "a$${hexW(disassem.second)} ", false)
val memory = listOf(bus[address], bus[address+1], bus[address+2]).toTypedArray()
val disassem = cpu.disassembleOneInstruction(memory, 0, address)
return IVirtualMachine.MonitorCmdResult(disassem.first, "a$${hexW(disassem.second + address)} ", false)
}
private fun parseRelativeToPC(relative: String, currentAddress: Int): Int {
val rest = relative.substring(1).trimStart()
if(rest.any()) {
val rest = relative.substring(1).trim()
if(rest.isNotEmpty()) {
return when(rest[0]) {
'-' -> currentAddress-parseNumber(rest.substring(1))
'+' -> currentAddress+parseNumber(rest.substring(1))

View File

@ -3,13 +3,10 @@ import razorvine.ksim65.components.Ram
import razorvine.ksim65.Cpu6502
import razorvine.ksim65.Cpu65C02
import razorvine.ksim65.components.Address
import razorvine.ksim65.components.BusComponent
import razorvine.ksim65.components.MemMappedComponent
import razorvine.ksim65.components.UByte
import razorvine.ksim65.hexW
import java.lang.Exception
import kotlin.math.max
import kotlin.math.min
import kotlin.test.*
@ -44,8 +41,6 @@ class Test6502Klaus2m5Functional {
val testnum = bus[0x200].toInt()
if(cpu.regPC!=0x3469 || testnum!=0xf0) {
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString("\n"))
fail("test failed")
}
}
@ -74,8 +69,6 @@ class Test6502Klaus2m5Functional {
println(testnum)
if(cpu.regPC!=0x24f1 || testnum!=0xf0) {
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString("\n"))
fail("test failed")
}
}
@ -138,8 +131,6 @@ class Test6502Klaus2m5Functional {
if(cpu.regPC!=0x06f5) {
println("Last IRQ triggered at ${hexW(irqtrigger.lastIRQpc)} last NMI at ${hexW(irqtrigger.lastNMIpc)}")
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString("\n"))
fail("test failed")
}
}
@ -174,8 +165,6 @@ class Test6502Klaus2m5Functional {
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
@ -209,8 +198,6 @@ class Test6502Klaus2m5Functional {
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
}

View File

@ -12,7 +12,7 @@ class TestDisassembler {
val memory = Ram(0, 0xffff)
val binfile = javaClass.classLoader.getResourceAsStream("disassem_instr_test.prg")?.readBytes()!!
memory.load(binfile, 0x1000-2)
val result = cpu.disassemble(memory, 0x1000, 0x1221)
val result = cpu.disassemble(memory.data, 0x1000..0x1221, 0)
assertEquals(256, result.first.size)
assertEquals(0x1222, result.second)
assertEquals("\$1000 69 01 adc #\$01", result.first[0])
@ -32,7 +32,7 @@ class TestDisassembler {
val memory = Ram(0, 0x0fff)
val source = javaClass.classLoader.getResource("disassem_r65c02.bin").readBytes()
memory.load(source, 0x0200)
val disassem = cpu.disassemble(memory, 0x0200, 0x0250)
val disassem = cpu.disassemble(memory.data, 0x0200..0x0250, 0)
assertEquals(0x251, disassem.second)
val result = disassem.first.joinToString("\n")
assertEquals("""${'$'}0200 07 12 rmb0 ${'$'}12
@ -78,7 +78,7 @@ ${'$'}0250 00 brk""", result)
val memory = Ram(0, 0x0fff)
val source = javaClass.classLoader.getResource("disassem_wdc65c02.bin").readBytes()
memory.load(source, 0x200)
val disassem = cpu.disassemble(memory, 0x0200, 0x0215)
val disassem = cpu.disassemble(memory.data, 0x0200..0x0215, 0)
assertEquals(0x216, disassem.second)
val result = disassem.first.joinToString("\n")
assertEquals("""${'$'}0200 cb wai