Improved paging simulation, added disassembler
This commit is contained in:
@@ -6,9 +6,9 @@ import com.thequux.mcpdp.ext.bit.shl
|
||||
import com.thequux.mcpdp.ext.bit.shr
|
||||
|
||||
interface VAddressSpace {
|
||||
fun getw(addr: UShort, dspace: Boolean = false): UShort
|
||||
fun getw(addr: UShort, dspace: Boolean = true): UShort
|
||||
fun getb(addr: UShort): UByte
|
||||
fun setw(addr: UShort, value: UShort, dspace: Boolean = false)
|
||||
fun setw(addr: UShort, value: UShort, dspace: Boolean = true)
|
||||
fun setb(addr: UShort, value: UByte)
|
||||
}
|
||||
|
||||
|
@@ -2,9 +2,11 @@ package com.thequux.mcpdp.core
|
||||
|
||||
import com.thequux.mcpdp.ext.bit.*
|
||||
import com.thequux.mcpdp.peripheral.MemBus
|
||||
import com.thequux.mcpdp.util.Disassembler
|
||||
import com.thequux.mcpdp.util.ProgrammerError
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import kotlin.math.log
|
||||
|
||||
/// The main CPU
|
||||
///
|
||||
@@ -15,6 +17,12 @@ import org.slf4j.LoggerFactory
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class CPU(val mbus: MemBus) {
|
||||
|
||||
companion object {
|
||||
val debugMode = System.getProperty("jdp11.itrace").toBoolean()
|
||||
}
|
||||
|
||||
|
||||
private var control_reg: UShort = 0u
|
||||
val logger: Logger = LoggerFactory.getLogger(this.javaClass)
|
||||
private val flagStr: String
|
||||
get() {
|
||||
@@ -29,6 +37,7 @@ class CPU(val mbus: MemBus) {
|
||||
private val general_registers = Array<UShortArray>(2) { UShortArray(6) }
|
||||
private val shadow_r6 = UShortArray(4) //
|
||||
val core = PagingUnit(mbus)
|
||||
private val dasm = Disassembler(core)
|
||||
|
||||
var runState: RunState = RunState.HALTED
|
||||
var psw: UShort
|
||||
@@ -119,10 +128,12 @@ class CPU(val mbus: MemBus) {
|
||||
private var V: Boolean = false
|
||||
private var T: Boolean = false
|
||||
private val PADDR_REG_BIT: Int = 23
|
||||
private val PADDR_ISPACE_BIT: Int = 22
|
||||
|
||||
init {
|
||||
val regs = Registers()
|
||||
mbus.unibus.run {
|
||||
attach(0x3FFE6u, 1, regs)
|
||||
attach(0x3FFF8u, 3, regs)
|
||||
attach(0x3FFF4u, 2, regs)
|
||||
}
|
||||
@@ -130,38 +141,40 @@ class CPU(val mbus: MemBus) {
|
||||
}
|
||||
|
||||
private fun is_paddr_reg(addr: UInt): Boolean = addr bit PADDR_REG_BIT
|
||||
private fun is_paddr_ispace(addr: UInt): Boolean = addr bit PADDR_ISPACE_BIT
|
||||
private fun op_resolve(operand: Int, byte_mode: Boolean = false): UInt {
|
||||
val mode = operand shr 3
|
||||
val reg = operand and 0x7
|
||||
val increment = if (byte_mode && reg != 7) 1U else 2U
|
||||
val is_pc = reg == 7
|
||||
val increment = if (byte_mode && !is_pc) 1U else 2U
|
||||
return 0x80_FFFFu and when (mode and 0x7) {
|
||||
0 -> reg.toUInt() bis PADDR_REG_BIT
|
||||
1 -> registers[reg].toUInt()
|
||||
2 -> {
|
||||
val addr = registers[reg]
|
||||
registers[reg] = (addr + increment).toUShort()
|
||||
addr.toUInt()
|
||||
addr.toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
||||
}
|
||||
3 -> {
|
||||
val addr = registers[reg]
|
||||
registers[reg] = (addr + 2U).toUShort()
|
||||
core.getw(addr).toUInt()
|
||||
core.getw(addr, dspace = !is_pc).toUInt()
|
||||
}
|
||||
4 -> {
|
||||
registers[reg] = (registers[reg] - increment).toUShort()
|
||||
return registers[reg].toUInt()
|
||||
return registers[reg].toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
||||
}
|
||||
5 -> {
|
||||
registers[reg] = (registers[reg] - 2U).toUShort()
|
||||
core.getw(registers[reg]).toUInt()
|
||||
core.getw(registers[reg], dspace = !is_pc).toUInt()
|
||||
}
|
||||
6 -> {
|
||||
val idx = core.getw(pc)
|
||||
val idx = core.getw(pc, dspace = false)
|
||||
pc = (pc + 2u).toUShort()
|
||||
idx + registers[reg]
|
||||
(idx + registers[reg]) and 0xFFFFu
|
||||
}
|
||||
7 -> {
|
||||
val idx = core.getw(pc)
|
||||
val idx = core.getw(pc, dspace = false)
|
||||
pc = (pc+2u).toUShort()
|
||||
core.getw((idx+registers[reg]).toUShort()).toUInt()
|
||||
}
|
||||
@@ -226,6 +239,9 @@ class CPU(val mbus: MemBus) {
|
||||
|
||||
/// Internal step; evaluates one opcode, but does not handle errors, interrupts, or updating system registers
|
||||
fun step_int() {
|
||||
if (debugMode) {
|
||||
logger.debug("${pc.toString(8).padStart(6, '0')}: ${dasm.dasm_at(pc)}")
|
||||
}
|
||||
val opcode = core.getw(pc).toInt()
|
||||
pc = (pc + 2u).toUShort()
|
||||
when (opcode and 0xF000) {
|
||||
@@ -618,7 +634,7 @@ class CPU(val mbus: MemBus) {
|
||||
0x7000 -> when (opcode shr 9 and 0x7) {
|
||||
0 -> { // MUL
|
||||
val r = opcode shr 6 and 0x7
|
||||
val src = op_loadw(opc_src(opcode)).toShort().toInt()
|
||||
val src = op_loadw(opc_dst(opcode)).toShort().toInt()
|
||||
val res = registers[r].toShort().toInt() * src
|
||||
registers[r bis 1] = (res shr 16).toUShort()
|
||||
registers[r] = res.toUShort()
|
||||
@@ -629,7 +645,7 @@ class CPU(val mbus: MemBus) {
|
||||
} // MUL
|
||||
1 -> { // DIV
|
||||
val r = opcode shr 6 and 0x7
|
||||
val src = op_loadw(opc_src(opcode)).toInt()
|
||||
val src = op_loadw(opc_dst(opcode)).toInt()
|
||||
val lho = (registers[r].toUInt() shl 16 or registers[r bis 1].toUInt()).toInt()
|
||||
if (src != 0) {
|
||||
val quot = lho / src
|
||||
@@ -647,7 +663,7 @@ class CPU(val mbus: MemBus) {
|
||||
} // DIV
|
||||
2 -> { // ASH
|
||||
val r = opcode shr 6 and 0x7
|
||||
var count = (op_loadb(opc_src(opcode)) and 0x3Fu).toInt()
|
||||
var count = (op_loadb(opc_dst(opcode)) and 0x3Fu).toInt()
|
||||
val src = registers[r].toShort().toInt() // two casts to sign extend
|
||||
count = count sex 6
|
||||
V = false
|
||||
@@ -674,7 +690,7 @@ class CPU(val mbus: MemBus) {
|
||||
} // ASH
|
||||
3 -> { // ASHC
|
||||
val r = opcode shr 6 and 0x7
|
||||
var count = (op_loadb(opc_src(opcode)) and 0x3Fu).toInt() sex 6
|
||||
var count = (op_loadb(opc_dst(opcode)) and 0x3Fu).toInt() sex 6
|
||||
val src = (registers[r].toUInt() shl 16 or registers[r or 1].toUInt()).toInt() // two casts to sign extend
|
||||
V = false
|
||||
val res = if (count > 0) {
|
||||
@@ -782,9 +798,9 @@ class CPU(val mbus: MemBus) {
|
||||
try {
|
||||
if (runState == RunState.HALTED) return
|
||||
|
||||
// TODO: handle PIRQ
|
||||
for (i in 7 downTo (psw_priority + 1)) {
|
||||
if (pirq bit 8+i) {
|
||||
logger.debug("PIRQ{} trap to 0xA0", i)
|
||||
trap(0xA0u)
|
||||
break
|
||||
}
|
||||
@@ -792,12 +808,16 @@ class CPU(val mbus: MemBus) {
|
||||
if (source != null) {
|
||||
// we might have been waiting for an interrupt
|
||||
runState = RunState.RUNNING
|
||||
trap(source.vector)
|
||||
val vector = source.vector
|
||||
logger.debug("Unibus interrupt at pri {} to {}", i, vector)
|
||||
trap(vector)
|
||||
source.handled()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (runState == RunState.WAIT_FOR_INTERRUPT) return
|
||||
if (runState == RunState.WAIT_FOR_INTERRUPT) {
|
||||
return
|
||||
}
|
||||
// System.err.println("Executing insn at ${pc.toString(8)}")
|
||||
step_int()
|
||||
// TODO: handle T bit
|
||||
@@ -808,9 +828,9 @@ class CPU(val mbus: MemBus) {
|
||||
is NonExistentMemoryError -> cpu_err or 0x20u
|
||||
is BusTimeoutError -> cpu_err or 0x10u
|
||||
}
|
||||
trap(4u)
|
||||
trap(0x04u)
|
||||
} catch (_: InvalidOpcodeException) {
|
||||
trap(10u)
|
||||
trap(0x10u)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,14 +844,18 @@ class CPU(val mbus: MemBus) {
|
||||
}
|
||||
|
||||
fun trap(vector: UShort) {
|
||||
stack_push(psw)
|
||||
logger.debug("Trap to {}", vector.toString(8))
|
||||
val old_psw = psw
|
||||
// update PSW first so that this gets pushed to the
|
||||
psw = core.getw((vector + 2u).toUShort())
|
||||
stack_push(old_psw)
|
||||
stack_push(pc)
|
||||
pc = core.getw(vector)
|
||||
psw = core.getw((vector + 2u).toUShort())
|
||||
}
|
||||
|
||||
private inner class Registers: PAddressSpace {
|
||||
override fun getw(addr: UInt): UShort = when (addr) {
|
||||
0x3FFE6u -> control_reg
|
||||
0x3FFF0u -> (mbus.size shr 6).toUShort()
|
||||
0x3FFF2u -> 0u // upper size
|
||||
0x3FFF4u -> 0x1170u // system ID
|
||||
@@ -843,6 +867,7 @@ class CPU(val mbus: MemBus) {
|
||||
}
|
||||
|
||||
override fun setw(addr: UInt, value: UShort) = when (addr) {
|
||||
0x3FFE6u -> control_reg = value
|
||||
0x3_FFF0u , 0x3_FFF2u , 0x3_FFF4u, 0x3_FFF8u -> {} // read-only registers
|
||||
0x3_FFF6u -> cpu_err = value
|
||||
0x3_FFFAu -> pirq = value
|
||||
|
@@ -6,6 +6,7 @@ import com.thequux.mcpdp.ext.bit.bit
|
||||
import com.thequux.mcpdp.ext.bit.shr
|
||||
import com.thequux.mcpdp.peripheral.Unibus
|
||||
import com.thequux.mcpdp.util.ProgrammerError
|
||||
import kotlin.math.max
|
||||
|
||||
enum class AccessAction {
|
||||
Allow,
|
||||
@@ -43,20 +44,27 @@ private data class PDR(val plf: UShort, var A: Boolean, var W: Boolean, var ed:
|
||||
|
||||
val range: UIntRange
|
||||
get() = if (ed) {
|
||||
(0x2000U - (plf.toUInt() shl 6))..0x1FFFu
|
||||
(plf.toUInt() shl 6) ..< 0x2000u
|
||||
} else {
|
||||
0U..((plf.toUInt() shl 6) -1U)
|
||||
0U..< (plf.toUInt() shl 6)
|
||||
}
|
||||
fun touched() { A = true }
|
||||
fun written() { A = true; W = true }
|
||||
}
|
||||
|
||||
private enum class MManMode(val mmanEnable: Boolean, val addrMask: UInt, val hipageMask: UInt) {
|
||||
MM_16(addrMask = 0xFFFFu, mmanEnable = false, hipageMask = 0xF000u),
|
||||
MM_18(addrMask = 0x3_FFFFu, mmanEnable = true, hipageMask = 0x3_E000u),
|
||||
MM_22(addrMask = 0x3F_FFFFu, mmanEnable = true, hipageMask = 0x3C_0000u),
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
|
||||
private var mmr = UShortArray(4)
|
||||
private var enableUnibusMap: Boolean = false
|
||||
private var enable22bit: Boolean = false
|
||||
private var mapMode: MManMode = MManMode.MM_16
|
||||
|
||||
/// The 18-bit address space exposed to peripherals
|
||||
val unibusMap: PAddressSpace = UnibusMap()
|
||||
@@ -102,20 +110,30 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
throw Trap(0xA8)
|
||||
}
|
||||
}
|
||||
return addr.toUInt() + (par.toUInt() shl 6) and 0x3F_FFFFu
|
||||
val tmp1 = addr.toUInt() + (par.toUInt() shl 6) and mapMode.addrMask
|
||||
if (tmp1 and mapMode.hipageMask == mapMode.hipageMask) {
|
||||
return tmp1 or 0x3C_0000u
|
||||
} else {
|
||||
return tmp1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mode: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
modeSpace = if (mmr[0] bit 0) {
|
||||
modeVTabs[if (field == 3) 2 else field]
|
||||
} else {
|
||||
noMmanSpace
|
||||
}
|
||||
updateMode()
|
||||
}
|
||||
|
||||
fun updateMode() {
|
||||
mapMode = when {
|
||||
!(mmr[0] bit 0) -> MManMode.MM_16
|
||||
enable22bit -> MManMode.MM_22
|
||||
else -> MManMode.MM_18
|
||||
}
|
||||
modeSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace
|
||||
}
|
||||
|
||||
private val itabs: Array<PageTable> = Array(3) { PageTable(if (it == 2) 3 else it, dspace = false) }
|
||||
private val dtabs: Array<PageTable> = Array(3) { PageTable(if (it == 2) 3 else it, dspace = true) }
|
||||
private val modeVTabs: Array<ModeVSpace> = Array(3) { ModeVSpace(itabs[it], dtabs[it], false) }
|
||||
@@ -141,7 +159,13 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
}
|
||||
|
||||
private inner class NoMmanSpace: VAddressSpace {
|
||||
private fun map(addr: UShort): UInt = if ((addr shr 13) == 7u.toUShort()) addr.toUInt().or(0x3F0000u) else addr.toUInt()
|
||||
private fun map(addr: UShort): UInt {
|
||||
if ((addr shr 13) == 7u.toUShort()) {
|
||||
return addr.toUInt() or 0x3F0000u
|
||||
} else {
|
||||
return addr.toUInt()
|
||||
}
|
||||
}
|
||||
override fun getb(addr: UShort): UByte = pspace.getb(map(addr))
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = pspace.getw(map(addr))
|
||||
override fun setb(addr: UShort, value: UByte) = pspace.setb(map(addr), value)
|
||||
@@ -149,20 +173,34 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MMR0: UInt = 0x3FF8Au
|
||||
private val MMR1: UInt = 0x3FF8Cu
|
||||
private val MMR2: UInt = 0x3FF8Eu
|
||||
private val MMR3: UInt = 0x3F54Eu
|
||||
}
|
||||
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = modeSpace.getw(addr, dspace)
|
||||
private fun <E> withRecovery(addr: UShort, op: PagingUnit.() -> E): E {
|
||||
try {
|
||||
return this.op()
|
||||
} catch (e: MemoryError) {
|
||||
e.addr = addr.toUInt()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = withRecovery(addr) { modeSpace.getw(addr, dspace) }
|
||||
|
||||
override fun getb(addr: UShort): UByte = modeSpace.getb(addr)
|
||||
override fun getb(addr: UShort): UByte = withRecovery(addr) { modeSpace.getb(addr) }
|
||||
|
||||
override fun setw(addr: UShort, value: UShort, dspace: Boolean) = modeSpace.setw(addr, value, dspace)
|
||||
override fun setw(addr: UShort, value: UShort, dspace: Boolean) = withRecovery(addr) { modeSpace.setw(addr, value, dspace) }
|
||||
|
||||
override fun setb(addr: UShort, value: UByte) = modeSpace.setb(addr, value)
|
||||
override fun setb(addr: UShort, value: UByte) = withRecovery(addr) { modeSpace.setb(addr, value) }
|
||||
|
||||
private inner class ConfigRegisters: PAddressSpace {
|
||||
|
||||
override fun getw(addr: UInt): UShort = when (addr) {
|
||||
MMR0 -> mmr[0]
|
||||
MMR1 -> mmr[1]
|
||||
MMR2 -> mmr[2]
|
||||
MMR3 -> {
|
||||
(0U.bit(0, modeVTabs[2].useDSpace)
|
||||
.bit(1, modeVTabs[1].useDSpace)
|
||||
@@ -181,6 +219,7 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
modeVTabs[0].useDSpace = value bit 2
|
||||
modeVTabs[1].useDSpace = value bit 1
|
||||
modeVTabs[2].useDSpace = value bit 0
|
||||
updateMode()
|
||||
}
|
||||
in 0x3F080u..0x3F0FFu -> {
|
||||
val uaddr = (addr shr 1 and 31u).toInt()
|
||||
|
241
src/main/kotlin/com/thequux/mcpdp/util/DebugTools.kt
Normal file
241
src/main/kotlin/com/thequux/mcpdp/util/DebugTools.kt
Normal file
@@ -0,0 +1,241 @@
|
||||
package com.thequux.mcpdp.util
|
||||
|
||||
import com.thequux.mcpdp.core.CPU
|
||||
import com.thequux.mcpdp.core.InvalidOpcodeException
|
||||
import com.thequux.mcpdp.core.VAddressSpace
|
||||
import com.thequux.mcpdp.ext.bit.*
|
||||
|
||||
object DebugTools {
|
||||
|
||||
|
||||
}
|
||||
|
||||
class NullDisassembler() {
|
||||
fun dasm_at(loc: UShort): String = ""
|
||||
}
|
||||
class Disassembler(val core: VAddressSpace) {
|
||||
|
||||
var vpc: UShort = 0u
|
||||
var opc: UShort = 0u
|
||||
var opcode: Int = 0
|
||||
|
||||
private fun fmt(opcode: String, vararg args: String): String {
|
||||
val res = StringBuilder()
|
||||
res.append(opcode.uppercase())
|
||||
|
||||
for ((index, arg) in args.withIndex()) {
|
||||
if (index == 0) {
|
||||
res.append("\t")
|
||||
} else {
|
||||
res.append(", ")
|
||||
}
|
||||
res.append(arg)
|
||||
}
|
||||
return res.toString()
|
||||
}
|
||||
|
||||
private fun reg_name(reg: Int): String {
|
||||
return when(reg) {
|
||||
6 -> "SP"
|
||||
7 -> "PC"
|
||||
else -> "R$reg"
|
||||
}
|
||||
}
|
||||
|
||||
private fun getw(): UShort {
|
||||
val ret = core.getw(vpc, dspace = false)
|
||||
vpc = vpc.inc().inc()
|
||||
return ret
|
||||
}
|
||||
private fun arg_at(offset: Int): String {
|
||||
val rv = opcode shr offset and 0x3F
|
||||
val reg = rv and 0x7
|
||||
val rn = reg_name(reg)
|
||||
val mode = rv shr 3 and 0x6
|
||||
val ind = if (rv bit 3) "@" else ""
|
||||
return when (mode) {
|
||||
0 -> "$ind$rn"
|
||||
2 -> if (reg == 7) "$ind#${getw().toString(8)}" else "$ind($rn)+"
|
||||
4 -> "$ind-($rn)"
|
||||
6 -> if (reg == 7) {
|
||||
ind + (getw() + vpc).toShort().toString(8)
|
||||
} else {
|
||||
"$ind${getw().toString(8)}($rn)"
|
||||
}
|
||||
else -> throw Exception("Failed to decode arg: ${rv.toString(8)}")
|
||||
}
|
||||
}
|
||||
private fun dst() = arg_at(0)
|
||||
private fun src() = arg_at(6)
|
||||
private fun reg0(): String = reg_name(opcode and 0x7)
|
||||
private fun reg6(): String = reg_name(opcode shr 6 and 0x7)
|
||||
|
||||
private fun br_rel(opc: String): String {
|
||||
val rel = (opcode and 0xFF) - (opcode and 0x80 shl 1)
|
||||
val dst = (vpc.toInt() + rel).toUShort()
|
||||
return fmt(opc, dst.toString(8))
|
||||
}
|
||||
|
||||
private fun rel6(): String {
|
||||
val rel = (opcode and 0x3F) - (opcode and 0x20 shl 1)
|
||||
val dst = vpc.toInt() + rel
|
||||
return dst.toUShort().toString(8)
|
||||
}
|
||||
|
||||
fun dasm_at(loc: UShort): String {
|
||||
var vpc = loc
|
||||
|
||||
opcode = core.getw(vpc, dspace = false).toInt()
|
||||
vpc = (vpc + 2u).toUShort()
|
||||
try {
|
||||
return when (opcode and 0xF000) {
|
||||
0x0, 0x8000 -> when (opcode and 0xFF00) {
|
||||
0x0000 -> when (opcode) {
|
||||
0x0000 -> fmt("HALT") // HALT
|
||||
0x0001 -> fmt("WAIT")
|
||||
0x0002 -> fmt("WTI")
|
||||
0x0003 -> fmt("BPT")
|
||||
0x0004 -> fmt("IOT")
|
||||
0x0005 -> fmt("RESET")
|
||||
0x0006 -> fmt("RTT")
|
||||
in 0x40..0x7f -> fmt("JMP", dst()) // JMP
|
||||
in 0x80..0x87 -> fmt("RTS", reg0()) // RTS
|
||||
in 0x98..0x9F -> fmt("SPL", (opcode and 7).toString())
|
||||
0xBF -> fmt("SCC")
|
||||
in 0xA0..0xBE -> {
|
||||
val items: ArrayList<String> = ArrayList()
|
||||
if (opcode bit 0) items.add("SEC")
|
||||
if (opcode bit 1) items.add("SEZ")
|
||||
if (opcode bit 2) items.add("SEV")
|
||||
if (opcode bit 3) items.add("SEN")
|
||||
items.joinToString(" ")
|
||||
} // Scc/Ccc
|
||||
in 0xC0..0xFF -> fmt("SWAB", dst()) // SWAB
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x0100 -> br_rel("BR") // BR
|
||||
0x0200 -> br_rel("BNE") // BNE
|
||||
0x0300 -> br_rel("BEQ") // BEQ
|
||||
0x0400 -> br_rel("BGE") // BGE
|
||||
0x0500 -> br_rel("BLT") // BLT
|
||||
0x0600 -> br_rel("BGT") // BGT
|
||||
0x0700 -> br_rel("BLE") // BLE
|
||||
0x0800, 0x0900 -> fmt("JSR", reg6(), dst()) // JSR
|
||||
0x0A00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("CLR", dst()) // CLR
|
||||
1 -> fmt("COM", dst()) // COM
|
||||
2 -> fmt("INC", dst()) // INC
|
||||
3 -> fmt("DEC", dst()) // DEC
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x0B00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("NEG", dst()) // NEG
|
||||
1 -> fmt("ADC", dst()) // ADC
|
||||
2 -> fmt("SBC", dst()) // SBC
|
||||
3 -> fmt("TST", dst()) // TST
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x0C00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("ROR", dst()) // ROR
|
||||
1 -> fmt("ROL", dst()) // ROL
|
||||
2 -> fmt("ASR", dst()) // ASR
|
||||
3 -> fmt("ASL", dst()) // ASL
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x0D00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("MARK", (opcode and 0x3F).toString(8)) // MARK
|
||||
1 -> {
|
||||
throw InvalidOpcodeException()
|
||||
} // MFPI // TODO
|
||||
2 -> {
|
||||
throw InvalidOpcodeException()
|
||||
} // MTPI // TODO
|
||||
3 -> fmt("SXT", dst()) // SXT
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x0F00 -> throw InvalidOpcodeException() // CSM
|
||||
0x8000 -> br_rel("BPL") // BPL
|
||||
0x8100 -> br_rel("BMI") // BMI
|
||||
0x8200 -> br_rel("BHI") // BHI
|
||||
0x8300 -> br_rel("BLOS") // BLOS
|
||||
0x8400 -> br_rel("BVC") // BVC
|
||||
0x8500 -> br_rel("BVS") // BVS
|
||||
0x8600 -> br_rel("BHIS") // BCC/BHIS
|
||||
0x8700 -> br_rel("BLO") // BCS/BLO
|
||||
0x8800 -> fmt("EMT", (opcode and 0xFF).toString(8)) // EMT
|
||||
0x8900 -> fmt("TRAP", (opcode and 0xFF).toString(8)) // TRAP
|
||||
|
||||
0x8A00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("CLRB", dst()) // CLRB
|
||||
1 -> fmt("COMB", dst()) // COMB
|
||||
2 -> fmt("INCB", dst()) // INC
|
||||
3 -> fmt("DECB", dst()) // DEC
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x8B00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("NEGB", dst()) // NEGB
|
||||
1 -> fmt("ADCB", dst()) // ADCB
|
||||
2 -> fmt("SBCB", dst()) // SBCB
|
||||
3 -> fmt("TSTB", dst()) // TSTB
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x8C00 -> when (opcode shr 6 and 3) {
|
||||
0 -> fmt("RORB", dst()) // RORB
|
||||
1 -> fmt("ROLB", dst()) // ROLB
|
||||
2 -> fmt("ASRB", dst()) // ASRB
|
||||
3 -> fmt("ASLB", dst()) // ASLB
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x8D00 -> when (opcode shr 6 and 3) {
|
||||
1 -> {
|
||||
throw InvalidOpcodeException()
|
||||
} // MFPD // TODO
|
||||
2 -> {
|
||||
throw InvalidOpcodeException()
|
||||
} // MTPD // TODO
|
||||
else -> throw InvalidOpcodeException()// Reserved
|
||||
}
|
||||
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
|
||||
0x1000 -> fmt("MOV", src(), dst()) // MOV
|
||||
0x2000 -> fmt("CMP", src(), dst()) // CMP
|
||||
0x3000 -> fmt("BIT", src(), dst()) // BIT
|
||||
0x4000 -> fmt("BIC", src(), dst()) // BIC
|
||||
0x5000 -> fmt("BIS", src(), dst()) // BIS
|
||||
0x6000 -> fmt("ADD", src(), dst()) // ADD
|
||||
0x7000 -> when (opcode shr 9 and 0x7) {
|
||||
0 -> fmt("MUL", reg6(), dst()) // MUL
|
||||
1 -> fmt("DIV", reg6(), dst()) // DIV
|
||||
2 -> fmt("ASH", reg6(), dst()) // ASH
|
||||
3 -> fmt("ASHC", reg6(), dst()) // ASHC
|
||||
4 -> fmt("XOR", reg6(), dst()) // XOR
|
||||
5, 6 -> throw InvalidOpcodeException()
|
||||
7 -> fmt("SOB", reg6(), rel6()) // SOB
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
// 0x800 handled above
|
||||
0x9000 -> fmt("MOVB", src(), dst()) // MOVB
|
||||
0xA000 -> fmt("CMPB", src(), dst()) // CMPB
|
||||
0xB000 -> fmt("BITB", src(), dst()) // BITB
|
||||
0xC000 -> fmt("BICB", src(), dst()) // BICB
|
||||
0xD000 -> fmt("BISB", src(), dst()) // BISB
|
||||
0xE000 -> fmt("SUB", src(), dst()) // SUB
|
||||
else -> throw InvalidOpcodeException()
|
||||
}
|
||||
} catch (_: InvalidOpcodeException) {
|
||||
return fmt(".WORD", opcode.toUShort().toString(8))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user