Many changes
This commit is contained in:
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.0" />
|
||||
<option name="version" value="1.9.10" />
|
||||
</component>
|
||||
</project>
|
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.9.0"
|
||||
application
|
||||
kotlin("kapt") version "1.9.10"
|
||||
}
|
||||
|
||||
group = "com.thequux"
|
||||
@@ -12,6 +13,10 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
testImplementation(kotlin("test"))
|
||||
|
||||
// For the utilities classes
|
||||
kapt("info.picocli:picocli-codegen:4.7.5")
|
||||
implementation("info.picocli:picocli:4.7.5")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
|
@@ -1,7 +1,3 @@
|
||||
fun main(args: Array<String>) {
|
||||
println("Hello World!")
|
||||
|
||||
// Try adding program arguments via Run/Debug configuration.
|
||||
// Learn more about running applications: https://www.jetbrains.com/help/idea/running-applications.html.
|
||||
println("Program arguments: ${args.joinToString()}")
|
||||
}
|
22
src/main/kotlin/com/thequux/mcpdp/RT11Loader.kt
Normal file
22
src/main/kotlin/com/thequux/mcpdp/RT11Loader.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.thequux.mcpdp
|
||||
|
||||
import com.thequux.mcpdp.core.CPU
|
||||
import com.thequux.mcpdp.core.PAddressSpace
|
||||
import java.io.File
|
||||
|
||||
/// Loads an RT-11 object file into memory
|
||||
fun CPU.loadAbs(infile: File) {
|
||||
val core = this.core.modeSpace
|
||||
val inStream = infile.inputStream().buffered()
|
||||
val buf = ByteArray(6)
|
||||
val
|
||||
while (true) {
|
||||
var read = inStream.read(buf, 0, 6)
|
||||
if (read == 0) {
|
||||
return
|
||||
} else if (read < 6) {
|
||||
|
||||
}
|
||||
if (hdr[0] != 0)
|
||||
}
|
||||
}
|
@@ -11,11 +11,11 @@ import com.thequux.mcpdp.util.ProgrammerError
|
||||
/// Exxx: ROM
|
||||
/// xxxx: rest
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class CPU(private val mbus: MemBus) {
|
||||
class CPU(val mbus: MemBus) {
|
||||
private val registers = UShortArray(8)
|
||||
private val general_registers = Array<UShortArray>(2) { UShortArray(5) }
|
||||
private val shadow_r6 = UShortArray(4) //
|
||||
private val core = PagingUnit(mbus)
|
||||
val core = PagingUnit(mbus)
|
||||
|
||||
var runState: RunState = RunState.HALTED
|
||||
var psw: UShort
|
||||
|
@@ -57,7 +57,6 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
private var mmr = UShortArray(4)
|
||||
private var enableUnibusMap: Boolean = false
|
||||
private var enable22bit: Boolean = false
|
||||
private var enableDSpaceByMode = BooleanArray(4)
|
||||
|
||||
/// The 18-bit address space exposed to peripherals
|
||||
val unibusMap: PAddressSpace = UnibusMap()
|
||||
@@ -108,36 +107,53 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
}
|
||||
|
||||
var mode: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
modeSpace = modeVTabs[if (field == 3) 2 else field]
|
||||
}
|
||||
|
||||
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 var curIspace: PageTable = itabs[0]
|
||||
private var curDspace: PageTable = dtabs[0]
|
||||
private val modeVTabs: Array<ModeVSpace> = Array(3) { ModeVSpace(itabs[it], dtabs[it], false) }
|
||||
var modeSpace: VAddressSpace = modeVTabs[0]
|
||||
private set
|
||||
private val unibusTable = UIntArray(32)
|
||||
|
||||
private fun getSpace(dspace: Boolean): PageTable = if (dspace) curDspace else curIspace
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = pspace.getw(getSpace(dspace).map(addr, write = false))
|
||||
|
||||
override fun getb(addr: UShort): UByte = pspace.getb(curDspace.map(addr, write = false))
|
||||
private inner class ModeVSpace(private val iSpace: PageTable, private val dSpace: PageTable, var useDSpace: Boolean): VAddressSpace {
|
||||
private fun getSpace(dspace: Boolean): PageTable = if (dspace) dSpace else iSpace
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = pspace.getw(getSpace(dspace).map(addr, write = false))
|
||||
|
||||
override fun setw(addr: UShort, value: UShort, dspace: Boolean) {
|
||||
pspace.setw(getSpace(dspace).map(addr, write = true), value)
|
||||
}
|
||||
override fun getb(addr: UShort): UByte = pspace.getb(dSpace.map(addr, write = false))
|
||||
|
||||
override fun setb(addr: UShort, value: UByte) {
|
||||
pspace.setb(curDspace.map(addr, write = true), value)
|
||||
override fun setw(addr: UShort, value: UShort, dspace: Boolean) {
|
||||
pspace.setw(getSpace(dspace).map(addr, write = true), value)
|
||||
}
|
||||
|
||||
override fun setb(addr: UShort, value: UByte) {
|
||||
pspace.setb(dSpace.map(addr, write = true), value)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MMR3: UInt = 0x3F54Eu
|
||||
}
|
||||
|
||||
override fun getw(addr: UShort, dspace: Boolean): UShort = modeSpace.getw(addr, dspace)
|
||||
|
||||
override fun getb(addr: UShort): UByte = modeSpace.getb(addr)
|
||||
|
||||
override fun setw(addr: UShort, value: UShort, dspace: Boolean) = modeSpace.setw(addr, value, dspace)
|
||||
|
||||
override fun setb(addr: UShort, value: UByte) = modeSpace.setb(addr, value)
|
||||
|
||||
private inner class ConfigRegisters: PAddressSpace {
|
||||
|
||||
override fun getw(addr: UInt): UShort = when (addr) {
|
||||
MMR3 -> {
|
||||
(0U.bit(0, enableDSpaceByMode[3])
|
||||
.bit(1, enableDSpaceByMode[1])
|
||||
.bit(2, enableDSpaceByMode[0])
|
||||
(0U.bit(0, modeVTabs[2].useDSpace)
|
||||
.bit(1, modeVTabs[1].useDSpace)
|
||||
.bit(2, modeVTabs[0].useDSpace)
|
||||
.bit(4, enable22bit)
|
||||
.bit(5, enableUnibusMap)
|
||||
.toUShort())
|
||||
@@ -149,9 +165,9 @@ class PagingUnit(val pspace: PAddressSpace): VAddressSpace {
|
||||
MMR3 -> {
|
||||
enableUnibusMap = value bit 5
|
||||
enable22bit = value bit 4
|
||||
enableDSpaceByMode[0] = value bit 2
|
||||
enableDSpaceByMode[1] = value bit 1
|
||||
enableDSpaceByMode[3] = value bit 0
|
||||
modeVTabs[0].useDSpace = value bit 2
|
||||
modeVTabs[1].useDSpace = value bit 1
|
||||
modeVTabs[2].useDSpace = value bit 0
|
||||
}
|
||||
in 0x3F080u..0x3F0FFu -> {
|
||||
val uaddr = (addr shr 1 and 31u).toInt()
|
||||
@@ -178,10 +194,10 @@ 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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private inner class UnibusMap: PAddressSpace {
|
||||
// This implements an *18-bit* address space, for the view of unibus peripherals
|
||||
|
||||
|
@@ -1,82 +1,86 @@
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package com.thequux.mcpdp.ext.bit
|
||||
|
||||
import kotlin.experimental.and
|
||||
import kotlin.math.max
|
||||
|
||||
infix fun Byte.shr(qty: Int): Byte = this.toInt().shr(max(qty, 7)).toByte()
|
||||
infix fun Byte.shl(qty: Int): Byte = if (qty > 7) 0 else this.toInt().shl(qty).toByte()
|
||||
infix fun Byte.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
fun Byte.bit(n: Int, v: Boolean): Byte = if (v) this bis n else this bic n
|
||||
infix fun Byte.bis(n: Int): Byte = this.toInt().or(1 shl n).toByte()
|
||||
infix fun Byte.bic(n: Int): Byte = this.toInt().and(1.shl(n).inv()).toByte()
|
||||
infix fun Byte.sex(n: Int): Byte {
|
||||
inline infix fun Byte.shr(qty: Int): Byte = this.toInt().shr(max(qty, 7)).toByte()
|
||||
inline infix fun Byte.shl(qty: Int): Byte = if (qty > 7) 0 else this.toInt().shl(qty).toByte()
|
||||
inline infix fun Byte.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
inline fun Byte.bit(n: Int, v: Boolean): Byte = if (v) this bis n else this bic n
|
||||
inline infix fun Byte.bis(n: Int): Byte = this.toInt().or(1 shl n).toByte()
|
||||
inline infix fun Byte.bic(n: Int): Byte = this.toInt().and(1.shl(n).inv()).toByte()
|
||||
inline infix fun Byte.sex(n: Int): Byte {
|
||||
val sign = 1.toByte() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toByte()
|
||||
}
|
||||
|
||||
infix fun UByte.shr(qty: Int): UByte = this.toUInt().shr(max(qty, 7)).toUByte()
|
||||
infix fun UByte.shl(qty: Int): UByte = if (qty > 7) 0U else this.toInt().shl(qty).toUByte()
|
||||
infix fun UByte.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
fun UByte.bit(n: Int, v: Boolean): UByte = if (v) this bis n else this bic n
|
||||
infix fun UByte.bis(n: Int): UByte = this.toUInt().or(1U shl n).toUByte()
|
||||
infix fun UByte.bic(n: Int): UByte = this.toUInt().and(1U.shl(n).inv()).toUByte()
|
||||
infix fun UByte.sex(n: Int): UByte {
|
||||
inline infix fun UByte.shr(qty: Int): UByte = this.toUInt().shr(max(qty, 7)).toUByte()
|
||||
inline infix fun UByte.shl(qty: Int): UByte = if (qty > 7) 0U else this.toInt().shl(qty).toUByte()
|
||||
inline infix fun UByte.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
inline fun UByte.bit(n: Int, v: Boolean): UByte = if (v) this bis n else this bic n
|
||||
inline infix fun UByte.bis(n: Int): UByte = this.toUInt().or(1U shl n).toUByte()
|
||||
inline infix fun UByte.bic(n: Int): UByte = this.toUInt().and(1U.shl(n).inv()).toUByte()
|
||||
inline infix fun UByte.sex(n: Int): UByte {
|
||||
val sign = 1.toUByte() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toUByte()
|
||||
}
|
||||
|
||||
infix fun Short.shr(qty: Int): Short = this.toInt().shr(max(qty, 15)).toShort()
|
||||
infix fun Short.shl(qty: Int): Short = if (qty > 15) 0 else this.toInt().shl(qty).toShort()
|
||||
infix fun Short.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
fun Short.bit(n: Int, v: Boolean): Short = if (v) this bis n else this bic n
|
||||
infix fun Short.bis(n: Int): Short = this.toInt().or(1 shl n).toShort()
|
||||
infix fun Short.bic(n: Int): Short = this.toInt().and(1.shl(n).inv()).toShort()
|
||||
infix fun Short.sex(n: Int): Short {
|
||||
inline infix fun Short.shr(qty: Int): Short = this.toInt().shr(max(qty, 15)).toShort()
|
||||
inline infix fun Short.shl(qty: Int): Short = if (qty > 15) 0 else this.toInt().shl(qty).toShort()
|
||||
inline infix fun Short.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
inline fun Short.bit(n: Int, v: Boolean): Short = if (v) this bis n else this bic n
|
||||
inline infix fun Short.bis(n: Int): Short = this.toInt().or(1 shl n).toShort()
|
||||
inline infix fun Short.bic(n: Int): Short = this.toInt().and(1.shl(n).inv()).toShort()
|
||||
inline infix fun Short.sex(n: Int): Short {
|
||||
val sign = 1.toShort() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toShort()
|
||||
}
|
||||
|
||||
infix fun UShort.shr(qty: Int): UShort = this.toUInt().shr(max(qty, 15)).toUShort()
|
||||
infix fun UShort.shl(qty: Int): UShort = if (qty > 15) 0U else this.toInt().shl(qty).toUShort()
|
||||
infix fun UShort.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
fun UShort.bit(n: Int, v: Boolean): UShort = if (v) this bis n else this bic n
|
||||
infix fun UShort.bis(n: Int): UShort = this.toUInt().or(1U shl n).toUShort()
|
||||
infix fun UShort.bic(n: Int): UShort = this.toUInt().and(1U.shl(n).inv()).toUShort()
|
||||
infix fun UShort.sex(n: Int): UShort {
|
||||
inline infix fun UShort.shr(qty: Int): UShort = this.toUInt().shr(max(qty, 15)).toUShort()
|
||||
inline infix fun UShort.shl(qty: Int): UShort = if (qty > 15) 0U else this.toInt().shl(qty).toUShort()
|
||||
inline infix fun UShort.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
inline fun UShort.bit(n: Int, v: Boolean): UShort = if (v) this bis n else this bic n
|
||||
inline infix fun UShort.bis(n: Int): UShort = this.toUInt().or(1U shl n).toUShort()
|
||||
inline infix fun UShort.bic(n: Int): UShort = this.toUInt().and(1U.shl(n).inv()).toUShort()
|
||||
inline infix fun UShort.sex(n: Int): UShort {
|
||||
val sign = 1.toUShort() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toUShort()
|
||||
}
|
||||
|
||||
infix fun Int.bit(n: Int): Boolean = this shr n and 1 != 0
|
||||
fun Int.bit(n: Int, v: Boolean): Int = if (v) this bis n else this bic n
|
||||
infix fun Int.bis(n: Int): Int = this.or(1 shl n)
|
||||
infix fun Int.bic(n: Int): Int = this and (1 shl n).inv()
|
||||
infix fun Int.sex(n: Int): Int {
|
||||
inline fun UShort.maskSet(v: UShort, mask: UShort) = this and mask.inv() or (v and mask)
|
||||
|
||||
inline infix fun Int.bit(n: Int): Boolean = this shr n and 1 != 0
|
||||
inline fun Int.bit(n: Int, v: Boolean): Int = if (v) this bis n else this bic n
|
||||
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))
|
||||
}
|
||||
infix fun UInt.bit(n: Int): Boolean = this shr n and 1U != 0U
|
||||
fun UInt.bit(n: Int, v: Boolean): UInt = if (v) this bis n else this bic n
|
||||
infix fun UInt.bis(n: Int): UInt = this.or(1U shl n)
|
||||
infix fun UInt.bic(n: Int): UInt = this.and(1U.shl(n).inv())
|
||||
infix fun UInt.sex(n: Int): UInt {
|
||||
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
|
||||
inline infix fun UInt.bis(n: Int): UInt = this.or(1U shl n)
|
||||
inline infix fun UInt.bic(n: Int): UInt = this.and(1U.shl(n).inv())
|
||||
inline infix fun UInt.sex(n: Int): UInt {
|
||||
val sign = 1U shl n+1
|
||||
return ((this and sign.dec()) - (this and sign))
|
||||
}
|
||||
|
||||
infix fun Long.bit(n: Int): Boolean = this shr n and 1L != 0L
|
||||
fun Long.bit(n: Int, v: Boolean): Long = if (v) this bis n else this bic n
|
||||
infix fun Long.bis(n: Int): Long = this.or(1L shl n)
|
||||
infix fun Long.bic(n: Int): Long = this and (1L shl n).inv()
|
||||
infix fun Long.sex(n: Int): Long {
|
||||
inline infix fun Long.bit(n: Int): Boolean = this shr n and 1L != 0L
|
||||
inline fun Long.bit(n: Int, v: Boolean): Long = if (v) this bis n else this bic n
|
||||
inline infix fun Long.bis(n: Int): Long = this.or(1L shl n)
|
||||
inline infix fun Long.bic(n: Int): Long = this and (1L shl n).inv()
|
||||
inline infix fun Long.sex(n: Int): Long {
|
||||
val sign = 1.toLong() shl n+1
|
||||
return (this and sign.dec()) - (this and sign)
|
||||
}
|
||||
infix fun ULong.bit(n: Int): Boolean = this shr n and 1UL != 0UL
|
||||
fun ULong.bit(n: Int, v: Boolean): ULong = if (v) this bis n else this bic n
|
||||
infix fun ULong.bis(n: Int): ULong = this.or(1UL shl n)
|
||||
infix fun ULong.bic(n: Int): ULong = this.and(1UL.shl(n).inv())
|
||||
infix fun ULong.sex(n: Int): ULong {
|
||||
inline infix fun ULong.bit(n: Int): Boolean = this shr n and 1UL != 0UL
|
||||
inline fun ULong.bit(n: Int, v: Boolean): ULong = if (v) this bis n else this bic n
|
||||
inline infix fun ULong.bis(n: Int): ULong = this.or(1UL shl n)
|
||||
inline infix fun ULong.bic(n: Int): ULong = this.and(1UL.shl(n).inv())
|
||||
inline infix fun ULong.sex(n: Int): ULong {
|
||||
val sign = 1UL shl n+1
|
||||
return ((this and (sign.dec())) - (this and sign))
|
||||
}
|
||||
|
92
src/main/kotlin/com/thequux/mcpdp/peripheral/DL11.kt
Normal file
92
src/main/kotlin/com/thequux/mcpdp/peripheral/DL11.kt
Normal file
@@ -0,0 +1,92 @@
|
||||
package com.thequux.mcpdp.peripheral
|
||||
|
||||
import com.thequux.mcpdp.core.MemoryError
|
||||
import com.thequux.mcpdp.core.MemoryErrorType
|
||||
import com.thequux.mcpdp.core.PAddressSpace
|
||||
import com.thequux.mcpdp.ext.bit.bic
|
||||
import com.thequux.mcpdp.ext.bit.bis
|
||||
import com.thequux.mcpdp.ext.bit.bit
|
||||
import com.thequux.mcpdp.ext.bit.maskSet
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.util.concurrent.Semaphore
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
|
||||
class DL11(private var istr: InputStream, private val ostr: OutputStream, val reg_base: UInt, val vector: UShort): PAddressSpace, Peripheral {
|
||||
private var reader: Thread? = null
|
||||
private var rcsr: UShort = 0x0u
|
||||
private var rbuf: UShort = 0u
|
||||
private var xcsr: UShort = 0u
|
||||
|
||||
constructor(istr: InputStream, ostr: OutputStream): this(istr, ostr, 0x3FF70u, 0x30u)
|
||||
|
||||
override fun mount(bus: Unibus) {
|
||||
bus.attach(reg_base, 3, this)
|
||||
}
|
||||
|
||||
override fun service() { }
|
||||
|
||||
override fun getw(addr: UInt): UShort = synchronized(this) {
|
||||
when (addr.toInt() and 7) {
|
||||
0 -> rcsr
|
||||
2 -> { rcsr = rcsr bic 7; rbuf }
|
||||
4 -> xcsr
|
||||
6 -> 0u
|
||||
else -> throw MemoryError(MemoryErrorType.OddAddress, addr)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setw(addr: UInt, value: UShort): Unit = synchronized(this) {
|
||||
when (addr.toInt() and 7) {
|
||||
0 -> {
|
||||
rcsr = rcsr.maskSet(value, 0x009Eu)
|
||||
if (value bit 0) {rcsr = rcsr bic 7 }
|
||||
}
|
||||
2 -> { rcsr = rcsr bic 7 }
|
||||
4 -> xcsr = xcsr.maskSet(value, 0x0045u)
|
||||
6 -> {
|
||||
val b = value.toInt() and 0xFF
|
||||
if (xcsr bit 1) {
|
||||
recvByte(b)
|
||||
}
|
||||
ostr.write(b)
|
||||
}
|
||||
else -> throw MemoryError(MemoryErrorType.OddAddress, addr)
|
||||
}
|
||||
}
|
||||
|
||||
private fun recvByte(data: Int) {
|
||||
val overrun = rcsr bit 7
|
||||
rcsr = rcsr and 0xC3FFu
|
||||
if (data < 0) {
|
||||
rcsr = rcsr bis 12
|
||||
} else {
|
||||
rcsr = rcsr bis 7
|
||||
rbuf = (data and 0xFF).bit(14, overrun).bit(15, overrun).toUShort()
|
||||
}
|
||||
}
|
||||
private fun readThread() {
|
||||
try {
|
||||
while (true) {
|
||||
val data = istr.read()
|
||||
synchronized(this) {
|
||||
// receive if not in maintenance mode
|
||||
// TODO: block until receiver ready
|
||||
if (!(xcsr bit 1)) recvByte(data)
|
||||
}
|
||||
if (data < 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (_: InterruptedException) {
|
||||
// Nothing to do; time to shut down
|
||||
}
|
||||
}
|
||||
override fun start() {
|
||||
super.start()
|
||||
reader = thread(block = this::readThread)
|
||||
|
||||
reader?.interrupt()
|
||||
}
|
||||
}
|
14
src/main/kotlin/com/thequux/mcpdp/peripheral/Peripheral.kt
Normal file
14
src/main/kotlin/com/thequux/mcpdp/peripheral/Peripheral.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.thequux.mcpdp.peripheral
|
||||
|
||||
interface Peripheral {
|
||||
fun mount(bus: Unibus)
|
||||
fun reset() {}
|
||||
|
||||
/// Check if the device needs to do something
|
||||
fun service()
|
||||
|
||||
/// Called when the device starts up
|
||||
fun start() {}
|
||||
/// Called when the device stops
|
||||
fun stop() {}
|
||||
}
|
@@ -13,7 +13,8 @@ interface Region {
|
||||
fun map(address: UInt): PAddressSpace?
|
||||
}
|
||||
|
||||
private class MappedDevice(val device: PAddressSpace): Region {
|
||||
@JvmInline
|
||||
private value class MappedDevice(val device: PAddressSpace): Region {
|
||||
override fun attach(address: UInt, suffix: Int, device: PAddressSpace) {
|
||||
throw ConfigurationError("Attempted to map one device over another at ${address.toString(8)}")
|
||||
}
|
||||
@@ -68,4 +69,8 @@ class Unibus: PAddressSpace, Subregion(12, 6) {
|
||||
override fun getb(addr: UInt): UByte = map(addr).getb(addr)
|
||||
override fun setw(addr: UInt, value: UShort) = map(addr).setw(addr, value)
|
||||
override fun setb(addr: UInt, value: UByte) = map(addr).setb(addr, value)
|
||||
|
||||
fun interrupt(vector: UShort) {
|
||||
throw NotImplementedError("Interrupts not yet implemented")
|
||||
}
|
||||
}
|
||||
|
62
src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt
Normal file
62
src/main/kotlin/com/thequux/mcpdp/tools/Link11.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
@file:OptIn(ExperimentalUnsignedTypes::class)
|
||||
|
||||
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
|
||||
|
||||
|
||||
@CommandLine.Command(name = "link", description = ["Link together multiple object files into something loadable"])
|
||||
class Link11: Callable<Int> {
|
||||
|
||||
@Parameters()
|
||||
lateinit var objects: Array<File>
|
||||
|
||||
@Option(names = ["-o", "--out"], required = true, description = ["Output file"])
|
||||
lateinit var outFile: File
|
||||
|
||||
@Option(names = ["-l", "--load"], description = ["Load address"])
|
||||
var loadAddr: Int = 1024
|
||||
|
||||
companion object {
|
||||
val R40Chars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.%0123456789".toCharArray()
|
||||
fun decodeRadix50(word: UShort): String {
|
||||
val buf = CharArray(3)
|
||||
var value = word.toInt()
|
||||
for (i in 0..2) {
|
||||
buf[2-i] = (value % 40).toChar()
|
||||
value /= 40
|
||||
}
|
||||
return String(buf)
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// symbols are always 4 bytes of radix-50, so we can just treat it as a uint
|
||||
private val symbols: HashMap<UInt, UShort> = HashMap()
|
||||
private val pendingReloc: HashMap<UInt, ArrayList<Consumer<UInt>>> = HashMap()
|
||||
private val mem = UByteArray(65536)
|
||||
|
||||
private val prog_start_addr: UShort = 1u
|
||||
private val prog_start_value: UShort = 1u
|
||||
private val prog_start_psect: UInt = 0xF94AF01u // ". ABS."
|
||||
|
||||
|
||||
|
||||
override fun call(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun load_rt11() {
|
||||
|
||||
}
|
||||
}
|
16
test/echo.mac
Normal file
16
test/echo.mac
Normal file
@@ -0,0 +1,16 @@
|
||||
rcsr = 177560
|
||||
rbuf = 177562
|
||||
xcsr = 177564
|
||||
xbuf = 177566
|
||||
|
||||
.psect .txt
|
||||
.title echo
|
||||
start:
|
||||
tstb @#rcsr
|
||||
bmi start
|
||||
mov @#rbuf,r1
|
||||
xor r1,#40
|
||||
mov r1,@#xbuf
|
||||
br start
|
||||
.byte 123
|
||||
.end start
|
Reference in New Issue
Block a user