generated from rnentjes/kotlin-server-web-undertow
70 lines
2.1 KiB
Kotlin
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
|
|
}
|
|
}
|
|
}
|