Remove legacy JVM-specific file system, shell, and related implementations; migrate to platform-agnostic and common main modules.

This commit is contained in:
2025-08-14 16:04:13 +02:00
parent 63f9a1f928
commit c7552c2a95
133 changed files with 981 additions and 898 deletions

View File

@@ -0,0 +1,87 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class ALUInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var toToken: MTMCToken? = null
private var fromToken: MTMCToken? = null
private var immediateOp: MTMCToken? = null
private var value: MTMCToken? = null
fun setTo(to: MTMCToken) {
this.toToken = to
}
fun setFrom(from: MTMCToken?) {
this.fromToken = from
}
fun setImmediateValue(value: MTMCToken) {
this.value = value
}
fun setImmediateOp(immediateOp: MTMCToken) {
this.immediateOp = immediateOp
}
fun isImmediateOp(): Boolean {
return this.type == InstructionType.IMM
}
val isBinaryOp: Boolean
get() = !ALUOp.valueOf(instructionToken.stringValue.uppercase()).isUnary
override fun genCode(output: ByteArray, assembler: Assembler) {
val opCode = ALUOp.toInteger(instructionToken.stringValue)
val to = toInteger(toToken!!.stringValue)
var from = 0
if (fromToken != null) {
from = toInteger(fromToken!!.stringValue)
}
output[location] = (16 or opCode).toByte()
if (this.isBinaryOp) {
output[location + 1] = (to shl 4 or from).toByte()
} else if (isImmediateOp()) {
val immediateValue = value!!.intValue()
val immediateOpValue = ALUOp.toInteger(immediateOp!!.stringValue)
output[location + 1] = (to shl 4 or immediateOpValue).toByte()
output[location + 2] = (immediateValue ushr 8).toByte()
output[location + 3] = immediateValue.toByte()
} else { // unary op
output[location + 1] = (to shl 4).toByte()
}
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 4, instruction).toInt() == 1) {
val builder = StringBuilder()
val opCode = BinaryUtils.getBits(12, 4, instruction)
val op = ALUOp.fromInt(opCode)
val aluOp = ALUOp.valueOf(op.uppercase())
if (aluOp == ALUOp.IMM) {
builder.append(op).append(" ")
builder.append(fromInteger(BinaryUtils.getBits(8, 4, instruction).toInt())).append(" ")
builder.append(ALUOp.fromInt(BinaryUtils.getBits(4, 4, instruction))).append(" ")
} else if (aluOp.isUnary) {
builder.append(op).append(" ")
builder.append(fromInteger(BinaryUtils.getBits(8, 4, instruction).toInt())).append(" ")
} else {
builder.append(op).append(" ")
builder.append(fromInteger(BinaryUtils.getBits(8, 4, instruction).toInt())).append(" ")
builder.append(fromInteger(BinaryUtils.getBits(4, 4, instruction).toInt())).append(" ")
}
return builder.toString()
}
return null
}
}
}

View File

@@ -0,0 +1,39 @@
package mtmc.asm.instructions
enum class ALUOp(val opCode: Int, val isUnary: Boolean) {
ADD(0x0000, false),
SUB(0x0001, false),
MUL(0x0002, false),
DIV(0x0003, false),
MOD(0x0004, false),
AND(0x0005, false),
OR(0x0006, false),
XOR(0x0007, false),
SHL(0x0008, false),
SHR(0x0009, false),
MIN(0x000A, false),
MAX(0x000B, false),
NOT(0x000C, true),
LNOT(0x000D, true),
NEG(0x000E, true),
IMM(0x000F, true);
companion object {
fun toInteger(instruction: String): Int {
return valueOf(instruction.uppercase()).opCode
}
fun fromInt(opCode: Short): String {
return entries[opCode.toInt()].name.lowercase()
}
fun isALUOp(op: String): Boolean {
try {
val aluOp = valueOf(op.uppercase())
return true
} catch (e: IllegalArgumentException) {
return false
}
}
}
}

View File

@@ -0,0 +1,23 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.tokenizer.MTMCToken
class ErrorInstruction(
labels: List<MTMCToken>,
instruction: MTMCToken,
error: String
) : Instruction(
InstructionType.ERROR,
labels,
instruction
) {
init {
addError(instruction, error)
}
override fun genCode(output: ByteArray, assembler: Assembler) {
// do nothing
}
}

