diff --git a/compiler.kt b/compiler.kt index 3602a03..f54ee15 100644 --- a/compiler.kt +++ b/compiler.kt @@ -11,7 +11,11 @@ enum class OpCode(val opcode: Int, val useM: Boolean, val useADR: Boolean, val u BNE(7, false, true), CMP(8, true, false), BEQ(9, false, true), - HALT(15, false, false, false) + HALT(15, false, false, false); + + companion object { + fun fromString(name: String) = OpCode.values().firstOrNull{ it.name == name } + } } enum class Mode(val id: Int) { @@ -19,27 +23,35 @@ enum class Mode(val id: Int) { } abstract class Instruction(val words: Int) { - fun getData(insns: Iterable): ShortArray + abstract fun getData(insns: Iterable): ShortArray } class Label(val name: String): Instruction(0) { override fun getData(insns: Iterable) = ShortArray(0) } -class Immediate(val data: Short): Instruction(1) { - override fun getData(insns: Iterable) = ShortArray(1){ data } -} - -class Operation(val code: OpCode, val reg: Int, val m: Mode, val adr: AddressReference, val immediate: Immediate? = null): Instruction(if(m == Mode.IMMEDIATE) 2 else 1) { - constructor(val code: OpCode): this(code, 0, Mode.DIRECT, AddressReference(0)) +class Operation(val code: OpCode, val reg: Int, val m: Mode, val adr: AddressReference, val immediate: Short? = null): Instruction(if(m == Mode.IMMEDIATE) 2 else 1) { + constructor(code: OpCode, reg: Int): this(code, reg, Mode.DIRECT, AddressReference(0)){ + if(code.useM || code.useADR) + throw IllegalArgumentException("Not enough parameters specified for instruction: ${code.name}") + } + constructor(code: OpCode, m: Mode, adr: AddressReference, immediate: Short? = null): this(code, 0, m, adr, immediate){ + if(code.useReg) + throw IllegalArgumentException("Not enough parameters specified for instruction: ${code.name}") + } + constructor(code: OpCode): this(code, 0, Mode.DIRECT, AddressReference(0)){ + if(code.useM || code.useADR || code.useReg) + throw IllegalArgumentException("Not enough parameters specified for instruction: ${code.name}") + } init { if(m == Mode.IMMEDIATE && immediate == null) throw IllegalArgumentException("No immediate argument passed!") } - override fun getData(insns: Iterable): Short { - return shortArrayOf(code.opcode + override fun getData(insns: Iterable): ShortArray { + val array = ShortArray(words) + array[0] = code.opcode .and(0b1111) .shl(12) .or( @@ -55,7 +67,9 @@ class Operation(val code: OpCode, val reg: Int, val m: Mode, val adr: AddressRef else 0 ) .toShort() - ) + if(m == Mode.IMMEDIATE) array[1] = immediate!! + + return array } } @@ -65,15 +79,204 @@ class AddressReference(private val label: Label?, private val absolute: Int?) { fun getAddress(insns: Iterable): Int { if(absolute != null) return absolute - insns.forEachIndexed{ index, insn -> - if(insn == label) - return@getAddress index*2 - } - - throw RuntimeException("Label cannot be found in set of instructions!") + var addrOff = 0 + for(insn in insns) + if(insn == label) return addrOff + else addrOff += insn.words + + throw RuntimeException("Found reference to undeclared label!") } } +class CompilationUnit { + private val instructions = ArrayList() + private val labels = ArrayList