A bunch of fixes; gets all the way to test 26
This commit is contained in:
@@ -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:
|
||||
|
||||
|
@@ -37,7 +37,10 @@ fun main(args: Array<String>) {
|
||||
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)}")
|
||||
|
@@ -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
|
||||
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 1] = rem.toUShort()
|
||||
val overflow = quot shr 16
|
||||
V = overflow == -(quot shr 15 and 1) // check if overflow extends the sign bit
|
||||
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,7 +783,7 @@ class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
|
||||
}
|
||||
private var pirq: UShort = 0u
|
||||
set(value) {
|
||||
val bitset = pirq shr 8
|
||||
val bitset = value shr 8
|
||||
var maxp: UShort = 0u
|
||||
for (i in 7 downTo 1) {
|
||||
if (bitset bit i) {
|
||||
@@ -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
|
||||
|
@@ -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<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 modeVTabs: Array<ModeVSpace> = 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)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user