Started implementing page tables
This commit is contained in:
@@ -37,10 +37,11 @@ fun main(args: Array<String>) {
|
||||
cpu.runState = CPU.RunState.RUNNING
|
||||
cpu.pc = 0x80u
|
||||
val start = System.nanoTime()
|
||||
val ninsn = cpu.run(600000000)
|
||||
// var ninsn = cpu.run(17405)
|
||||
// cpu.tracer = tracer
|
||||
// ninsn += cpu.run(30)
|
||||
// var ninsn = cpu.run(600000000)
|
||||
var ninsn = cpu.run(376670)
|
||||
cpu.tracer = tracer
|
||||
ninsn += cpu.run(30)
|
||||
cpu.dumpReg()
|
||||
val end = System.nanoTime()
|
||||
|
||||
System.err.println("Halted at 0${cpu.pc.toString(8)}")
|
||||
|
@@ -9,7 +9,7 @@ import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.lang.StringBuilder
|
||||
|
||||
private enum class TrapReason(val vector: UShort, val load_mmr2: Boolean, val clear: Int) {
|
||||
internal enum class TrapReason(val vector: UShort, val load_mmr2: Boolean, val clear: Int) {
|
||||
/** Floating point error */
|
||||
FPE(0xA4u, true, 0),
|
||||
/** Power fail */
|
||||
@@ -93,9 +93,9 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
mbus.unibus.reset()
|
||||
} // bus reset TODO: bus init
|
||||
0x0006 -> {
|
||||
// TODO: handle suspending the trace trap
|
||||
pc = stack_pop()
|
||||
psw = stack_pop()
|
||||
allowT = false
|
||||
} // RTT
|
||||
in 0x40..0x7f -> {
|
||||
// jmp
|
||||
@@ -747,6 +747,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
}
|
||||
}
|
||||
|
||||
private var allowT: Boolean = true
|
||||
private var control_reg: UShort = 0u
|
||||
val logger: Logger = LoggerFactory.getLogger(this.javaClass)
|
||||
private val flagStr: String
|
||||
@@ -764,7 +765,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
private var stack_limit: UShort = 0u
|
||||
private var handlingStackRed: Boolean = false
|
||||
private var trapReq: Int = 0
|
||||
val core = PagingUnit(mbus)
|
||||
val core = PagingUnit(mbus, this)
|
||||
|
||||
var runState: RunState = RunState.HALTED
|
||||
var psw: UShort
|
||||
@@ -1005,10 +1006,12 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
fun step_int() {
|
||||
try {
|
||||
tracer.noteBegin(this)
|
||||
core.newInsn(pc)
|
||||
val opcode = core.getw(pc).toInt()
|
||||
tracer.noteOpcode(opcode.toUShort())
|
||||
pc = (pc + 2u).toUShort()
|
||||
this.(insnTable[opcode shr 8])(opcode)
|
||||
core.endInsn()
|
||||
} finally {
|
||||
tracer.noteEnd()
|
||||
}
|
||||
@@ -1034,6 +1037,8 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
psw = core.getw(6u)
|
||||
core.setw(2u, psw)
|
||||
core.setw(0u, pc)
|
||||
sp = 0u
|
||||
trapReq = trapReq and TrapReason.RED.clear.inv()
|
||||
pc = core.getw(4u)
|
||||
}
|
||||
|
||||
@@ -1046,8 +1051,11 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
for (cause in TrapReason.entries.reversed()) {
|
||||
if (trapReq and cause.mask != 0) {
|
||||
// logger.warn("Trapping because $cause")
|
||||
callVector(cause.vector)
|
||||
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
|
||||
try {
|
||||
callVector(cause.vector)
|
||||
} finally {
|
||||
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
|
||||
}
|
||||
// TODO: load MMR2 if necessary
|
||||
break
|
||||
}
|
||||
@@ -1096,6 +1104,10 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
// Proceed to handling instruction
|
||||
try {
|
||||
step_int()
|
||||
if (T && allowT) {
|
||||
setTrap(TrapReason.TRC)
|
||||
}
|
||||
allowT = true
|
||||
} catch (error: MemoryError) {
|
||||
// TODO: fill in memory manager fields
|
||||
when (error) {
|
||||
@@ -1112,7 +1124,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
setTrap(TrapReason.NXM)
|
||||
}
|
||||
}
|
||||
// logger.warn("Threw error: $error")
|
||||
logger.warn("Threw error: $error")
|
||||
} catch (_: InvalidOpcodeException) {
|
||||
setTrap(TrapReason.ILL)
|
||||
} catch (_: EndCycle) {
|
||||
@@ -1132,7 +1144,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
var ninsn: Long = 0
|
||||
while (runState == RunState.RUNNING && ninsn < nstep) {
|
||||
ninsn++
|
||||
if (pc == 0x1F76u.toUShort()) {
|
||||
if (pc == 0x344A.toUShort()) {
|
||||
pc = pc
|
||||
}
|
||||
step()
|
||||
@@ -1149,7 +1161,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
pc = core.getw(vector)
|
||||
}
|
||||
|
||||
private fun setTrap(reason: TrapReason) {
|
||||
internal fun setTrap(reason: TrapReason) {
|
||||
trapReq = trapReq or reason.mask
|
||||
}
|
||||
|
||||
@@ -1187,7 +1199,6 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
||||
fun checkSP(addr: UShort): UShort {
|
||||
if (cur_mode != 0) return addr
|
||||
if (sp < stack_limit + 224u || sp.toInt() and 0xFFFE == 0xFFFE) {
|
||||
logger.warn("Stack RED")
|
||||
trapRed()
|
||||
throw EndCycle()
|
||||
} else if (sp < stack_limit + 256u) {
|
||||
|
@@ -36,6 +36,9 @@ private data class PDR(val plf: UShort, var A: Boolean, var W: Boolean, var ed:
|
||||
} else {
|
||||
0U..< (plf.toUInt() shl 6)
|
||||
}
|
||||
|
||||
val asU16: UShort
|
||||
get() = (plf shl 7).bit(7, A).bit(6, W).bit(3, ed) or acf.ordinal.toUShort()
|
||||
fun touched() { A = true }
|
||||
fun written() { A = true; W = true }
|
||||
}
|
||||
@@ -47,11 +50,11 @@ private enum class MManMode(val mmanEnable: Boolean, val addrMask: UInt, val hip
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
class PagingUnit(val pspace: PAddressSpace, val cpu: CPU): VAddressSpace {
|
||||
companion object {
|
||||
private val MMR0: UInt = 0x3FF8Au
|
||||
private val MMR1: UInt = 0x3FF8Cu
|
||||
private val MMR2: UInt = 0x3FF8Eu
|
||||
private val MMR0: UInt = 0x3FF7Au
|
||||
private val MMR1: UInt = 0x3FF7Cu
|
||||
private val MMR2: UInt = 0x3FF7Eu
|
||||
private val MMR3: UInt = 0x3F54Eu
|
||||
private val MEMORY_ERROR_REG: UInt = 0x3FFE4u
|
||||
}
|
||||
@@ -102,17 +105,20 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
if (addr and 0x1FFFU !in pdr.range) {
|
||||
setMmr0(14, apf)
|
||||
// TODO: handle rest of trap
|
||||
throw Trap(0xA8)
|
||||
cpu.setTrap(TrapReason.MME)
|
||||
// TODO: check whether this is always an abort
|
||||
throw EndCycle()
|
||||
}
|
||||
when (pdr.acf.action(write)) {
|
||||
AccessAction.Allow -> {}
|
||||
AccessAction.Trap -> {
|
||||
setMmr0(12, apf, true)
|
||||
trap = true
|
||||
setMmr0(12, apf)
|
||||
cpu.setTrap(TrapReason.MME)
|
||||
}
|
||||
AccessAction.Abort -> {
|
||||
setMmr0(13, apf)
|
||||
throw Trap(0xA8)
|
||||
cpu.setTrap(TrapReason.MME)
|
||||
throw EndCycle()
|
||||
}
|
||||
}
|
||||
val tmp1 = addr.toUInt() + (par.toUInt() shl 6) and mapMode.addrMask
|
||||
@@ -210,8 +216,36 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
|
||||
override fun setb(addr: UShort, value: UByte) = withRecovery(addr) { modeSpace.setb(addr, value) }
|
||||
|
||||
private class PdPair(val ipt: PageTable, val dpt: PageTable): PAddressSpace {
|
||||
override fun getw(addr: UInt): UShort {
|
||||
val mode = addr.toInt() shr 4 and 3
|
||||
val reg = addr.toInt() shr 1 and 7
|
||||
return when (mode) {
|
||||
0 -> ipt.pdr[reg].asU16
|
||||
1 -> dpt.pdr[reg].asU16
|
||||
2 -> ipt.par[reg]
|
||||
3 -> dpt.par[reg]
|
||||
else -> throw BusTimeoutError(addr)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setw(addr: UInt, value: UShort) {
|
||||
val mode = addr.toInt() shr 4 and 3
|
||||
val reg = addr.toInt() shr 1 and 7
|
||||
when (mode) {
|
||||
0 -> ipt.pdr[reg] = PDR(value) // This clears A and W
|
||||
1 -> dpt.pdr[reg] = PDR(value) // This clears A and W
|
||||
2 -> ipt.par[reg] = value
|
||||
3 -> dpt.par[reg] = value
|
||||
else -> throw BusTimeoutError(addr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private inner class ConfigRegisters: PAddressSpace {
|
||||
|
||||
|
||||
override fun getw(addr: UInt): UShort {
|
||||
return when (addr) {
|
||||
MMR0 -> mmr0
|
||||
@@ -232,6 +266,12 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
|
||||
override fun setw(addr: UInt, value: UShort): Unit {
|
||||
return when(addr) {
|
||||
MMR0 -> {
|
||||
mmr0 = value
|
||||
updateMode()
|
||||
}
|
||||
MMR1 -> mmr1 = value
|
||||
MMR2 -> mmr2 = value
|
||||
MMR3 -> {
|
||||
enableUnibusMap = value bit 5
|
||||
enable22bit = value bit 4
|
||||
@@ -260,16 +300,25 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
|
||||
}
|
||||
|
||||
// Page space
|
||||
// 772 200-217 = SUP I PDR
|
||||
// 772 220-237 = SUP D PDR
|
||||
// 772 240-257 = SUP I PAR
|
||||
// 772 260-277 = SUP D PAR
|
||||
//
|
||||
// 772 300-377 = KRN same
|
||||
// 777 600-677 = USR same
|
||||
|
||||
fun mount(unibus: Unibus) {
|
||||
val regs = ConfigRegisters()
|
||||
unibus.run {
|
||||
deviceView = UnibusMap()
|
||||
attach(0x3_FF80u, 6, regs) // User PAR/PDR
|
||||
attach(0x3_F480u, 6, PdPair(itabs[0], dtabs[0]))
|
||||
attach(0x3_F4C0u, 6, PdPair(itabs[1], dtabs[1]))
|
||||
attach(0x3_FF80u, 6, PdPair(itabs[2], dtabs[2])) // User PAR/PDR
|
||||
attach(0x3_FF7Au, 1, regs) // MMR0
|
||||
attach(0x3_FF7Cu, 2, regs) // MMR1-2
|
||||
attach(0x3_F54Eu, 1, regs) // MMR3
|
||||
attach(0x3_F4C0u, 6, regs) // Kernal PAR/PDF
|
||||
attach(0x3_F480u, 6, regs) // Supervisor PAR/PDR
|
||||
attach(0x3_F080u, 7, regs) // Unibus map
|
||||
attach(MEMORY_ERROR_REG, 1, regs)
|
||||
}
|
||||
@@ -286,6 +335,10 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
|
||||
}
|
||||
|
||||
fun endInsn() {
|
||||
mmr0 = mmr0 or 0x70u
|
||||
}
|
||||
|
||||
|
||||
private inner class UnibusMap: PAddressSpace {
|
||||
// This implements an *18-bit* address space, for the view of unibus peripherals
|
||||
|
@@ -38,7 +38,7 @@ class MemBus(val size: Int) : PAddressSpace {
|
||||
}
|
||||
|
||||
override fun getw(addr: UInt): UShort {
|
||||
if (size bit 0) {
|
||||
if (addr bit 0) {
|
||||
throw OddAddressError(addr)
|
||||
}
|
||||
return when (addr.toInt()) {
|
||||
@@ -49,7 +49,7 @@ class MemBus(val size: Int) : PAddressSpace {
|
||||
}
|
||||
|
||||
override fun setw(addr: UInt, value: UShort) {
|
||||
if (size bit 0) {
|
||||
if (addr bit 0) {
|
||||
throw OddAddressError(addr)
|
||||
}
|
||||
return when (addr.toInt()) {
|
||||
|
Reference in New Issue
Block a user