Fixed all ASH and ASHC tests in EKBB

This commit is contained in:
2023-09-27 15:14:09 +02:00
parent 1e994b3f69
commit dfeb859ac3
7 changed files with 146 additions and 72 deletions

8
NOTES.EKBB.md Normal file
View File

@@ -0,0 +1,8 @@
# Test 3
tests reset insn
## RACF E8 BAD
triggered by printer interrupt; unknown root cause. Apparently need to examine DL11 docs to see how it handles RESET

View File

@@ -1,4 +1,5 @@
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.core.util.StatusPrinter
import com.thequux.mcpdp.core.CPU
import com.thequux.mcpdp.debug.LoggingCollector
import com.thequux.mcpdp.debug.NullTracer
@@ -11,6 +12,14 @@ import java.io.File
fun main(args: Array<String>) {
// val lc: LoggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
// StatusPrinter.print(lc)
// print system properties
// for ((name, value) in System.getProperties()) {
// println("${name}=${value}")
// }
val tb = org.jline.terminal.TerminalBuilder.terminal()
var mbus = MemBus(65536)
val tracer = Tracer()

View File

@@ -43,7 +43,7 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
} // RTI
0x0003 -> trap(0x0Cu) // BPT
0x0004 -> trap(0x10u) // IOT
0x0005 -> throw InvalidOpcodeException() // bus reset TODO: bus init
0x0005 -> mbus.unibus.reset() // bus reset TODO: bus init
0x0006 -> {
// TODO: handle suspending the trace trap
pc = stack_pop()
@@ -226,7 +226,7 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
when (opcode shr 6 and 3) {
0 -> { // MARK
val count = opcode and 0x3F
sp = (sp + (2 * count).toUInt()).toUShort()
sp = (pc + (2 * count).toUInt()).toUShort()
pc = registers[5]
registers[5] = stack_pop()
} // MARK
@@ -337,26 +337,33 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
val src = registers[r].toShort().toInt() // two casts to sign extend
count = count sex 6
V = false
val res = if (count > 0) {
C = (src shl (count-1)) bit 15
val shifted = if (count < 16) {
src shr 16-count
} else {
val res = when {
count > 15 -> {
C = (count == 16 && src bit 0)
0
}
count > 0 -> {
C = src bit 16-count
src shl count
}
count < -15 -> {
C = src bit 15
src shr 8 shr 8
}
count < 0 -> {
count = -count
C = src bit (count-1)
src shr count
}
else -> {
C = false
src
}
V = (shifted != 0) and (shifted != -1)
src shl count
} else if (count < 0) {
count = -count
C = (src shr (count-1)) bit 0
src shr count
} else {
C = false
src
}
}.toShort()
registers[r] = res.toUShort()
V = (src xor res.toInt()) bit 15
N = res < 0
Z = res == 0
Z = res == 0.toShort()
} // ASH
insnTable[0x76] = { opcode -> // ASHC
val r = opcode shr 6 and 0x7
@@ -364,10 +371,11 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
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) {
C = (src shl (count-1)) bit 31
val shifted = src shr 32-count
V = (shifted != 0) and (shifted != -1)
C = (src shl (count - 1)) bit 31
src shl count
} else if (count == -32) {
C = src bit 31
src shr 16 shr 16
} else if (count < 0) {
count = -count
C = (src shr (count-1)) bit 0
@@ -376,10 +384,11 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
C = false
src
}
registers[r] = (res and 0xFFFF).toUShort()
registers[r or 1] = (res shr 16 and 0xFFFF).toUShort()
registers[r] = (res shr 16).toUShort()
registers[r or 1] = (res).toUShort()
N = res < 0
Z = res == 0
V = (src xor res) bit 31
} // ASHC
insnTable[0x78] = {opcode -> // XOR
val r = opcode shr 6 and 7

View File

@@ -4,6 +4,7 @@ package com.thequux.mcpdp.core
import com.thequux.mcpdp.ext.bit.bic
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.util.ProgrammerError
import kotlin.math.max
@@ -60,10 +61,19 @@ private enum class MManMode(val mmanEnable: Boolean, val addrMask: UInt, val hip
@OptIn(ExperimentalUnsignedTypes::class)
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
private val MEMORY_ERROR_REG: UInt = 0x3FFE4u
}
private var mmr = UShortArray(4)
private var enableUnibusMap: Boolean = false
private var enable22bit: Boolean = false
var memErrorReg: UShort = 0u
private var mapMode: MManMode = MManMode.MM_16
/// The 18-bit address space exposed to peripherals
@@ -172,13 +182,6 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
override fun setw(addr: UShort, value: UShort, dspace: Boolean) = pspace.setw(map(addr), value)
}
companion object {
private val MMR0: UInt = 0x3FF8Au
private val MMR1: UInt = 0x3FF8Cu
private val MMR2: UInt = 0x3FF8Eu
private val MMR3: UInt = 0x3F54Eu
}
private fun <E> withRecovery(addr: UShort, op: PagingUnit.() -> E): E {
try {
return this.op()
@@ -197,40 +200,50 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
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)
.bit(2, modeVTabs[0].useDSpace)
.bit(4, enable22bit)
.bit(5, enableUnibusMap)
.toUShort())
} // 772516 MMR3
else -> throw BusTimeoutError(addr)
override fun getw(addr: UInt): UShort {
return when (addr) {
MMR0 -> mmr[0]
MMR1 -> mmr[1]
MMR2 -> mmr[2]
MMR3 -> {
(0U.bit(0, modeVTabs[2].useDSpace)
.bit(1, modeVTabs[1].useDSpace)
.bit(2, modeVTabs[0].useDSpace)
.bit(4, enable22bit)
.bit(5, enableUnibusMap)
.toUShort())
} // 772516 MMR3
MEMORY_ERROR_REG -> memErrorReg
else -> throw BusTimeoutError(addr)
}
}
override fun setw(addr: UInt, value: UShort): Unit = when(addr) {
MMR3 -> {
enableUnibusMap = value bit 5
enable22bit = value bit 4
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()
val hiWord = addr bit 1
if (hiWord) {
unibusTable[uaddr] = unibusTable[uaddr] and 0xFFFFu or (value.toUInt() and 0x3Fu shl 16)
} else {
unibusTable[uaddr] = unibusTable[uaddr] and 0xFFFF_0000u or (value.toUInt() bic 0)
override fun setw(addr: UInt, value: UShort): Unit {
return when(addr) {
MMR3 -> {
enableUnibusMap = value bit 5
enable22bit = value bit 4
modeVTabs[0].useDSpace = value bit 2
modeVTabs[1].useDSpace = value bit 1
modeVTabs[2].useDSpace = value bit 0
updateMode()
}
} // 770200..770377 Unibus map
else -> throw BusTimeoutError(addr)
MEMORY_ERROR_REG -> {
memErrorReg = memErrorReg and value.inv()
}
in 0x3F080u..0x3F0FFu -> {
val uaddr = (addr shr 1 and 31u).toInt()
val hiWord = addr bit 1
if (hiWord) {
unibusTable[uaddr] = unibusTable[uaddr] and 0xFFFFu or (value.toUInt() and 0x3Fu shl 16)
} else {
unibusTable[uaddr] = unibusTable[uaddr] and 0xFFFF_0000u or (value.toUInt() bic 0)
}
} // 770200..770377 Unibus map
else -> throw BusTimeoutError(addr)
}
}
}
@@ -246,6 +259,7 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
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)
}
}
@@ -265,12 +279,18 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
}
}
override fun getw(addr: UInt): UShort = pspace.getw(map(addr))
override fun getb(addr: UInt): UByte = pspace.getb(map(addr))
override fun setw(addr: UInt, value: UShort) = pspace.setw(map(addr), value)
override fun setb(addr: UInt, value: UByte) = pspace.setb(map(addr), value)
private inline fun <E> catchMemoryError(fn: () -> E): E = try {
fn()
} catch (e: MemoryError) {
memErrorReg = memErrorReg or 0x400u
throw e
}
override fun getw(addr: UInt): UShort = catchMemoryError { pspace.getw(map(addr)) }
override fun getb(addr: UInt): UByte = catchMemoryError { pspace.getb(map(addr)) }
override fun setw(addr: UInt, value: UShort) = catchMemoryError { pspace.setw(map(addr), value) }
override fun setb(addr: UInt, value: UByte) = catchMemoryError { pspace.setb(map(addr), value) }
}
}