View File

@@ -0,0 +1,71 @@
package mtmc.asm.instructions
import mtmc.asm.ASMElement
import mtmc.asm.Assembler
import mtmc.asm.instructions.ALUInstruction.Companion.disassemble
import mtmc.emulator.MonTanaMiniComputer.Companion.isDoubleWordInstruction
import mtmc.tokenizer.MTMCToken
abstract class Instruction(
val type: InstructionType,
labels: List<MTMCToken>,
val instructionToken: MTMCToken
) : ASMElement(labels, instructionToken.line) {
open fun validateLabel(assembler: Assembler) {
// default does nothing
}
override fun addError(error: String) {
addError(instructionToken, error)
}
abstract fun genCode(output: ByteArray, assembler: Assembler)
override var sizeInBytes: Int = type.sizeInBytes
get() = type.sizeInBytes
companion object {
fun isInstruction(cmd: String): Boolean {
return InstructionType.fromString(cmd) != null
}
fun disassemble(instruction: Short, previousInstruction: Short): String {
if (isDoubleWordInstruction(previousInstruction)) {
return instruction.toInt().toString()
}
val misc = MiscInstruction.disassemble(instruction)
if (misc != null) {
return misc
}
val aluOp = disassemble(instruction)
if (aluOp != null) {
return aluOp
}
val stack = StackInstruction.disassemble(instruction)
if (stack != null) {
return stack
}
val test = TestInstruction.disassemble(instruction)
if (test != null) {
return test
}
val lsr = LoadStoreRegisterInstruction.disassemble(instruction)
if (lsr != null) {
return lsr
}
val ls = LoadStoreInstruction.disassemble(instruction)
if (ls != null) {
return ls
}
val jumpReg = JumpInstruction.disassemble(instruction)
if (jumpReg != null) {
return jumpReg
}
val jump = JumpInstruction.disassemble(instruction)
if (jump != null) {
return jump
}
return "<unknown>"
}
}
}

View File

@@ -0,0 +1,95 @@
package mtmc.asm.instructions
enum class InstructionType constructor(
val instructionClass: InstructionClass?,
val sizeInBytes: Int = 2
) {
SYS(InstructionClass.MISC),
MOV(InstructionClass.MISC),
INC(InstructionClass.MISC),
DEC(InstructionClass.MISC),
SETI(InstructionClass.MISC),
NOP(InstructionClass.MISC),
MCP(InstructionClass.MISC, 4),
DEBUG(InstructionClass.MISC),
ADD(InstructionClass.ALU),
SUB(InstructionClass.ALU),
MUL(InstructionClass.ALU),
DIV(InstructionClass.ALU),
MOD(InstructionClass.ALU),
AND(InstructionClass.ALU),
OR(InstructionClass.ALU),
XOR(InstructionClass.ALU),
SHL(InstructionClass.ALU),
SHR(InstructionClass.ALU),
MIN(InstructionClass.ALU),
MAX(InstructionClass.ALU),
NOT(InstructionClass.ALU),
LNOT(InstructionClass.ALU),
NEG(InstructionClass.ALU),
IMM(InstructionClass.ALU, 4),
PUSH(InstructionClass.STACK),
POP(InstructionClass.STACK),
DUP(InstructionClass.STACK),
SWAP(InstructionClass.STACK),
DROP(InstructionClass.STACK),
OVER(InstructionClass.STACK),
ROT(InstructionClass.STACK),
SOP(InstructionClass.STACK),
PUSHI(InstructionClass.STACK, 4),
EQ(InstructionClass.TEST),
NEQ(InstructionClass.TEST),
GT(InstructionClass.TEST),
GTE(InstructionClass.TEST),
LT(InstructionClass.TEST),
LTE(InstructionClass.TEST),
EQI(InstructionClass.TEST),
NEQI(InstructionClass.TEST),
GTI(InstructionClass.TEST),
GTEI(InstructionClass.TEST),
LTI(InstructionClass.TEST),
LTEI(InstructionClass.TEST),
LWR(InstructionClass.LOAD_STORE_REGISTER),
LBR(InstructionClass.LOAD_STORE_REGISTER),
SWR(InstructionClass.LOAD_STORE_REGISTER),
SBR(InstructionClass.LOAD_STORE_REGISTER),
LW(InstructionClass.LOAD_STORE, 4),
LWO(InstructionClass.LOAD_STORE, 4),
LI(InstructionClass.LOAD_STORE, 4),
LB(InstructionClass.LOAD_STORE, 4),
LBO(InstructionClass.LOAD_STORE, 4),
SW(InstructionClass.LOAD_STORE, 4),
SWO(InstructionClass.LOAD_STORE, 4),
SB(InstructionClass.LOAD_STORE, 4),
SBO(InstructionClass.LOAD_STORE, 4),
JR(InstructionClass.JUMP_REGISTER),
J(InstructionClass.JUMP),
JZ(InstructionClass.JUMP),
JNZ(InstructionClass.JUMP),
JAL(InstructionClass.JUMP),
META(InstructionClass.MISC),
ERROR(InstructionClass.MISC),
;
enum class InstructionClass {
MISC,
ALU,
STACK,
TEST,
LOAD_STORE_REGISTER,
LOAD_STORE,
JUMP_REGISTER,
JUMP
}
companion object {
fun fromString(string: String): InstructionType? {
try {
return valueOf(string.uppercase())
} catch (e: IllegalArgumentException) {
return null
}
}
}
}

