package mtmc.asm.instructions import mtmc.asm.Assembler import mtmc.tokenizer.MTMCToken import mtmc.util.BinaryUtils class JumpInstruction( type: InstructionType, label: List, instructionToken: MTMCToken ) : Instruction(type, label, instructionToken) { private var addressToken: MTMCToken? = null fun setAddressToken(addressToken: MTMCToken) { this.addressToken = addressToken } override fun validateLabel(assembler: Assembler) { if (addressToken!!.type == MTMCToken.TokenType.IDENTIFIER) { if (!assembler.hasLabel(addressToken!!.stringValue)) { addError("Unresolved label: " + addressToken!!.stringValue) } } } private fun resolveTargetAddress(assembler: Assembler): Int? { if (addressToken!!.type == MTMCToken.TokenType.IDENTIFIER) { return assembler.resolveLabel(addressToken!!.stringValue) } else { return addressToken!!.intValue() } } override fun genCode(output: ByteArray, assembler: Assembler) { var opcode = 0 when (type) { InstructionType.J -> opcode = 12 InstructionType.JZ -> opcode = 13 InstructionType.JNZ -> opcode = 14 InstructionType.JAL -> opcode = 15 else -> println("Invalid instruction type") } val address = resolveTargetAddress(assembler)!! output[location] = (opcode shl 4 or (address ushr 8)).toByte() output[location + 1] = address.toByte() } companion object { fun disassemble(instruction: Short): String? { if (BinaryUtils.getBits(16, 2, instruction).toInt() == 3) { val jumpType = BinaryUtils.getBits(14, 2, instruction) val sb = StringBuilder() if (jumpType.toInt() == 0) { sb.append("j") } else if (jumpType.toInt() == 1) { sb.append("jz") } else if (jumpType.toInt() == 2) { sb.append("jnz") } else if (jumpType.toInt() == 3) { sb.append("jal") } val target = BinaryUtils.getBits(12, 12, instruction) sb.append(" ").append(target.toInt()) return sb.toString() } return null } } }