View File

@@ -57,8 +57,8 @@ import kotlin.math.min
/*inline*/ infix fun Int.bis(n: Int): Int = this.or(1 shl n)
/*inline*/ infix fun Int.bic(n: Int): Int = this and (1 shl n).inv()
/*inline*/ infix fun Int.sex(n: Int): Int {
val sign = 1 shl n+1
return ((this and sign.dec()) - (this and sign))
val sign = this and (1 shl n-1)
return this or -sign
}
/*inline*/ infix fun UInt.bit(n: Int): Boolean = this shr n and 1U != 0U
/*inline*/ fun UInt.bit(n: Int, v: Boolean): UInt = if (v) this bis n else this bic n

View File

@@ -39,8 +39,18 @@ class DL11(private var istr: InputStream, private val ostr: OutputStream, val re
constructor(unibus: Unibus, istr: InputStream, ostr: OutputStream): this(istr, ostr, 0x3FF70u, 0x30u, unibus)
override fun reset() {
rcsr = 0x0u
rcsr = 0x0u
// xcsr = 0x80u
intrRcv.level = false
intrXmit.level = false
}
override fun mount(bus: Unibus) {
bus.attach(reg_base, 3, this)
bus.addDevice(this)
}
override fun service() { }

View File

@@ -77,29 +77,47 @@ class Unibus: PAddressSpace, Subregion(12, 6) {
private val logger = LoggerFactory.getLogger(this.javaClass)
private val queue: Array<MutableList<InterruptSource>> = Array(8) { Vector(4) }
private val devices: HashSet<Peripheral> = HashSet()
private var interruptCount: Int = 0
val interruptPending: Boolean
get() = interruptCount > 0
override fun map(address: UInt): PAddressSpace =
super.map(address) ?: throw BusTimeoutError(address)
private fun shouldTrace(addr: UInt): Boolean {
if (!logger.isTraceEnabled) return false
if (addr and 0x3FFF8u == 0x3FF70u) return false
return true
}
override fun getw(addr: UInt): UShort {
if (logger.isTraceEnabled) logger.trace("DATIW ${addr.toOctal()}")
if (shouldTrace(addr)) logger.trace("DATIW ${addr.toOctal()}")
return map(addr).getw(addr)
}
override fun getb(addr: UInt): UByte {
if (logger.isTraceEnabled) logger.trace("DATIB ${addr.toOctal()}")
if (shouldTrace(addr)) logger.trace("DATIB ${addr.toOctal()}")
return map(addr).getb(addr)
}
override fun setw(addr: UInt, value: UShort) {
if (logger.isTraceEnabled) logger.trace("DATOW ${addr.toOctal()} <- ${value.toOctal()}")
if (shouldTrace(addr)) logger.trace("DATOW ${addr.toOctal()} <- ${value.toOctal()}")
map(addr).setw(addr, value)
}
override fun setb(addr: UInt, value: UByte) {
if (logger.isTraceEnabled) logger.trace("DATOB ${addr.toOctal()} <- ${value.toOctal()}")
if (shouldTrace(addr)) logger.trace("DATOB ${addr.toOctal()} <- ${value.toOctal()}")
map(addr).setb(addr, value)
}
fun reset() {
for (dev in devices) {
dev.reset()
}
}
fun addDevice(dev: Peripheral) {
devices.add(dev)
}
/// Request that the processor service an interrupt. When the interrupt is handled, calls getVector() on the device
/// to fetch the currently desired interrupt vector
fun assertInterrupt(priority: Int, device: InterruptSource) {