Files
mtmc-web/src/jvmMain/kotlin/mtmc/asm/instructions/JumpInstruction.kt

70 lines
2.1 KiB
Kotlin

package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class JumpInstruction(
type: InstructionType,
label: List<MTMCToken>,
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
}
}
}