View File

@@ -0,0 +1,69 @@
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
}
}
}

View File

@@ -0,0 +1,37 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class JumpRegisterInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var register: MTMCToken? = null
fun setRegister(register: MTMCToken) {
this.register = register
}
public override fun genCode(output: ByteArray, assembler: Assembler) {
val opcode = 9
output[location] = (opcode shl 4).toByte()
val reg = toInteger(register!!.stringValue)
output[location + 1] = reg.toByte()
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 5, instruction).toInt() == 9) {
val reg = BinaryUtils.getBits(4, 4, instruction)
val sb = StringBuilder("jr")
sb.append(fromInteger(reg.toInt()))
}
return null
}
}
}

View File

@@ -0,0 +1,115 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class LoadStoreInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var targetToken: MTMCToken? = null
private var offsetToken: MTMCToken? = null
private var value: MTMCToken? = null
fun setTargetToken(targetToken: MTMCToken) {
this.targetToken = targetToken
}
fun setOffsetToken(offsetToken: MTMCToken) {
this.offsetToken = offsetToken
}
fun setValue(value: MTMCToken) {
this.value = value
}
val isOffset: Boolean
get() = type.name.endsWith("O")
public override fun validateLabel(assembler: Assembler) {
if (value!!.type == MTMCToken.TokenType.IDENTIFIER) {
if (!assembler.hasLabel(value!!.stringValue)) {
addError("Unresolved label: " + value!!.stringValue)
}
}
}
private fun resolveValue(assembler: Assembler): Int? {
if (value!!.type == MTMCToken.TokenType.IDENTIFIER) {
return assembler.resolveLabel(value!!.stringValue)
} else {
return value!!.intValue()
}
}
override fun genCode(output: ByteArray, assembler: Assembler) {
val upperByte = when (type) {
InstructionType.LW -> 128
InstructionType.LWO -> 129
InstructionType.LB -> 130
InstructionType.LBO -> 131
InstructionType.SW -> 132
InstructionType.SWO -> 133
InstructionType.SB -> 134
InstructionType.SBO -> 135
InstructionType.LI -> 143
else -> 0
}
val target = toInteger(targetToken!!.stringValue)
output[location] = upperByte.toByte()
if (this.isOffset) {
val offsetReg = toInteger(offsetToken!!.stringValue)
output[location + 1] = (target shl 4 or offsetReg).toByte()
} else {
output[location + 1] = (target shl 4).toByte()
}
val numericValue = resolveValue(assembler)!!
output[location + 2] = (numericValue ushr 8).toByte()
output[location + 3] = numericValue.toByte()
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 4, instruction).toInt() == 8) {
val topNibble = BinaryUtils.getBits(12, 4, instruction)
val sb = StringBuilder()
if (topNibble.toInt() == 15) {
sb.append("li ")
} else if (topNibble.toInt() == 0) {
sb.append("lw ")
} else if (topNibble.toInt() == 1) {
sb.append("lwo ")
} else if (topNibble.toInt() == 2) {
sb.append("lb ")
} else if (topNibble.toInt() == 3) {
sb.append("lbo ")
} else if (topNibble.toInt() == 4) {
sb.append("sw ")
} else if (topNibble.toInt() == 5) {
sb.append("swo ")
} else if (topNibble.toInt() == 6) {
sb.append("sb ")
} else if (topNibble.toInt() == 7) {
sb.append("sbo ")
}
val target = BinaryUtils.getBits(8, 4, instruction)
val reg = fromInteger(target.toInt())
sb.append(reg)
if (topNibble.toInt() == 1 || topNibble.toInt() == 3 || topNibble.toInt() == 5 || topNibble.toInt() == 7) {
val offset = BinaryUtils.getBits(4, 4, instruction)
val offsetReg = fromInteger(offset.toInt())
sb.append(" ").append(offsetReg)
}
return sb.toString()
}
return null
}
}
}

