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