diff --git a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt index ce4a76e..3a65fb6 100644 --- a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt +++ b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt @@ -42,7 +42,12 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { } // RTI 0x0003 -> trap(0x0Cu) // BPT 0x0004 -> trap(0x10u) // IOT - 0x0005 -> mbus.unibus.reset() // bus reset TODO: bus init + 0x0005 -> { + stack_limit = 0u + pirq = 0u + core.reset() + mbus.unibus.reset() + } // bus reset TODO: bus init 0x0006 -> { // TODO: handle suspending the trace trap pc = stack_pop() @@ -225,7 +230,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { when (opcode shr 6 and 3) { 0 -> { // MARK val count = opcode and 0x3F - sp = (pc + (2 * count).toUInt()).toUShort() + sp = check_sp((pc + (2 * count).toUInt()).toUShort()) pc = registers[5] registers[5] = stack_pop() } // MARK @@ -712,6 +717,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { private val registers = UShortArray(8) private val general_registers = Array(2) { UShortArray(6) } private val shadow_r6 = UShortArray(4) // + private var stack_limit: UShort = 0u val core = PagingUnit(mbus) var runState: RunState = RunState.HALTED @@ -1046,7 +1052,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { 0x3FFF4u -> 0x1170u // system ID 0x3FFF6u -> cpu_err 0x3FFFAu -> pirq // PIRQ - 0x3FFFCu -> 0x0u // stack limit + 0x3FFFCu -> stack_limit // stack limit 0x3FFFEu -> psw else -> throw BusTimeoutError(addr) } @@ -1059,7 +1065,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { 0x3_FFF0u , 0x3_FFF2u , 0x3_FFF4u, 0x3_FFF8u -> {} // read-only registers 0x3_FFF6u -> cpu_err = value 0x3_FFFAu -> pirq = value - 0x3_FFFCu -> {} // stack limit + 0x3_FFFCu -> stack_limit = value and 0xFF00u // stack limit 0x3_FFFEu -> psw = value or (cur_mode.toUShort() shl 14) // writing to PSW can only increase current mode else -> { println("Bus error at ${addr.toString(16)}: ${value.toString(16)}") @@ -1068,6 +1074,22 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { } } + fun check_sp(addr: UShort): UShort { + if (cur_mode != 0) return addr + if (sp < stack_limit + 224u) { + // setCPUERR(CPUE_RED) + // we can always assume that this is running in kernel mode, as no stack check occurs in exec or user mode + sp = 4u + throw Trap(0x04) + // stack limit red + } else if (sp < stack_limit + 256u) { + // stack limit yellow + // setTRAP(TRAP_YELLOW) + // setCPUERR(CPUE_YELLOW) + } + return addr + } + enum class RunState(val handleInterrupt: Boolean) { RUNNING(handleInterrupt = true), HALTED(handleInterrupt = false), diff --git a/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt b/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt index f188214..45fe6b6 100644 --- a/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt +++ b/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt @@ -267,6 +267,17 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace { } } + fun reset() { + enable22bit = false + enableUnibusMap = false + modeVTabs[0].useDSpace = false + modeVTabs[1].useDSpace = false + modeVTabs[2].useDSpace = false + mmr[3] = 0u + updateMode() + + } + private inner class UnibusMap: PAddressSpace { // This implements an *18-bit* address space, for the view of unibus peripherals