View File

@@ -0,0 +1,75 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class LoadStoreRegisterInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var targetToken: MTMCToken? = null
private var pointerToken: MTMCToken? = null
private var offsetToken: MTMCToken? = null
fun setTargetToken(targetToken: MTMCToken) {
this.targetToken = targetToken
}
fun setPointerToken(pointerToken: MTMCToken) {
this.pointerToken = pointerToken
}
fun setOffsetToken(offsetToken: MTMCToken?) {
this.offsetToken = offsetToken
}
override fun genCode(output: ByteArray, assembler: Assembler) {
var opcode = 0
when (type) {
InstructionType.LWR -> opcode = 4
InstructionType.LBR -> opcode = 5
InstructionType.SWR -> opcode = 6
InstructionType.SBR -> opcode = 7
else -> println("Invalid instruction type")
}
val target = toInteger(targetToken!!.stringValue)
val pointer = toInteger(pointerToken!!.stringValue)
var offset = Register.PC.ordinal
if (offsetToken != null) {
offset = toInteger(offsetToken!!.stringValue)
}
output[location] = (opcode shl 4 or target).toByte()
output[location + 1] = (pointer shl 4 or offset).toByte()
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 2, instruction).toInt() == 1) {
val builder = StringBuilder()
val type = BinaryUtils.getBits(14, 2, instruction)
if (type.toInt() == 0) {
builder.append("lwr ")
} else if (type.toInt() == 1) {
builder.append("lbr ")
} else if (type.toInt() == 2) {
builder.append("swr ")
} else if (type.toInt() == 3) {
builder.append("sbr ")
}
val srcDestReg = BinaryUtils.getBits(12, 4, instruction)
val addrReg = BinaryUtils.getBits(8, 4, instruction)
val offsetReg = BinaryUtils.getBits(4, 4, instruction)
builder.append(fromInteger(srcDestReg.toInt())).append(" ")
builder.append(fromInteger(addrReg.toInt())).append(" ")
builder.append(fromInteger(offsetReg.toInt()))
return builder.toString()
}
return null
}
}
}

View File

