Mostly through stack yellow testing
This commit is contained in:
@@ -38,9 +38,9 @@ fun main(args: Array<String>) {
|
|||||||
cpu.pc = 0x80u
|
cpu.pc = 0x80u
|
||||||
val start = System.nanoTime()
|
val start = System.nanoTime()
|
||||||
val ninsn = cpu.run(600000000)
|
val ninsn = cpu.run(600000000)
|
||||||
// var ninsn = cpu.run(30000)
|
// var ninsn = cpu.run(17405)
|
||||||
// cpu.tracer = tracer
|
// cpu.tracer = tracer
|
||||||
// ninsn += cpu.run(100)
|
// ninsn += cpu.run(30)
|
||||||
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)}")
|
||||||
|
@@ -762,6 +762,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
private val general_registers = Array<UShortArray>(2) { UShortArray(6) }
|
private val general_registers = Array<UShortArray>(2) { UShortArray(6) }
|
||||||
private val shadow_r6 = UShortArray(4) //
|
private val shadow_r6 = UShortArray(4) //
|
||||||
private var stack_limit: UShort = 0u
|
private var stack_limit: UShort = 0u
|
||||||
|
private var handlingStackRed: Boolean = false
|
||||||
private var trapReq: Int = 0
|
private var trapReq: Int = 0
|
||||||
val core = PagingUnit(mbus)
|
val core = PagingUnit(mbus)
|
||||||
|
|
||||||
@@ -882,32 +883,40 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
|
|
||||||
private fun is_paddr_reg(addr: UInt): Boolean = addr bit PADDR_REG_BIT
|
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 is_paddr_ispace(addr: UInt): Boolean = addr bit PADDR_ISPACE_BIT
|
||||||
|
|
||||||
|
private inline fun adjust_reg(reg: Int, amount: Int) {
|
||||||
|
val new_val = (registers[reg].toInt() + amount).toUShort()
|
||||||
|
registers[reg] = new_val
|
||||||
|
core.logIncrement(reg, amount)
|
||||||
|
}
|
||||||
private fun op_resolve(operand: Int, src: Boolean, byte_mode: Boolean = false): UInt {
|
private fun op_resolve(operand: Int, src: Boolean, byte_mode: Boolean = false): UInt {
|
||||||
val mode = operand shr 3
|
val mode = operand shr 3 and 0x7
|
||||||
val reg = operand and 0x7
|
val reg = operand and 0x7
|
||||||
val is_pc = reg == 7
|
val is_pc = reg == 7
|
||||||
val increment = if (byte_mode && reg < 6) 1U else 2U
|
val increment = if (byte_mode && reg < 6) 1 else 2
|
||||||
val decoded = 0x80_FFFFu and when (mode and 0x7) {
|
val decoded = 0x80_FFFFu and when (mode) {
|
||||||
0 -> reg.toUInt() bis PADDR_REG_BIT
|
0 -> reg.toUInt() bis PADDR_REG_BIT
|
||||||
1 -> registers[reg].toUInt()
|
1 -> registers[reg].toUInt()
|
||||||
2 -> {
|
2 -> {
|
||||||
val addr = registers[reg]
|
val addr = registers[reg]
|
||||||
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
||||||
registers[reg] = (addr + increment).toUShort()
|
adjust_reg(reg, increment)
|
||||||
addr.toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
addr.toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
||||||
}
|
}
|
||||||
3 -> {
|
3 -> {
|
||||||
val addr = registers[reg]
|
val addr = registers[reg]
|
||||||
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
||||||
registers[reg] = (addr + 2U).toUShort()
|
adjust_reg(reg, 2)
|
||||||
core.getw(addr, dspace = !is_pc).toUInt()
|
core.getw(addr, dspace = !is_pc).toUInt()
|
||||||
}
|
}
|
||||||
4 -> {
|
4 -> {
|
||||||
registers[reg] = (registers[reg] - increment).toUShort()
|
adjust_reg(reg, -increment)
|
||||||
return registers[reg].toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
// if (reg == 6) checkSP(sp)
|
||||||
|
registers[reg].toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
||||||
}
|
}
|
||||||
5 -> {
|
5 -> {
|
||||||
registers[reg] = (registers[reg] - 2U).toUShort()
|
adjust_reg(reg, -2)
|
||||||
|
// if (reg == 6) checkSP(sp)
|
||||||
core.getw(registers[reg], dspace = !is_pc).toUInt()
|
core.getw(registers[reg], dspace = !is_pc).toUInt()
|
||||||
}
|
}
|
||||||
6 -> {
|
6 -> {
|
||||||
@@ -924,6 +933,9 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
}
|
}
|
||||||
else -> throw InvalidOpcodeException() // unreachable
|
else -> throw InvalidOpcodeException() // unreachable
|
||||||
}
|
}
|
||||||
|
if (mode >= 1 && reg == 6) {
|
||||||
|
checkSP(sp)
|
||||||
|
}
|
||||||
return decoded.bit(PADDR_DST_BIT, !src) bis PADDR_ARG_BIT
|
return decoded.bit(PADDR_DST_BIT, !src) bis PADDR_ARG_BIT
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,7 +989,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
|
|
||||||
private fun stack_pop(): UShort = core.getw(sp).also { sp = (sp + 2u).toUShort() }
|
private fun stack_pop(): UShort = core.getw(sp).also { sp = (sp + 2u).toUShort() }
|
||||||
private fun stack_push(value: UShort) {
|
private fun stack_push(value: UShort) {
|
||||||
sp = (sp-2u).toUShort()
|
sp = checkSP((sp-2u).toUShort())
|
||||||
core.setw(sp, value)
|
core.setw(sp, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,6 +1025,18 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun trapRed() {
|
||||||
|
// This is handled separately because otherwise the stack push
|
||||||
|
// would itself trigger a red trap
|
||||||
|
logger.warn("Stack RED")
|
||||||
|
cpu_err = cpu_err or CPU_ERR_STK_RED
|
||||||
|
val old_psw = psw
|
||||||
|
psw = core.getw(6u)
|
||||||
|
core.setw(2u, psw)
|
||||||
|
core.setw(0u, pc)
|
||||||
|
pc = core.getw(4u)
|
||||||
|
}
|
||||||
|
|
||||||
fun step() {
|
fun step() {
|
||||||
if (runState == RunState.HALTED) return
|
if (runState == RunState.HALTED) return
|
||||||
|
|
||||||
@@ -1021,9 +1045,10 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
if (trapReq != 0) {
|
if (trapReq != 0) {
|
||||||
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")
|
||||||
|
callVector(cause.vector)
|
||||||
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
|
trapReq = trapReq and cause.clear.inv() and cause.mask.inv()
|
||||||
// TODO: load MMR2 if necessary
|
// TODO: load MMR2 if necessary
|
||||||
callVector(cause.vector)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1033,7 +1058,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
else if (mbus.unibus.interruptPending) {
|
else if (mbus.unibus.interruptPending) {
|
||||||
for (i in 7 downTo (psw_priority + 1)) {
|
for (i in 7 downTo (psw_priority + 1)) {
|
||||||
if (pirq bit 8 + i) {
|
if (pirq bit 8 + i) {
|
||||||
logger.debug("PIRQ{} trap to 0xA0", i)
|
// logger.debug("PIRQ{} trap to 0xA0", i)
|
||||||
callVector(0xA0u)
|
callVector(0xA0u)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1042,7 +1067,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
// we might have been waiting for an interrupt
|
// we might have been waiting for an interrupt
|
||||||
runState = RunState.RUNNING
|
runState = RunState.RUNNING
|
||||||
val vector = source.vector
|
val vector = source.vector
|
||||||
logger.debug("Unibus interrupt at pri {} to {}", i, vector)
|
// logger.debug("Unibus interrupt at pri {} to {}", i, vector)
|
||||||
callVector(vector)
|
callVector(vector)
|
||||||
source.handled()
|
source.handled()
|
||||||
break
|
break
|
||||||
@@ -1051,7 +1076,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
} else {
|
} else {
|
||||||
val pirqLvl = pirq.toInt() shr 1 and 7;
|
val pirqLvl = pirq.toInt() shr 1 and 7;
|
||||||
if (pirqLvl > psw_priority) {
|
if (pirqLvl > psw_priority) {
|
||||||
logger.debug("PIRQ{} trap to 0xA0", pirqLvl)
|
// logger.debug("PIRQ{} trap to 0xA0", pirqLvl)
|
||||||
callVector(0xA0u)
|
callVector(0xA0u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1061,10 +1086,7 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
return
|
return
|
||||||
} catch (_: MemoryError) {
|
} catch (_: MemoryError) {
|
||||||
// Failed to transfer to vector, treat as STK_RED
|
// Failed to transfer to vector, treat as STK_RED
|
||||||
cur_mode = 0
|
trapRed()
|
||||||
sp = 4u
|
|
||||||
cpu_err = cpu_err or CPU_ERR_STK_RED
|
|
||||||
setTrap(TrapReason.RED)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runState == RunState.WAIT_FOR_INTERRUPT) {
|
if (runState == RunState.WAIT_FOR_INTERRUPT) {
|
||||||
@@ -1090,7 +1112,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) {
|
||||||
@@ -1102,7 +1124,6 @@ class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) {
|
|||||||
var ninsn: Long = 0
|
var ninsn: Long = 0
|
||||||
while (runState == RunState.RUNNING) {
|
while (runState == RunState.RUNNING) {
|
||||||
ninsn += run(Long.MAX_VALUE)
|
ninsn += run(Long.MAX_VALUE)
|
||||||
step()
|
|
||||||
}
|
}
|
||||||
return ninsn
|
return ninsn
|
||||||
}
|
}
|
||||||
@@ -1111,6 +1132,9 @@ 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()) {
|
||||||
|
pc = pc
|
||||||
|
}
|
||||||
step()
|
step()
|
||||||
}
|
}
|
||||||
return ninsn
|
return ninsn
|
||||||
@@ -1162,17 +1186,23 @@ 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) {
|
if (sp >= stack_limit + 256u) {
|
||||||
// we can always assume that this is running in kernel mode, as no stack check occurs in exec or user mode
|
return addr
|
||||||
sp = 4u
|
} else if (sp >= stack_limit + 224u) {
|
||||||
cpu_err = cpu_err or CPU_ERR_STK_RED
|
// if (cpu_err and CPU_ERR_STK_YLW == 0.toUShort()) {
|
||||||
throw Trap(0x04)
|
logger.warn("Stack YLW")
|
||||||
|
// stack limit yellow
|
||||||
|
cpu_err = cpu_err or CPU_ERR_STK_YLW
|
||||||
|
setTrap(TrapReason.YEL)
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
// if (cpu_err and CPU_ERR_STK_RED == 0.toUShort()) {
|
||||||
|
// Don't trigger if already triggered
|
||||||
|
logger.warn("Stack RED")
|
||||||
|
// we can always assume that this is running in kernel mode, as no stack check occurs in exec or user mode
|
||||||
|
trapRed()
|
||||||
|
throw EndCycle()
|
||||||
// stack limit red
|
// stack limit red
|
||||||
} else if (sp < stack_limit + 256u) {
|
|
||||||
// stack limit yellow
|
|
||||||
cpu_err = cpu_err or CPU_ERR_STK_YLW
|
|
||||||
|
|
||||||
// setTRAP(TRAP_YELLOW)
|
|
||||||
}
|
}
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
|
|
||||||
package com.thequux.mcpdp.core
|
package com.thequux.mcpdp.core
|
||||||
|
|
||||||
import com.thequux.mcpdp.ext.bit.bic
|
import com.thequux.mcpdp.ext.bit.*
|
||||||
import com.thequux.mcpdp.ext.bit.bit
|
|
||||||
import com.thequux.mcpdp.ext.bit.shr
|
|
||||||
import com.thequux.mcpdp.ext.bit.toOctal
|
|
||||||
import com.thequux.mcpdp.peripheral.Unibus
|
import com.thequux.mcpdp.peripheral.Unibus
|
||||||
import com.thequux.mcpdp.util.ProgrammerError
|
import com.thequux.mcpdp.util.ProgrammerError
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
@@ -14,29 +11,19 @@ enum class AccessAction {
|
|||||||
Trap,
|
Trap,
|
||||||
Abort,
|
Abort,
|
||||||
}
|
}
|
||||||
enum class ACF(val bin: UShort, val read: AccessAction, val write: AccessAction) {
|
enum class ACF(val read: AccessAction, val write: AccessAction) {
|
||||||
NonResident(0U, AccessAction.Abort, AccessAction.Abort),
|
NonResident(AccessAction.Abort, AccessAction.Abort),
|
||||||
ReadTrap(1U, AccessAction.Trap, AccessAction.Abort),
|
ReadTrap(AccessAction.Trap, AccessAction.Abort),
|
||||||
ReadOnly(2U, AccessAction.Abort, AccessAction.Allow),
|
ReadOnly(AccessAction.Abort, AccessAction.Allow),
|
||||||
Unused1(3U, AccessAction.Abort, AccessAction.Abort),
|
Unused1(AccessAction.Abort, AccessAction.Abort),
|
||||||
TrapAlways(4U, AccessAction.Trap, AccessAction.Trap),
|
TrapAlways(AccessAction.Trap, AccessAction.Trap),
|
||||||
WriteTrap(5U, AccessAction.Allow, AccessAction.Trap),
|
WriteTrap(AccessAction.Allow, AccessAction.Trap),
|
||||||
ReadWrite(6U, AccessAction.Allow, AccessAction.Allow),
|
ReadWrite(AccessAction.Allow, AccessAction.Allow),
|
||||||
Unused2(7U, AccessAction.Abort, AccessAction.Abort);
|
Unused2(AccessAction.Abort, AccessAction.Abort);
|
||||||
|
|
||||||
fun action(writep: Boolean): AccessAction = if (writep) write else read
|
fun action(writep: Boolean): AccessAction = if (writep) write else read
|
||||||
companion object {
|
companion object {
|
||||||
fun fromField(value: UShort): ACF = when ((value and 0x7U).toInt()) {
|
fun fromField(value: UShort): ACF = ACF.entries[value.toInt() and 0x7]
|
||||||
0 -> NonResident
|
|
||||||
1 -> ReadTrap
|
|
||||||
2 -> ReadOnly
|
|
||||||
3 -> Unused1
|
|
||||||
4 -> TrapAlways
|
|
||||||
5 -> WriteTrap
|
|
||||||
6 -> ReadWrite
|
|
||||||
7 -> Unused2
|
|
||||||
else -> throw ProgrammerError("Unreachable")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private data class PDR(val plf: UShort, var A: Boolean, var W: Boolean, var ed: Boolean, var acf: ACF) {
|
private data class PDR(val plf: UShort, var A: Boolean, var W: Boolean, var ed: Boolean, var acf: ACF) {
|
||||||
@@ -70,7 +57,14 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private var mmr = UShortArray(4)
|
private var mmr0: UShort = 0u
|
||||||
|
set(value) {
|
||||||
|
mmrLocked = value and 0xE000u != 0u.toUShort()
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
private var mmr1: UShort = 0u
|
||||||
|
private var mmr2: UShort = 0u
|
||||||
|
private var mmrLocked: Boolean = false
|
||||||
private var enableUnibusMap: Boolean = false
|
private var enableUnibusMap: Boolean = false
|
||||||
private var enable22bit: Boolean = false
|
private var enable22bit: Boolean = false
|
||||||
var memErrorReg: UShort = 0u
|
var memErrorReg: UShort = 0u
|
||||||
@@ -85,15 +79,16 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
|
|
||||||
|
|
||||||
fun setMmr0(causeBit: Int, apf: Int, completed: Boolean = false) {
|
fun setMmr0(causeBit: Int, apf: Int, completed: Boolean = false) {
|
||||||
val reg = mmr[0].toInt()
|
val reg = mmr0.toInt()
|
||||||
val cause_flag = 1 shl causeBit
|
val cause_flag = 1 shl causeBit
|
||||||
if (reg and 0xF000 and -cause_flag == 0) {
|
if (reg and 0xF000 and -cause_flag == 0) {
|
||||||
// no higher priority flags
|
// no higher priority flags
|
||||||
mmr[0] = (reg and 0xF200
|
mmr0 = (reg and 0xF200
|
||||||
or 0x4000 // trap: page length
|
or 0x4000 // trap: page length
|
||||||
or mode.shl(5)
|
or mode.shl(5)
|
||||||
or (if (completed) 0x80 else 0)
|
or (if (completed) 0x80 else 0)
|
||||||
or (if (dspace) 8 else 0)
|
or (if (dspace) 8 else 0)
|
||||||
|
or cause_flag
|
||||||
or apf).toUShort()
|
or apf).toUShort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +132,7 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
|
|
||||||
fun updateMode() {
|
fun updateMode() {
|
||||||
mapMode = when {
|
mapMode = when {
|
||||||
!(mmr[0] bit 0) -> MManMode.MM_16
|
!(mmr0 bit 0) -> MManMode.MM_16
|
||||||
enable22bit -> MManMode.MM_22
|
enable22bit -> MManMode.MM_22
|
||||||
else -> MManMode.MM_18
|
else -> MManMode.MM_18
|
||||||
}
|
}
|
||||||
@@ -146,6 +141,19 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
|
|
||||||
fun getSpace(mode: Int): VAddressSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace
|
fun getSpace(mode: Int): VAddressSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace
|
||||||
|
|
||||||
|
fun logIncrement(register: Int, amount: Int) {
|
||||||
|
assert(register in 0..7)
|
||||||
|
assert(amount in -16..15)
|
||||||
|
if (!mmrLocked)
|
||||||
|
mmr1 = mmr1 shl 8 or register.toUShort() or (amount.toUShort() and 0x1Fu shl 3)
|
||||||
|
}
|
||||||
|
fun newInsn(addr: UShort) {
|
||||||
|
if (!mmrLocked) {
|
||||||
|
mmr1 = 0u
|
||||||
|
mmr2 = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val itabs: Array<PageTable> = Array(3) { PageTable(if (it == 2) 3 else it, dspace = false) }
|
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 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) }
|
private val modeVTabs: Array<ModeVSpace> = Array(3) { ModeVSpace(itabs[it], dtabs[it], false) }
|
||||||
@@ -206,9 +214,9 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
|
|
||||||
override fun getw(addr: UInt): UShort {
|
override fun getw(addr: UInt): UShort {
|
||||||
return when (addr) {
|
return when (addr) {
|
||||||
MMR0 -> mmr[0]
|
MMR0 -> mmr0
|
||||||
MMR1 -> mmr[1]
|
MMR1 -> mmr0
|
||||||
MMR2 -> mmr[2]
|
MMR2 -> mmr0
|
||||||
MMR3 -> {
|
MMR3 -> {
|
||||||
(0U.bit(0, modeVTabs[2].useDSpace)
|
(0U.bit(0, modeVTabs[2].useDSpace)
|
||||||
.bit(1, modeVTabs[1].useDSpace)
|
.bit(1, modeVTabs[1].useDSpace)
|
||||||
@@ -267,13 +275,13 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
enable22bit = false
|
enable22bit = false
|
||||||
enableUnibusMap = false
|
enableUnibusMap = false
|
||||||
modeVTabs[0].useDSpace = false
|
modeVTabs[0].useDSpace = false
|
||||||
modeVTabs[1].useDSpace = false
|
modeVTabs[1].useDSpace = false
|
||||||
modeVTabs[2].useDSpace = false
|
modeVTabs[2].useDSpace = false
|
||||||
mmr[3] = 0u
|
|
||||||
updateMode()
|
updateMode()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -287,7 +295,7 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
|||||||
return if (uaddr > 0x3_0000u) {
|
return if (uaddr > 0x3_0000u) {
|
||||||
// I/O page is always mapped as follows
|
// I/O page is always mapped as follows
|
||||||
addr or 0x3FC000u
|
addr or 0x3FC000u
|
||||||
} else if (mmr[3] bit 5) {
|
} else if (enableUnibusMap) {
|
||||||
unibusTable[(uaddr shr 13).toInt()] + (uaddr and 0x1FFFu) or 0x3C0000U
|
unibusTable[(uaddr shr 13).toInt()] + (uaddr and 0x1FFFu) or 0x3C0000U
|
||||||
} else {
|
} else {
|
||||||
addr
|
addr
|
||||||
|
Reference in New Issue
Block a user