From 78dbcd85003df1067335f7b9768cf64bcdffbe7d Mon Sep 17 00:00:00 2001 From: TQ Hirsch Date: Wed, 27 Sep 2023 17:54:06 +0200 Subject: [PATCH] A bunch of fixes; gets all the way to test 26 --- NOTES.EKBB.md | 4 +- src/main/kotlin/Main.kt | 5 +- src/main/kotlin/com/thequux/mcpdp/core/CPU.kt | 151 ++++++++++++++---- .../com/thequux/mcpdp/core/PagingUnit.kt | 4 + 4 files changed, 134 insertions(+), 30 deletions(-) diff --git a/NOTES.EKBB.md b/NOTES.EKBB.md index a886d7e..867d4b1 100644 --- a/NOTES.EKBB.md +++ b/NOTES.EKBB.md @@ -4,5 +4,7 @@ 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 - +# Test 014 +## PC=12136 CC's did not load properly +This is actually a bug in the exerciser: diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 12fead2..cec8d8a 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -37,7 +37,10 @@ fun main(args: Array) { cpu.runState = CPU.RunState.RUNNING cpu.pc = 0x80u val start = System.nanoTime() - val ninsn = cpu.run(600000000) +// val ninsn = cpu.run(600000000) + var ninsn = cpu.run(30000) +// cpu.tracer = tracer +// ninsn += cpu.run(100) val end = System.nanoTime() System.err.println("Halted at 0${cpu.pc.toString(8)}") diff --git a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt index 19d875f..66f7366 100644 --- a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt +++ b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt @@ -2,7 +2,6 @@ package com.thequux.mcpdp.core import com.thequux.mcpdp.ext.bit.* import com.thequux.mcpdp.peripheral.MemBus -import com.thequux.mcpdp.debug.Disassembler import com.thequux.mcpdp.debug.ITracer import com.thequux.mcpdp.debug.NullTracer import com.thequux.mcpdp.util.ProgrammerError @@ -17,7 +16,7 @@ import java.lang.StringBuilder /// Exxx: ROM /// xxxx: rest @OptIn(ExperimentalUnsignedTypes::class) -class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { +class CPU(val mbus: MemBus, var tracer: ITracer = NullTracer()) { companion object { val PADDR_REG_BIT: Int = 23 @@ -230,8 +229,38 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { pc = registers[5] registers[5] = stack_pop() } // MARK - 1 -> { throw InvalidOpcodeException() } // MFPI // TODO - 2 -> { throw InvalidOpcodeException() } // MTPI // TODO + 1 -> { + val src = opc_dst(opcode) + val v = if (is_paddr_reg(src)) { + if (src and 7u == 6u && prv_mode != cur_mode) { + shadow_r6[prv_mode] + } else + registers[src.toInt() and 7] + } else { + // memory ref + core.getSpace(prv_mode).getw(src.toUShort(), dspace = false) + } + stack_push(v) + N = v bit 15 + Z = v == 0u.toUShort() + V = false + } // MFPI // TODO + 2 -> { + val v = stack_pop() + val dest = opc_dst(opcode) + if (is_paddr_reg(dest)) { + if (dest and 7u == 6u && prv_mode != cur_mode) { + shadow_r6[prv_mode] = v + } else + registers[dest.toInt() and 7] = v + } else { + // memory ref + core.getSpace(prv_mode).setw(dest.toUShort(), v, dspace = false) + } + N = v bit 15 + Z = v == 0u.toUShort() + V = false + } // MTPI // TODO 3 -> { op_storw(opc_dst(opcode), if (N) (-1).toUShort() else 0.toUShort()) Z = !N @@ -305,28 +334,49 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { insnTable[0x70] = { opcode -> // MUL val r = opcode shr 6 and 0x7 val src = op_loadw(opc_dst(opcode)).toShort().toInt() - val res = registers[r].toShort().toInt() * src - registers[r bis 1] = (res shr 16).toUShort() - registers[r] = res.toUShort() + val src2 = registers[r].toShort().toInt() + val res = src2 * src + registers[r] = (res shr 16 and 0xFFFF).toUShort() + registers[r bis 0] = (res and 0xFFFF).toUShort() N = res bit 31 Z = res == 0 V = false - C = (res shr 16) == -(res shr 15 and 1) // check if overflow extends the sign bit + C = (res < -0x8000 || res > 0x7FFF) // check if overflow extends the sign bit } // MUL insnTable[0x72] = { opcode -> // DIV val r = opcode shr 6 and 0x7 - val src = op_loadw(opc_dst(opcode)).toInt() - val lho = (registers[r].toUInt() shl 16 or registers[r bis 1].toUInt()).toInt() - if (src != 0) { - val quot = lho / src - val rem = lho % src - registers[r] = quot.toUShort() - registers[r bis 1] = rem.toUShort() - val overflow = quot shr 16 - V = overflow == -(quot shr 15 and 1) // check if overflow extends the sign bit + val divisor = op_loadw(opc_dst(opcode)).toShort().toInt() + val dividend = registers[r].toInt() shl 16 or registers[r bis 0].toInt() +// logger.warn("$dividend / $divisor") +// dumpReg() + if (dividend.toUInt() == 0x8000_0000u && divisor == 1) { + // Undocumented, but simh does this "for 11/70 compatibility" + // 'tis a good question whether this is a bug in ekbb or a bug in simh. + N = true + Z = true + V = true + C = false + } else if (divisor != 0) { + val quot = dividend / divisor + val rem = dividend % divisor + if (quot > 0x7FFF || quot < -0x8000) { + V = true + N = false + C = false + Z = false + } else { + registers[r] = quot.toUShort() + registers[r bis 0] = rem.toUShort() +// logger.warn("$dividend / $divisor = $quot x + $rem") +// V = overflow != -(quot shr 15 and 1) // check if overflow extends the sign bit + V = false + } N = quot bit 15 Z = quot == 0 + C = false } else { + N = false + Z = true C = true V = true } @@ -543,8 +593,38 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { } // RORB, ROLB, ASRB, ASLB insnTable[0x8D] = { opcode -> when (opcode shr 6 and 3) { - 1 -> { throw InvalidOpcodeException() } // MFPD // TODO - 2 -> { throw InvalidOpcodeException() } // MTPD // TODO + 1 -> { + val src = opc_dst(opcode) + val v = if (is_paddr_reg(src)) { + if (src and 7u == 6u && prv_mode != cur_mode) { + shadow_r6[prv_mode] + } else + registers[src.toInt() and 7] + } else { + // memory ref + core.getSpace(prv_mode).getw(src.toUShort(), dspace = true) + } + stack_push(v) + N = v bit 15 + Z = v == 0u.toUShort() + V = false + } // MFPD // TODO + 2 -> { + val v = stack_pop() + val dest = opc_dst(opcode) + if (is_paddr_reg(dest)) { + if (dest and 7u == 6u && prv_mode != cur_mode) { + shadow_r6[prv_mode] = v + } else + registers[dest.toInt() and 7] = v + } else { + // memory ref + core.getSpace(prv_mode).setw(dest.toUShort(), v, dspace = true) + } + N = v bit 15 + Z = v == 0u.toUShort() + V = false + } // MTPD // TODO else -> { throw InvalidOpcodeException() } // Reserved } } // MFPD, MTPD @@ -703,16 +783,16 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { } private var pirq: UShort = 0u set(value) { - val bitset = pirq shr 8 - var maxp: UShort = 0u - for (i in 7 downTo 1) { - if (bitset bit i) { - maxp = i.toUShort() shl 1 - break + val bitset = value shr 8 + var maxp: UShort = 0u + for (i in 7 downTo 1) { + if (bitset bit i) { + maxp = i.toUShort() shl 1 + break + } } + field = value and 0xFE00u or maxp or (maxp shl 4) } - field = value and 0xFE00u or maxp or (maxp shl 4) - } private var cpu_err: UShort = 0u set(value) { field = value and 0xFCu } @@ -734,6 +814,21 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { core.mount(mbus.unibus) } + fun dumpReg() { + val r = StringBuilder() + r.append("PC=${registers[7].toOctal()} ") + for (i in 0..5) { + r.append("R$i=${registers[i].toOctal()} ") + } + r.append("SP=${registers[6].toOctal()} ") + r.append("CC=") + r.append(if (N) 'N' else '-') + r.append(if (Z) 'Z' else '-') + r.append(if (V) 'V' else '-') + r.append(if (C) 'C' else '-') + logger.info("Regs: {}", r) + } + 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 op_resolve(operand: Int, src: Boolean, byte_mode: Boolean = false): UInt { @@ -944,7 +1039,7 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) { private inner class Registers: PAddressSpace { override fun getw(addr: UInt): UShort = when (addr) { - 0x3FF78u -> 0u // Console switch/display + 0x3FF78u -> 0x70u // Console switch/display 0x3FFE6u -> control_reg 0x3FFF0u -> (mbus.size shr 6).toUShort() 0x3FFF2u -> 0u // upper size diff --git a/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt b/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt index 196f775..f188214 100644 --- a/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt +++ b/src/main/kotlin/com/thequux/mcpdp/core/PagingUnit.kt @@ -144,12 +144,16 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace { modeSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace } + fun getSpace(mode: Int): VAddressSpace = if (mapMode.mmanEnable) modeVTabs[max(mode, 2)] else noMmanSpace + private val itabs: Array = Array(3) { PageTable(if (it == 2) 3 else it, dspace = false) } private val dtabs: Array = Array(3) { PageTable(if (it == 2) 3 else it, dspace = true) } private val modeVTabs: Array = Array(3) { ModeVSpace(itabs[it], dtabs[it], false) } private var noMmanSpace = NoMmanSpace() var modeSpace: VAddressSpace = noMmanSpace private set + var prevSpace: VAddressSpace = noMmanSpace + private set private val unibusTable = UIntArray(32)