@@ -0,0 +1,90 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.tokenizer.MTMCToken
class MetaInstruction(instruction: MTMCToken) :
Instruction(InstructionType.META, listOf(), instruction) {
private var originalFilePath: MTMCToken? = null
private var originaLineNumber: MTMCToken? = null
private var globalName: MTMCToken? = null
private var globalLocation: MTMCToken? = null
private var globalType: MTMCToken? = null
private var localName: MTMCToken? = null
private var localOffset: MTMCToken? = null
private var localType: MTMCToken? = null
override fun genCode(output: ByteArray, assembler: Assembler) {
// do nothing
}
val isFileDirective: Boolean
get() = "file" == this.instructionToken.stringValue
val isLineDirective: Boolean
get() = "line" == this.instructionToken.stringValue
val isGlobalDirective: Boolean
get() = "global" == this.instructionToken.stringValue
val isLocalDirective: Boolean
get() = "local" == this.instructionToken.stringValue
val isEndLocalDirective: Boolean
get() = "endlocal" == this.instructionToken.stringValue
fun setOriginalFilePath(path: MTMCToken) {
this.originalFilePath = path
}
fun setOriginalLineNumber(lineNumber: MTMCToken) {
this.originaLineNumber = lineNumber
}
val originalLineNumber: Int
get() = this.originaLineNumber!!.intValue()
fun setGlobalInfo(name: MTMCToken, location: MTMCToken, type: MTMCToken) {
this.globalName = name
this.globalLocation = location
this.globalType = type
}
fun setLocalInfo(name: MTMCToken, offset: MTMCToken, type: MTMCToken) {
this.localName = name
this.localOffset = offset
this.localType = type
}
fun setEndLocalInfo(name: MTMCToken) {
this.localName = name
}
fun getOriginalFilePath(): String? {
return this.originalFilePath!!.stringValue
}
fun getGlobalName(): String? {
return this.globalName!!.stringValue
}
fun getGlobalLocation(): Int {
return this.globalLocation!!.intValue()
}
fun getGlobalType(): String? {
return this.globalType!!.stringValue
}
fun getLocalName(): String? {
return this.localName!!.stringValue
}
fun getLocalOffset(): Int {
return this.localOffset!!.intValue()
}
fun getLocalType(): String? {
return this.localType!!.stringValue
}
}

View File

@@ -0,0 +1,145 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.os.SysCall
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class MiscInstruction(
type: InstructionType,
labels: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, labels, instructionToken) {
private var syscallType: MTMCToken? = null
private var fromRegister: MTMCToken? = null
private var toRegister: MTMCToken? = null
private var value: MTMCToken? = null
fun setSyscallType(type: MTMCToken) {
this.syscallType = type
}
fun setFrom(fromRegister: MTMCToken) {
this.fromRegister = fromRegister
}
fun setTo(toRegister: MTMCToken) {
this.toRegister = toRegister
}
fun setValue(value: MTMCToken?) {
this.value = value
}
override fun genCode(output: ByteArray, assembler: Assembler) {
if (type == InstructionType.SYS) {
output[location] = 0
output[location + 1] = SysCall.getValue(this.syscallType!!.stringValue)
} else if (type == InstructionType.MOV) {
val to = toInteger(toRegister!!.stringValue)
val from = toInteger(fromRegister!!.stringValue)
output[location] = 1
output[location + 1] = (to shl 4 or from).toByte()
} else if (type == InstructionType.INC) {
output[location] = 2
val to = toInteger(toRegister!!.stringValue)
var immediateVal = 1
if (value != null) {
immediateVal = value!!.intValue()
}
output[location + 1] = (to shl 4 or immediateVal).toByte()
} else if (type == InstructionType.DEC) {
output[location] = 3
val to = toInteger(toRegister!!.stringValue)
var immediateVal = 1
if (value != null) {
immediateVal = value!!.intValue()
}
output[location + 1] = (to shl 4 or immediateVal).toByte()
} else if (type == InstructionType.SETI) {
output[location] = 4
val to = toInteger(toRegister!!.stringValue)
val immediateVal = value!!.intValue()
output[location + 1] = (to shl 4 or immediateVal).toByte()
} else if (type == InstructionType.MCP) {
output[location] = 5
val from = toInteger(fromRegister!!.stringValue)
val to = toInteger(toRegister!!.stringValue)
val value = this.value!!.intValue()
output[location + 1] = (from shl 4 or to).toByte()
output[location + 2] = (value shl 8).toByte()
output[location + 3] = (value and 0xFF).toByte()
} else if (type == InstructionType.DEBUG) {
output[location] = 8
output[location + 1] = value!!.intValue().toByte()
} else if (type == InstructionType.NOP) {
output[location] = 15
output[location + 1] = 255.toByte()
}
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 4, instruction).toInt() == 0) {
val topNibble = BinaryUtils.getBits(12, 4, instruction)
if (topNibble.toInt() == 0) {
val builder = StringBuilder("sys ")
val bits = BinaryUtils.getBits(8, 8, instruction)
val name = SysCall.getString(bits.toByte())
builder.append(name)
return builder.toString()
} else if (topNibble.toInt() == 1) {
val builder = StringBuilder("mov ")
val to = BinaryUtils.getBits(8, 4, instruction)
val from = BinaryUtils.getBits(4, 4, instruction)
val toName = fromInteger(to.toInt())
builder.append(toName).append(" ")
val fromName = fromInteger(from.toInt())
builder.append(fromName)
return builder.toString()
} else if (topNibble.toInt() == 2) {
val builder = StringBuilder("inc ")
val to = BinaryUtils.getBits(8, 4, instruction)
val amount = BinaryUtils.getBits(4, 4, instruction)
val toName = fromInteger(to.toInt())
builder.append(toName).append(" ")
builder.append(amount.toInt())
return builder.toString()
} else if (topNibble.toInt() == 3) {
val builder = StringBuilder("dec ")
val to = BinaryUtils.getBits(8, 4, instruction)
val amount = BinaryUtils.getBits(4, 4, instruction)
val toName = fromInteger(to.toInt())
builder.append(toName).append(" ")
builder.append(amount.toInt())
return builder.toString()
} else if (topNibble.toInt() == 4) {
val builder = StringBuilder("seti ")
val to = BinaryUtils.getBits(8, 4, instruction)
val amount = BinaryUtils.getBits(4, 4, instruction)
val toName = fromInteger(to.toInt())
builder.append(toName).append(" ")
builder.append(amount.toInt())
return builder.toString()
} else if (topNibble.toInt() == 5) {
val from = BinaryUtils.getBits(8, 4, instruction)
val fromName = fromInteger(from.toInt())
val to = BinaryUtils.getBits(4, 4, instruction)
val toName = fromInteger(to.toInt())
return "mcp " + fromName + " " + toName
} else if (topNibble.toInt() == 8) {
val builder = StringBuilder("debug ")
val stringIndex = BinaryUtils.getBits(8, 8, instruction)
builder.append(stringIndex.toInt())
return builder.toString()
} else if (topNibble.toInt() == 15) {
val builder = StringBuilder("noop")
return builder.toString()
}
}
return null
}
}
}

