1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-17 01:29:28 +00:00

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') regPtf.text = "NV-BDIZC\n"+state.P.asInt().toString(2).padStart(8, '0')
regPCtf.text = hexW(state.PC) regPCtf.text = hexW(state.PC)
regSPtf.text = hexB(state.SP) regSPtf.text = hexB(state.SP)
val memory = bus.memoryComponentFor(state.PC)
val disassem = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim() val memory = listOf(bus[state.PC], bus[state.PC+1], bus[state.PC+2]).toTypedArray()
println("${hexW(state.PC)} $disassem") // XXX val disassem = cpu.disassembleOneInstruction(memory, 0, state.PC).first.substringAfter(' ').trim()
disassemTf.text = disassem disassemTf.text = disassem
if (zeropageTf.isVisible || stackpageTf.isVisible) { if (zeropageTf.isVisible || stackpageTf.isVisible) {

View File

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

View File

@ -1,5 +1,7 @@
package razorvine.ksim65 package razorvine.ksim65
import kotlin.math.max
class Monitor(val bus: Bus, val cpu: Cpu6502) { class Monitor(val bus: Bus, val cpu: Cpu6502) {
private val instructions by lazy { 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 addresses = command.substring(1).trim().split(' ')
val start = parseNumber(addresses[0]) val start = parseNumber(addresses[0])
val end = if (addresses.size > 1) parseNumber(addresses[1]) else start 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) IVirtualMachine.MonitorCmdResult(disassem.first.joinToString("\n") { "d$it" }, "d$${hexW(disassem.second)}", false)
} }
else -> { else -> {
@ -213,18 +216,16 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
} else { } else {
// absolute or absZp // absolute or absZp
val absAddress = try { val absAddress = try {
parseRelativeToPC(arg, address) if(arg.startsWith('*')) parseRelativeToPC(arg, address) else parseNumber(arg)
} catch (x: NumberFormatException) { } catch (x: NumberFormatException) {
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false) return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
} }
if (absAddress <= 255) { val zpInstruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)]
val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)] ?: return IVirtualMachine.MonitorCmdResult( if (absAddress <= 255 && zpInstruction!=null) {
"?invalid instruction", command, false) bus.write(address, zpInstruction.toShort())
bus.write(address, absInstr.toShort())
bus.write(address+1, absAddress.toShort()) bus.write(address+1, absAddress.toShort())
} else { } else {
val absInstr = val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
bus.write(address, absInstr.toShort()) bus.write(address, absInstr.toShort())
bus.write(address+1, (absAddress and 255).toShort()) bus.write(address+1, (absAddress and 255).toShort())
bus.write(address+2, (absAddress ushr 8).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) else -> return IVirtualMachine.MonitorCmdResult("?syntax error", command, false)
} }
val disassem = cpu.disassemble(bus.memoryComponentFor(address), address, address) val memory = listOf(bus[address], bus[address+1], bus[address+2]).toTypedArray()
return IVirtualMachine.MonitorCmdResult(disassem.first.single(), "a$${hexW(disassem.second)} ", false) 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 { private fun parseRelativeToPC(relative: String, currentAddress: Int): Int {
val rest = relative.substring(1).trimStart() val rest = relative.substring(1).trim()
if(rest.any()) { if(rest.isNotEmpty()) {
return when(rest[0]) { return when(rest[0]) {
'-' -> currentAddress-parseNumber(rest.substring(1)) '-' -> currentAddress-parseNumber(rest.substring(1))
'+' -> 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.Cpu6502
import razorvine.ksim65.Cpu65C02 import razorvine.ksim65.Cpu65C02
import razorvine.ksim65.components.Address import razorvine.ksim65.components.Address
import razorvine.ksim65.components.BusComponent
import razorvine.ksim65.components.MemMappedComponent import razorvine.ksim65.components.MemMappedComponent
import razorvine.ksim65.components.UByte import razorvine.ksim65.components.UByte
import razorvine.ksim65.hexW import razorvine.ksim65.hexW
import java.lang.Exception import java.lang.Exception
import kotlin.math.max
import kotlin.math.min
import kotlin.test.* import kotlin.test.*
@ -44,8 +41,6 @@ class Test6502Klaus2m5Functional {
val testnum = bus[0x200].toInt() val testnum = bus[0x200].toInt()
if(cpu.regPC!=0x3469 || testnum!=0xf0) { if(cpu.regPC!=0x3469 || testnum!=0xf0) {
println(cpu.snapshot()) 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") fail("test failed")
} }
} }
@ -74,8 +69,6 @@ class Test6502Klaus2m5Functional {
println(testnum) println(testnum)
if(cpu.regPC!=0x24f1 || testnum!=0xf0) { if(cpu.regPC!=0x24f1 || testnum!=0xf0) {
println(cpu.snapshot()) 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") fail("test failed")
} }
} }
@ -138,8 +131,6 @@ class Test6502Klaus2m5Functional {
if(cpu.regPC!=0x06f5) { if(cpu.regPC!=0x06f5) {
println("Last IRQ triggered at ${hexW(irqtrigger.lastIRQpc)} last NMI at ${hexW(irqtrigger.lastNMIpc)}") println("Last IRQ triggered at ${hexW(irqtrigger.lastIRQpc)} last NMI at ${hexW(irqtrigger.lastNMIpc)}")
println(cpu.snapshot()) 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") fail("test failed")
} }
} }
@ -174,8 +165,6 @@ class Test6502Klaus2m5Functional {
} }
println(cpu.snapshot()) 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") fail("test failed")
} }
@ -209,8 +198,6 @@ class Test6502Klaus2m5Functional {
} }
println(cpu.snapshot()) 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") fail("test failed")
} }
} }

View File

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