diff --git a/.idea/misc.xml b/.idea/misc.xml index d737538..5a452ce 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -20,7 +20,7 @@ - + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 5ef9a49..4e91771 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,7 +29,7 @@ tasks.test { } kotlin { - jvmToolchain(8) + jvmToolchain(19) } application { diff --git a/settings.gradle.kts b/settings.gradle.kts index f38c4ca..a37eb65 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,4 +9,4 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0" } -rootProject.name = "mc-pdp" \ No newline at end of file +rootProject.name = "jdp11" \ No newline at end of file diff --git a/src/main/kotlin/com/thequux/mcpdp/RT11Loader.kt b/src/main/kotlin/com/thequux/mcpdp/Loader.kt similarity index 80% rename from src/main/kotlin/com/thequux/mcpdp/RT11Loader.kt rename to src/main/kotlin/com/thequux/mcpdp/Loader.kt index 74e48c0..9889246 100644 --- a/src/main/kotlin/com/thequux/mcpdp/RT11Loader.kt +++ b/src/main/kotlin/com/thequux/mcpdp/Loader.kt @@ -4,18 +4,22 @@ import com.thequux.mcpdp.core.CPU import com.thequux.mcpdp.core.PAddressSpace import com.thequux.mcpdp.ext.bit.bit import com.thequux.mcpdp.ext.bit.shl +import org.slf4j.LoggerFactory import java.io.File +import kotlin.math.log /// Loads an RT-11 object file into memory fun CPU.loadAbs(infile: File) { + + val logger = LoggerFactory.getLogger("AbsLoader") + val core = this.core.modeSpace val inStream = infile.inputStream() var buf = ByteArray(6) - var offset = 0 - var addr: UShort = 0u - var len: Int = 0 - var cksum: Int = 0 + var addr: UShort + var len: Int + var cksum: Int var pos = 0 @@ -53,20 +57,21 @@ fun CPU.loadAbs(infile: File) { if (buf.size < len+1) { buf = ByteArray(len+1) } - System.err.println("Reading ${len+1} bytes into ${buf.size}") inStream.read(buf, 0, len+1) for (i in 0..len) { cksum += buf[i] } cksum = cksum and 0xFF - // TODO: validate checksum == 0 - println("Loading 0x${len.toString(16)} bytes at 0x${addr.toString(16)}") + if (cksum != 0) { + throw Exception("Incorrect checksum: 0x${cksum.toString(16)}") + } + logger.debug("Loading 0x${len.toString(16)} bytes at 0x${addr.toString(16)}") if (len == 0) { // end of file - println("Tape ended at ${pos+len+7}") + logger.debug("Tape ended at ${pos+len+7}") if (!(addr bit 0)){ this.pc = addr - println("Ready to run") + logger.debug("Ready to run at ${addr.toString(8)}") } return } else { diff --git a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt index b76e44f..3e351c8 100644 --- a/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt +++ b/src/main/kotlin/com/thequux/mcpdp/core/CPU.kt @@ -3,6 +3,8 @@ package com.thequux.mcpdp.core import com.thequux.mcpdp.ext.bit.* import com.thequux.mcpdp.peripheral.MemBus import com.thequux.mcpdp.util.ProgrammerError +import org.slf4j.Logger +import org.slf4j.LoggerFactory /// The main CPU /// @@ -12,6 +14,8 @@ import com.thequux.mcpdp.util.ProgrammerError /// xxxx: rest @OptIn(ExperimentalUnsignedTypes::class) class CPU(val mbus: MemBus) { + + val logger: Logger = LoggerFactory.getLogger(this.javaClass) private val flagStr: String get() { val chars = CharArray(4) { '-' } @@ -130,7 +134,7 @@ class CPU(val mbus: MemBus) { val mode = operand shr 3 val reg = operand and 0x7 val increment = if (byte_mode && reg != 7) 1U else 2U - return when (mode and 0x7) { + return 0x80_FFFFu and when (mode and 0x7) { 0 -> reg.toUInt() bis PADDR_REG_BIT 1 -> registers[reg].toUInt() 2 -> { @@ -227,8 +231,11 @@ class CPU(val mbus: MemBus) { when (opcode and 0xF000) { 0x0, 0x8000 -> when (opcode and 0xFF00) { 0x0000 -> when (opcode) { - 0x0000 -> runState = RunState.HALTED - 0x0001 -> runState = RunState.WAIT_FOR_INTERRUPT + 0x0000 -> { + if (cur_mode == 0) + runState = RunState.HALTED + } // HALT + 0x0001 -> runState = RunState.WAIT_FOR_INTERRUPT // WAIT 0x0002 -> { // RTI pc = stack_pop() psw = stack_pop() // TODO: check privilege on mode; check psw[11] @@ -777,10 +784,10 @@ class CPU(val mbus: MemBus) { // TODO: handle PIRQ for (i in 7 downTo (psw_priority + 1)) { - if (pirq bit 8+i) { - trap(0xA0u) - break - } + if (pirq bit 8+i) { + trap(0xA0u) + break + } val source = mbus.unibus.checkInterrupt(i) if (source != null) { // we might have been waiting for an interrupt @@ -796,6 +803,11 @@ class CPU(val mbus: MemBus) { // TODO: handle T bit } catch (error: MemoryError) { // TODO: fill in memory manager fields + cpu_err = when (error) { + is OddAddressError -> cpu_err or 0x40u + is NonExistentMemoryError -> cpu_err or 0x20u + is BusTimeoutError -> cpu_err or 0x10u + } trap(4u) } catch (_: InvalidOpcodeException) { trap(10u) @@ -820,23 +832,22 @@ class CPU(val mbus: MemBus) { private inner class Registers: PAddressSpace { override fun getw(addr: UInt): UShort = when (addr) { - 0x3FFF0u -> (mbus.size shr 6).toUShort() - 0x3FFF2u -> 0u // upper size - 0x3FFF4u -> 0x1170u // system ID - 0x3FFF6u -> cpu_err - 0x3FFFAu -> pirq // PIRQ - 0x3FFFCu -> 0x0u // stack limit + 0x3FFF0u -> (mbus.size shr 6).toUShort() + 0x3FFF2u -> 0u // upper size + 0x3FFF4u -> 0x1170u // system ID + 0x3FFF6u -> cpu_err + 0x3FFFAu -> pirq // PIRQ + 0x3FFFCu -> 0x0u // stack limit 0x3FFFEu -> psw - else -> throw BusTimeoutError(addr) } override fun setw(addr: UInt, value: UShort) = when (addr) { - 0x3_FFF0u , 0x3_FFF2u , 0x3_FFF4u, 0x3_FFF8u -> {} // read-only registers - 0x3_FFF6u -> cpu_err = value - 0x3_FFFAu -> pirq = value - 0x3_FFFCu -> {} // stack limit - 0x3_FFFEu -> psw = value + 0x3_FFF0u , 0x3_FFF2u , 0x3_FFF4u, 0x3_FFF8u -> {} // read-only registers + 0x3_FFF6u -> cpu_err = value + 0x3_FFFAu -> pirq = value + 0x3_FFFCu -> {} // stack limit + 0x3_FFFEu -> psw = value or (cur_mode.toUShort() shl 14) // writing to PSW can only increase current mode else -> { println("Bus error at ${addr.toString(16)}: ${value.toString(16)}") throw BusTimeoutError(addr) diff --git a/src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt b/src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt index 8530687..aa37b3e 100644 --- a/src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt +++ b/src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt @@ -2,12 +2,10 @@ package com.thequux.mcpdp.tools -import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream import picocli.CommandLine import picocli.CommandLine.Option import picocli.CommandLine.Parameters import java.io.File -import java.util.Hashtable import java.util.concurrent.Callable import java.util.function.Consumer @@ -17,7 +15,6 @@ class Link11: Callable { @Parameters() lateinit var objects: Array - @Option(names = ["-o", "--out"], required = true, description = ["Output file"]) lateinit var outFile: File