View File

@@ -0,0 +1,108 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.asm.instructions.ALUOp.Companion.fromInt
import mtmc.emulator.Register
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class StackInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var targetToken: MTMCToken? = null
private var stackRegisterToken: MTMCToken? = null
private var aluOpToken: MTMCToken? = null
private var value: MTMCToken? = null
fun setTarget(target: MTMCToken) {
this.targetToken = target
}
fun setStackRegister(stackRegister: MTMCToken?) {
this.stackRegisterToken = stackRegister
}
fun setALUOp(aluOp: MTMCToken) {
this.aluOpToken = aluOp
}
fun setValue(value: MTMCToken) {
this.value = value
}
override fun genCode(output: ByteArray, assembler: Assembler) {
var stackReg = Register.SP.ordinal
if (stackRegisterToken != null) {
stackReg = Register.Companion.toInteger(stackRegisterToken!!.stringValue)
}
if (type == InstructionType.PUSH) {
val target = Register.Companion.toInteger(targetToken!!.stringValue)
output[location] = 32
output[location + 1] = (target shl 4 or stackReg).toByte()
} else if (type == InstructionType.POP) {
val target = Register.Companion.toInteger(targetToken!!.stringValue)
output[location] = 33
output[location + 1] = (target shl 4 or stackReg).toByte()
} else if (type == InstructionType.SOP) {
val aluOp = ALUOp.toInteger(aluOpToken!!.stringValue)
output[location] = 39
output[location + 1] = (aluOp shl 4 or stackReg).toByte()
} else if (type == InstructionType.PUSHI) {
val immediateValue = value!!.intValue()
output[location] = 47
output[location + 1] = stackReg.toByte()
output[location + 2] = (immediateValue ushr 8).toByte()
output[location + 3] = immediateValue.toByte()
} else {
val stackOp: Int
stackOp = when (type) {
InstructionType.DUP -> 34
InstructionType.SWAP -> 35
InstructionType.DROP -> 36
InstructionType.OVER -> 37
InstructionType.ROT -> 38
else -> 0
}
output[location] = stackOp.toByte()
output[location + 1] = stackReg.toByte()
}
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 4, instruction).toInt() == 2) {
val opCode = BinaryUtils.getBits(12, 4, instruction)
val stackReg = BinaryUtils.getBits(4, 4, instruction)
if (opCode.toInt() == 0) {
val sourceReg = BinaryUtils.getBits(8, 4, instruction)
return "push " + fromInteger(sourceReg.toInt()) + " " + fromInteger(stackReg.toInt())
}
if (opCode.toInt() == 1) {
val destReg = BinaryUtils.getBits(8, 4, instruction)
return "pop " + fromInteger(destReg.toInt()) + " " + fromInteger(stackReg.toInt())
}
if (opCode.toInt() == 2) {
return "dup " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 3) {
return "swap " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 4) {
return "drop " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 5) {
return "over " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 6) {
return "rot " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 7) {
val aluOp = BinaryUtils.getBits(8, 4, instruction)
val op = fromInt(aluOp)
return "sop " + op + " " + fromInteger(stackReg.toInt())
} else if (opCode.toInt() == 15) {
return "pushi " + fromInteger(stackReg.toInt())
}
}
return null
}
}
}

