From cc1fb9716b660954dde64479718b95022c3e02ee Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 16 Feb 2020 22:45:54 +0100 Subject: [PATCH] fixed monitor disassemble and assemble commands --- .../razorvine/examplemachines/DebugWindow.kt | 6 +- src/main/kotlin/razorvine/ksim65/Bus.kt | 3 - src/main/kotlin/razorvine/ksim65/Cpu6502.kt | 66 +++++++++---------- src/main/kotlin/razorvine/ksim65/Monitor.kt | 26 ++++---- src/test/kotlin/Test6502Klaus2m5Functional.kt | 13 ---- src/test/kotlin/TestDisassembler.kt | 6 +- 6 files changed, 51 insertions(+), 69 deletions(-) diff --git a/src/main/kotlin/razorvine/examplemachines/DebugWindow.kt b/src/main/kotlin/razorvine/examplemachines/DebugWindow.kt index 0b86586..542b6a1 100644 --- a/src/main/kotlin/razorvine/examplemachines/DebugWindow.kt +++ b/src/main/kotlin/razorvine/examplemachines/DebugWindow.kt @@ -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) { diff --git a/src/main/kotlin/razorvine/ksim65/Bus.kt b/src/main/kotlin/razorvine/ksim65/Bus.kt index 730dcac..79c2b40 100644 --- a/src/main/kotlin/razorvine/ksim65/Bus.kt +++ b/src/main/kotlin/razorvine/ksim65/Bus.kt @@ -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 } diff --git a/src/main/kotlin/razorvine/ksim65/Cpu6502.kt b/src/main/kotlin/razorvine/ksim65/Cpu6502.kt index 1003300..853e306 100644 --- a/src/main/kotlin/razorvine/ksim65/Cpu6502.kt +++ b/src/main/kotlin/razorvine/ksim65/Cpu6502.kt @@ -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, baseAddress: Address, from: Address, to: Address): Pair, Address> { - var location = from + fun disassemble(memory: Array, range: IntRange, baseAddress: Address): Pair, Address> { + var offset = range.first val result = mutableListOf() - 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, address: Address, baseAddress: Address): Pair { + fun disassembleOneInstruction(memory: Array, offset: Int, baseAddress: Address): Pair { 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) } } diff --git a/src/main/kotlin/razorvine/ksim65/Monitor.kt b/src/main/kotlin/razorvine/ksim65/Monitor.kt index 311f0e6..5a35db0 100644 --- a/src/main/kotlin/razorvine/ksim65/Monitor.kt +++ b/src/main/kotlin/razorvine/ksim65/Monitor.kt @@ -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)) diff --git a/src/test/kotlin/Test6502Klaus2m5Functional.kt b/src/test/kotlin/Test6502Klaus2m5Functional.kt index 558312b..70ca85c 100644 --- a/src/test/kotlin/Test6502Klaus2m5Functional.kt +++ b/src/test/kotlin/Test6502Klaus2m5Functional.kt @@ -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") } } diff --git a/src/test/kotlin/TestDisassembler.kt b/src/test/kotlin/TestDisassembler.kt index a904cda..9a3a94c 100644 --- a/src/test/kotlin/TestDisassembler.kt +++ b/src/test/kotlin/TestDisassembler.kt @@ -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