From e6a0351942c98404778c160601546b6904ca0a74 Mon Sep 17 00:00:00 2001 From: Gabriel Tofvesson <gabto095@student.liu.se> Date: Fri, 5 Apr 2019 23:19:05 +0200 Subject: [PATCH] Add machine-code weaver --- weaver.kt | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 weaver.kt diff --git a/weaver.kt b/weaver.kt new file mode 100644 index 0000000..9b89577 --- /dev/null +++ b/weaver.kt @@ -0,0 +1,155 @@ +import java.io.* + +class MachineState { + val programMemory = ShortArray(256)// PM + val microMemory = IntArray(128) // MyM + val k1 = ByteArray(16) // K1 + val k2 = ByteArray(4) // K2 + var pc: Byte = 0.toByte() // PC + var asr: Byte = 0.toByte() // ASR + var ar: Short = 0.toShort() // AR + var hr: Short = 0.toShort() // HR + var gr0: Short = 0.toShort() // GR0 + var gr1: Short = 0.toShort() // GR0 + var gr2: Short = 0.toShort() // GR0 + var gr3: Short = 0.toShort() // GR0 + var ir: Byte = 0.toByte() // IR + var uPC: Byte = 0.toByte() // MyPC + var uSP: Byte = 0.toByte() // SMyPC + var lc: Byte = 0.toByte() // LC + + override fun toString(): String { + val builder = StringBuilder("PM:\n") + for(index in 0 until programMemory.size) + builder.append(index.toUHex()).append(": ").append(programMemory[index].toUHex()).append("\n") + + builder.append("\nMyM:\n") + for(index in 0 until microMemory.size) + builder.append(index.toUHex()).append(": ").append(microMemory[index].toShortUHex()).append("\n") + + builder.append("\nK1:\n") + for(index in 0 until k1.size) + builder.append(index.toUHex()).append(": ").append(k1[index].toUHex()).append("\n") + + builder.append("\nK2:\n") + for(index in 0 until k2.size) + builder.append(index.toUHex()).append(": ").append(k2[index].toUHex()).append("\n") + + return builder + .append("\nPC:\n") + .append(pc.toUHex()) + .append("\n\nASR:\n") + .append(asr.toUHex()) + .append("\n\nAR:\n") + .append(ar.toUHex()) + .append("\n\nHR:\n") + .append(hr.toUHex()) + .append("\n\nGR0:\n") + .append(gr0.toUHex()) + .append("\n\nGR1:\n") + .append(gr1.toUHex()) + .append("\n\nGR2:\n") + .append(gr2.toUHex()) + .append("\n\nGR3:\n") + .append(gr3.toUHex()) + .append("\n\nIR:\nb") + .append(ir.toInt().or(1 shl 30).toString(2).substring(28)) + .append("\n\nMyPC:\n") + .append(uPC.toUHex()) + .append("\n\nSMyPC:\n") + .append(uSP.toUHex()) + .append("\n\nLC:\n") + .append(lc.toUHex()) + .append("\n\nO_flag:\n\nC_flag:\n\nN_flag:\n\nZ_flag:\n\nL_flag:\nEnd_of_dump_file") + .toString() + } + + companion object { + fun parseState(rawState: String): MachineState { + val state = MachineState() + val lines = rawState.replace("\r", "").split("\n").toTypedArray() + + // Read PM + for(index in 0 until 256) + state.programMemory[index] = Integer.parseInt(lines[index + 1].substring(4), 16).toShort() + + // Read MyM + for(index in 0 until 128) + state.microMemory[index] = Integer.parseInt(lines[index + 3 + 256].substring(4), 16) + + // Read K1 + for(index in 0 until 16) + state.k1[index] = Integer.parseInt(lines[index + 5 + 256 + 128].substring(4), 16).toByte() + + // Read K2 + for(index in 0 until 4) + state.k2[index] = Integer.parseInt(lines[index + 7 + 256 + 128 + 16].substring(4), 16).toByte() + + state.pc = Integer.parseInt(lines[413], 16).toByte() + state.asr = Integer.parseInt(lines[416], 16).toByte() + state.ar = Integer.parseInt(lines[419], 16).toShort() + state.hr = Integer.parseInt(lines[422], 16).toShort() + state.gr0 = Integer.parseInt(lines[425], 16).toShort() + state.gr1 = Integer.parseInt(lines[428], 16).toShort() + state.gr2 = Integer.parseInt(lines[431], 16).toShort() + state.gr3 = Integer.parseInt(lines[434], 16).toShort() + state.ir = Integer.parseInt(lines[437].substring(1), 2).toByte() + state.uPC = Integer.parseInt(lines[440], 16).toByte() + state.uSP = Integer.parseInt(lines[443], 16).toByte() + state.lc = Integer.parseInt(lines[446], 16).toByte() + + return state + } + } +} + +inline fun error(message: String){ + System.err.println(message) + println("Usage:\n\tkotlin WeaverKt [machineCodeFile] [outputFile]\nor\n\tkotlin WeaverKt [machineCodeFile] [inputState] [outputFile]") + System.exit(1) +} + +fun main(args: Array<String>){ + if(args.size > 3) error("Too many arguments!") + if(args.size < 2) error("Too few arguments!") + + val weaveFile = File(args[0]) + if(!weaveFile.isFile) error("Given machine code file doesn't exist!") + + val state: MachineState + + if(args.size == 2) state = MachineState() + else{ + val file = File(args[1]) + if(file.isFile) state = MachineState.parseState(file.readText()) + else{ + error("Machine state file (${args[1]}) doesn't exist!") + state = MachineState() + } + } + + val weaveData = weaveFile.readText().replace("\r", "").split("\n").toTypedArray() + var subtract = 0 + for(index in weaveData.indices) + if(weaveData[index].length == 0 || weaveData[index].startsWith("#")) ++subtract + else if((index - subtract) > state.programMemory.size) error("Program memory out of bounds! Did you pass too much data?") + else if(weaveData[index].length != 4) error("Cannot weave data of bad length: ${weaveData[index]}") + else try{ + state.programMemory[index - subtract] = Integer.parseInt(weaveData[index], 16).toShort() + }catch(e: NumberFormatException){ + error("Cannot weave non-hex data: ${weaveData[index]}") + } + + val outputFile = if(args.size == 3) File(args[2]) else File(args[1]) + if(outputFile.isFile) outputFile.delete() + outputFile.createNewFile() + + + val machineData = state.toString() + outputFile.bufferedWriter().use{ it.write(machineData, 0, machineData.length) } +} + +fun Short.toUHex() = toInt().and(0xFFFF.toInt()).or(1.shl(30)).toString(16).substring(4) +fun Int.toUHex() = and(0xFF).or(1.shl(30)).toString(16).substring(6) +fun Int.toShortUHex() = and((-1 ushr 7)).or(1.shl(30)).toString(16).substring(1) +fun Byte.toUHex() = toInt().and(0xFF.toInt()).or(1.shl(30)).toString(16).substring(6)