View File

@@ -0,0 +1,126 @@
package mtmc.asm.instructions
import mtmc.asm.Assembler
import mtmc.emulator.Register.Companion.fromInteger
import mtmc.emulator.Register.Companion.toInteger
import mtmc.tokenizer.MTMCToken
import mtmc.util.BinaryUtils
class TestInstruction(
type: InstructionType,
label: List<MTMCToken>,
instructionToken: MTMCToken
) : Instruction(type, label, instructionToken) {
private var first: MTMCToken? = null
private var second: MTMCToken? = null
private var value: MTMCToken? = null
fun setFirst(to: MTMCToken) {
this.first = to
}
fun setSecond(from: MTMCToken) {
this.second = from
}
fun setImmediateValue(value: MTMCToken) {
this.value = value
}
val isImmediate: Boolean
get() = type.name.endsWith("I")
override fun genCode(output: ByteArray, assembler: Assembler) {
val firstReg = toInteger(first!!.stringValue)
if (this.isImmediate) {
val upperByte = when (type) {
InstructionType.EQI -> 56
InstructionType.NEQI -> 57
InstructionType.GTI -> 58
InstructionType.GTEI -> 59
InstructionType.LTI -> 60
InstructionType.LTEI -> 61
else -> 0
}
val immediateValue = value!!.intValue()
output[location] = upperByte.toByte()
output[location + 1] = (firstReg shl 4 or immediateValue).toByte()
} else {
val upperByte = when (type) {
InstructionType.EQ -> 48
InstructionType.NEQ -> 49
InstructionType.GT -> 50
InstructionType.GTE -> 51
InstructionType.LT -> 52
InstructionType.LTE -> 53
else -> 0
}
val secondReg = toInteger(second!!.stringValue)
output[location] = upperByte.toByte()
output[location + 1] = (firstReg shl 4 or secondReg).toByte()
}
}
companion object {
fun disassemble(instruction: Short): String? {
if (BinaryUtils.getBits(16, 4, instruction).toInt() == 3) {
val sb = StringBuilder()
val opCode = BinaryUtils.getBits(12, 4, instruction)
val thirdNibble = BinaryUtils.getBits(8, 4, instruction)
val fourthNibble = BinaryUtils.getBits(4, 4, instruction)
if (opCode.toInt() == 0) {
sb.append("eq ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
} else if (opCode.toInt() == 1) {
sb.append("neq ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
} else if (opCode.toInt() == 2) {
sb.append("gt ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
} else if (opCode.toInt() == 3) {
sb.append("gte ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
} else if (opCode.toInt() == 4) {
sb.append("lt ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
} else if (opCode.toInt() == 5) {
sb.append("lte ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fromInteger(fourthNibble.toInt()))
}
if (opCode.toInt() == 8) {
sb.append("eqi ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
} else if (opCode.toInt() == 9) {
sb.append("neqi ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
} else if (opCode.toInt() == 10) {
sb.append("gti ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
} else if (opCode.toInt() == 11) {
sb.append("gtei ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
} else if (opCode.toInt() == 12) {
sb.append("lti ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
} else if (opCode.toInt() == 13) {
sb.append("ltei ")
sb.append(fromInteger(thirdNibble.toInt()))
.append(" ").append(fourthNibble.toInt())
}
return sb.toString()
}
return null
}
}
}