mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
vm: limit int instructions to just 2 register args
This commit is contained in:
parent
4be7bc8323
commit
517cf61d11
@ -77,22 +77,19 @@ internal class VmCodeInstruction(
|
||||
type: VmDataType?=null,
|
||||
reg1: Int?=null, // 0-$ffff
|
||||
reg2: Int?=null, // 0-$ffff
|
||||
reg3: Int?=null, // 0-$ffff
|
||||
fpReg1: Int?=null, // 0-$ffff
|
||||
fpReg2: Int?=null, // 0-$ffff
|
||||
value: Int?=null, // 0-$ffff
|
||||
fpValue: Float?=null,
|
||||
symbol: List<String>?=null // alternative to value
|
||||
): VmCodeLine() {
|
||||
val ins = Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, value, fpValue, symbol)
|
||||
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, symbol)
|
||||
|
||||
init {
|
||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
||||
throw IllegalArgumentException("reg1 out of bounds")
|
||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
||||
throw IllegalArgumentException("reg2 out of bounds")
|
||||
if(reg3!=null && (reg3<0 || reg3>65536))
|
||||
throw IllegalArgumentException("reg3 out of bounds")
|
||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
||||
|
@ -115,7 +115,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val andReg = codeGen.vmRegisters.nextFree()
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister, reg3=andReg)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister)
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=andReg, symbol = notNegativeLabel)
|
||||
code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
@ -125,7 +125,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val andReg = codeGen.vmRegisters.nextFree()
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister, reg3=andReg)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister)
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=andReg, symbol = notNegativeLabel)
|
||||
code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
|
||||
code += VmCodeLabel(notNegativeLabel)
|
||||
@ -230,11 +230,10 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
|
||||
private fun funcMkword(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val msbReg = codeGen.vmRegisters.nextFree()
|
||||
val lsbReg = codeGen.vmRegisters.nextFree()
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], msbReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], lsbReg, -1)
|
||||
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg)
|
||||
code += exprGen.translateExpression(call.args[1], resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg)
|
||||
return code
|
||||
}
|
||||
|
||||
|
@ -331,11 +331,11 @@ class CodeGen(internal val program: PtProgram,
|
||||
val valueReg = vmRegisters.nextFree()
|
||||
if(value>0) {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value= value)
|
||||
code += VmCodeInstruction(Opcode.ADD, dt, reg1 = reg, reg2 = reg, reg3 = valueReg)
|
||||
code += VmCodeInstruction(Opcode.ADD, dt, reg1 = reg, reg2 = valueReg)
|
||||
}
|
||||
else {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value= -value)
|
||||
code += VmCodeInstruction(Opcode.SUB, dt, reg1 = reg, reg2 = reg, reg3 = valueReg)
|
||||
code += VmCodeInstruction(Opcode.SUB, dt, reg1 = reg, reg2 = valueReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -366,13 +366,13 @@ class CodeGen(internal val program: PtProgram,
|
||||
if(value>0) {
|
||||
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=value)
|
||||
code += VmCodeInstruction(Opcode.ADD, dt, reg1 = valueReg, reg2 = valueReg, reg3 = operandReg)
|
||||
code += VmCodeInstruction(Opcode.ADD, dt, reg1 = valueReg, reg2 = operandReg)
|
||||
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
|
||||
}
|
||||
else {
|
||||
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=-value)
|
||||
code += VmCodeInstruction(Opcode.SUB, dt, reg1 = valueReg, reg2 = valueReg, reg3 = operandReg)
|
||||
code += VmCodeInstruction(Opcode.SUB, dt, reg1 = valueReg, reg2 = operandReg)
|
||||
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
|
||||
}
|
||||
}
|
||||
@ -409,7 +409,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=reg, reg3=pow2reg)
|
||||
code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
|
||||
} else {
|
||||
if (factor == 0) {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
|
||||
@ -417,7 +417,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
else {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=reg, reg3=factorReg)
|
||||
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=factorReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -450,7 +450,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=reg, reg3=pow2reg)
|
||||
code += VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
|
||||
} else {
|
||||
if (factor == 0) {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||
@ -458,7 +458,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
else {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||
code += VmCodeInstruction(Opcode.DIV, dt, reg1=reg, reg2=reg, reg3=factorReg)
|
||||
code += VmCodeInstruction(Opcode.DIV, dt, reg1=reg, reg2=factorReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
|
@ -185,7 +185,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask)
|
||||
}
|
||||
"not" -> {
|
||||
val label = codeGen.createLabelName()
|
||||
@ -194,7 +194,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeLabel(label)
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask)
|
||||
}
|
||||
else -> throw AssemblyError("weird prefix operator")
|
||||
}
|
||||
@ -329,7 +329,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = resultRegister, reg3 = zeroRegister)
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
@ -339,7 +339,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -365,7 +365,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = resultRegister, reg3 = zeroRegister)
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
@ -375,7 +375,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -395,14 +395,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeLabel(label)
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=regMask, value=1)
|
||||
code += VmCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
|
||||
code += VmCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=resultRegister, reg2=regMask)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -418,7 +418,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opc = if (signed) Opcode.ASRN else Opcode.LSRN
|
||||
code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
|
||||
code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -432,7 +432,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -442,7 +442,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -451,7 +451,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -471,7 +471,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -498,7 +498,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -536,7 +536,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -564,7 +564,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -600,7 +600,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
|
@ -3,7 +3,6 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: get rid of the 3-register instructions just make them 2 registers? Result register is always same as second?
|
||||
- vm: use more instructions in codegen: branching
|
||||
- vm: add more instructions operating directly on memory instead of only registers?
|
||||
- in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird.
|
||||
|
@ -25,29 +25,10 @@ main {
|
||||
|
||||
ubyte @shared value = inline_candidate()
|
||||
|
||||
float fl1 = 1.1
|
||||
float fl2 = 2.2
|
||||
floats.print_f(floats.pow(fl1,fl2))
|
||||
|
||||
if fl1==fl2
|
||||
txt.print("equals!?\n")
|
||||
if fl1!=fl2
|
||||
txt.print("not equals.\n")
|
||||
fl1 = fl2
|
||||
if fl1==fl2
|
||||
txt.print("equals.\n")
|
||||
if fl1!=fl2
|
||||
txt.print("not equals!?\n")
|
||||
|
||||
if fl1 <= fl2
|
||||
txt.print("yup\n")
|
||||
if fl1 > fl2
|
||||
txt.print("nope\n")
|
||||
fl1 = 3.3
|
||||
if fl1 <= fl2
|
||||
txt.print("yup\n")
|
||||
if fl1 > fl2
|
||||
txt.print("nope\n")
|
||||
ubyte lowb = $31
|
||||
ubyte highb = $ea
|
||||
uword result = mkword(highb, lowb)
|
||||
txt.print_uwhex(result, true)
|
||||
|
||||
; txt.print_ub(inline_candidate())
|
||||
; txt.nl()
|
||||
|
@ -157,10 +157,10 @@ class Assembler {
|
||||
fpReg2 = fpReg3
|
||||
fpReg3 = null
|
||||
}
|
||||
if(reg3!=null)
|
||||
throw IllegalArgumentException("too many reg arguments $line")
|
||||
if(fpReg3!=null)
|
||||
throw IllegalArgumentException("too many fpreg arguments $line")
|
||||
// TODO also check reg3
|
||||
|
||||
|
||||
if(type!=null && type !in formats)
|
||||
throw IllegalArgumentException("invalid type code for $line")
|
||||
@ -168,16 +168,12 @@ class Assembler {
|
||||
throw IllegalArgumentException("needs reg1 for $line")
|
||||
if(format.reg2 && reg2==null)
|
||||
throw IllegalArgumentException("needs reg2 for $line")
|
||||
if(format.reg3 && reg3==null)
|
||||
throw IllegalArgumentException("needs reg3 for $line")
|
||||
if(format.value && value==null)
|
||||
throw IllegalArgumentException("needs value for $line")
|
||||
if(!format.reg1 && reg1!=null)
|
||||
throw IllegalArgumentException("invalid reg1 for $line")
|
||||
if(!format.reg2 && reg2!=null)
|
||||
throw IllegalArgumentException("invalid reg2 for $line")
|
||||
if(!format.reg3 && reg3!=null)
|
||||
throw IllegalArgumentException("invalid reg3 for $line")
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
@ -200,7 +196,7 @@ class Assembler {
|
||||
if(format.fpValue)
|
||||
floatValue = value!!
|
||||
|
||||
program.add(Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, value = intValue, fpValue = floatValue))
|
||||
program.add(Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value = intValue, fpValue = floatValue))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,16 +73,16 @@ bgt reg1, reg2, location - jump to location in program given by l
|
||||
bgts reg1, reg2, location - jump to location in program given by location, if reg1 > reg2 (signed)
|
||||
bge reg1, reg2, location - jump to location in program given by location, if reg1 >= reg2 (unsigned)
|
||||
bges reg1, reg2, location - jump to location in program given by location, if reg1 >= reg2 (signed)
|
||||
seq reg1, reg2, reg3 - set reg=1 if reg2 == reg3, otherwise set reg1=0
|
||||
sne reg1, reg2, reg3 - set reg=1 if reg2 != reg3, otherwise set reg1=0
|
||||
slt reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (signed), otherwise set reg1=0
|
||||
sge reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (unsigned), otherwise set reg1=0
|
||||
sges reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (signed), otherwise set reg1=0
|
||||
seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0
|
||||
sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0
|
||||
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0
|
||||
sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
|
||||
sges reg1, reg2 - set reg=1 if reg1 >= reg2 (signed), otherwise set reg1=0
|
||||
|
||||
|
||||
ARITHMETIC
|
||||
@ -96,11 +96,11 @@ incm address - memory at address += 1
|
||||
dec reg1 - reg1 = reg1-1
|
||||
decm address - memory at address -= 1
|
||||
neg reg1 - reg1 = sign negation of reg1
|
||||
add reg1, reg2, reg3 - reg1 = reg2+reg3 (unsigned + signed)
|
||||
sub reg1, reg2, reg3 - reg1 = reg2-reg3 (unsigned + signed)
|
||||
mul reg1, reg2, reg3 - unsigned multiply reg1=reg2*reg3 note: byte*byte->byte, no type extension to word!
|
||||
div reg1, reg2, reg3 - unsigned division reg1=reg2/reg3 note: division by zero yields max signed int $ff/$ffff
|
||||
mod reg1, reg2, reg3 - remainder (modulo) of unsigned division reg1=reg2%reg3 note: division by zero yields max signed int $ff/$ffff
|
||||
add reg1, reg2 - reg1 += reg2 (unsigned + signed)
|
||||
sub reg1, reg2 - reg1 -= reg2 (unsigned + signed)
|
||||
mul reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
div reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max signed int $ff/$ffff
|
||||
mod reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
|
||||
sqrt reg1, reg2 - reg1 is the square root of reg2
|
||||
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
||||
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
||||
@ -113,12 +113,12 @@ LOGICAL/BITWISE
|
||||
---------------
|
||||
All have type b or w.
|
||||
|
||||
and reg1, reg2, reg3 - reg1 = reg2 bitwise and reg3
|
||||
or reg1, reg2, reg3 - reg1 = reg2 bitwise or reg3
|
||||
xor reg1, reg2, reg3 - reg1 = reg2 bitwise xor reg3
|
||||
lsrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit
|
||||
asrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + set Carry to shifted bit
|
||||
lsln reg1, reg2, reg3 - reg1 = multi-shift reg2 left by reg3 bits + set Carry to shifted bit
|
||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
||||
asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit
|
||||
lsln reg1, reg2 - reg1 = multi-shift reg1 left by reg2 bits + set Carry to shifted bit
|
||||
lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit
|
||||
asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit
|
||||
lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit
|
||||
@ -151,7 +151,7 @@ sec - set Carry status bit
|
||||
nop - do nothing
|
||||
breakpoint - trigger a breakpoint
|
||||
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
|
||||
concat [b, w] reg1, reg2, reg3 - reg1 = concatenated lsb/lsw of reg2 and lsb/lsw of reg3 into new word or int (int not yet implemented; requires 32bits regs)
|
||||
concat [b, w] reg1, reg2 - reg1 = concatenated lsb/lsw of reg1 (as lsb) and lsb/lsw of reg2 (as msb) into word or int (int not yet implemented; requires 32bits regs)
|
||||
push [b, w] reg1 - push value in reg1 on the stack
|
||||
pop [b, w] reg1 - pop value from stack into reg1
|
||||
|
||||
@ -289,7 +289,6 @@ data class Instruction(
|
||||
val type: VmDataType?=null,
|
||||
val reg1: Int?=null, // 0-$ffff
|
||||
val reg2: Int?=null, // 0-$ffff
|
||||
val reg3: Int?=null, // 0-$ffff
|
||||
val fpReg1: Int?=null, // 0-$ffff
|
||||
val fpReg2: Int?=null, // 0-$ffff
|
||||
val value: Int?=null, // 0-$ffff
|
||||
@ -302,17 +301,13 @@ data class Instruction(
|
||||
throw IllegalArgumentException("missing type")
|
||||
|
||||
val format = formats.getValue(type)
|
||||
if(format.reg1 && reg1==null ||
|
||||
format.reg2 && reg2==null ||
|
||||
format.reg3 && reg3==null)
|
||||
if(format.reg1 && reg1==null || format.reg2 && reg2==null)
|
||||
throw IllegalArgumentException("missing a register (int)")
|
||||
|
||||
if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null)
|
||||
throw IllegalArgumentException("missing a register (float)")
|
||||
|
||||
if(!format.reg1 && reg1!=null ||
|
||||
!format.reg2 && reg2!=null ||
|
||||
!format.reg3 && reg3!=null)
|
||||
if(!format.reg1 && reg1!=null || !format.reg2 && reg2!=null)
|
||||
throw IllegalArgumentException("too many registers (int)")
|
||||
|
||||
if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null)
|
||||
@ -346,10 +341,6 @@ data class Instruction(
|
||||
result.add("r$it")
|
||||
result.add(",")
|
||||
}
|
||||
reg3?.let {
|
||||
result.add("r$it")
|
||||
result.add(",")
|
||||
}
|
||||
fpReg1?.let {
|
||||
result.add("fr$it")
|
||||
result.add(",")
|
||||
@ -376,7 +367,7 @@ data class Instruction(
|
||||
}
|
||||
|
||||
data class InstructionFormat(val datatype: VmDataType?,
|
||||
val reg1: Boolean, val reg2: Boolean, val reg3: Boolean,
|
||||
val reg1: Boolean, val reg2: Boolean,
|
||||
val fpReg1: Boolean, val fpReg2: Boolean,
|
||||
val value: Boolean,
|
||||
val fpValue: Boolean) {
|
||||
@ -386,7 +377,6 @@ data class InstructionFormat(val datatype: VmDataType?,
|
||||
for(part in spec.split('|').map{ it.trim() }) {
|
||||
var reg1 = false
|
||||
var reg2 = false
|
||||
var reg3 = false
|
||||
var fpreg1 = false
|
||||
var fpreg2 = false
|
||||
var value = false
|
||||
@ -397,7 +387,6 @@ data class InstructionFormat(val datatype: VmDataType?,
|
||||
when(splits.next()) {
|
||||
"r1" -> reg1=true
|
||||
"r2" -> reg2=true
|
||||
"r3" -> reg3=true
|
||||
"fr1" -> fpreg1=true
|
||||
"fr2" -> fpreg2=true
|
||||
"v" -> value = true
|
||||
@ -406,13 +395,13 @@ data class InstructionFormat(val datatype: VmDataType?,
|
||||
}
|
||||
}
|
||||
if(typespec=="N")
|
||||
result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
if('B' in typespec)
|
||||
result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
if('W' in typespec)
|
||||
result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
if('F' in typespec)
|
||||
result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -456,38 +445,38 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.BLES to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGE to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGES to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SGES to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGES to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.INC to InstructionFormat.from("BW,r1"),
|
||||
Opcode.INCM to InstructionFormat.from("BW,v"),
|
||||
Opcode.DEC to InstructionFormat.from("BW,r1"),
|
||||
Opcode.DECM to InstructionFormat.from("BW,v"),
|
||||
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.ADD to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
|
||||
Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
|
||||
Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
|
||||
Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.MOD to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.DIV to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.MOD to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.EXT to InstructionFormat.from("BW,r1"),
|
||||
Opcode.EXTS to InstructionFormat.from("BW,r1"),
|
||||
Opcode.AND to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.OR to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.ASRN to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.LSRN to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.LSLN to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.AND to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.OR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.ASRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSLN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.ASR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.LSR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.LSL to InstructionFormat.from("BW,r1"),
|
||||
@ -521,7 +510,7 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.MSIG to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.PUSH to InstructionFormat.from("BW,r1"),
|
||||
Opcode.POP to InstructionFormat.from("BW,r1"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.CLC to InstructionFormat.from("N"),
|
||||
Opcode.SEC to InstructionFormat.from("N"),
|
||||
Opcode.BREAKPOINT to InstructionFormat.from("N"),
|
||||
|
@ -527,73 +527,73 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
private fun InsSEQ(i: Instruction) {
|
||||
val (resultReg: Int, left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val (left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left==right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSNE(i: Instruction) {
|
||||
val (resultReg: Int, left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val (left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left!=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLT(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val (left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left<right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLTS(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val (left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left<right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGT(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val (left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left>right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGTS(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val (left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left>right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLE(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val (left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left<=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLES(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val (left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left<=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGE(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val (left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left>=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
|
||||
}
|
||||
|
||||
private fun InsSGES(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val (left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left>=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
|
||||
}
|
||||
@ -645,8 +645,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsADD(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!)
|
||||
VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!)
|
||||
VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!)
|
||||
}
|
||||
pc++
|
||||
@ -654,16 +654,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsSUB(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!)
|
||||
VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!)
|
||||
VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!)
|
||||
}
|
||||
pc++
|
||||
}
|
||||
private fun InsMUL(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!)
|
||||
VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!)
|
||||
VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!)
|
||||
}
|
||||
pc++
|
||||
@ -671,8 +671,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsDIV(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!)
|
||||
VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!)
|
||||
VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!)
|
||||
}
|
||||
pc++
|
||||
@ -680,8 +680,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsMOD(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> arithByte("%", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.WORD -> arithWord("%", i.reg1!!, i.reg2!!, i.reg3!!)
|
||||
VmDataType.BYTE -> arithByte("%", i.reg1!!, i.reg2!!)
|
||||
VmDataType.WORD -> arithWord("%", i.reg1!!, i.reg2!!)
|
||||
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||
}
|
||||
pc++
|
||||
@ -744,9 +744,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun arithByte(operator: String, reg1: Int, reg2: Int, reg3: Int) {
|
||||
val left = registers.getUB(reg2)
|
||||
val right = registers.getUB(reg3)
|
||||
private fun arithByte(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getUB(reg1)
|
||||
val right = registers.getUB(reg2)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
@ -764,9 +764,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
registers.setUB(reg1, result.toUByte())
|
||||
}
|
||||
|
||||
private fun arithWord(operator: String, reg1: Int, reg2: Int, reg3: Int) {
|
||||
val left = registers.getUW(reg2)
|
||||
val right = registers.getUW(reg3)
|
||||
private fun arithWord(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getUW(reg1)
|
||||
val right = registers.getUW(reg2)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
@ -1019,9 +1019,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsCONCAT(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val lsb = registers.getUB(i.reg1!!)
|
||||
val msb = registers.getUB(i.reg2!!)
|
||||
val lsb = registers.getUB(i.reg3!!)
|
||||
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
registers.setUW(i.reg1, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
}
|
||||
VmDataType.WORD -> TODO("concat.w not yet supported, requires 32-bits registers")
|
||||
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||
@ -1180,8 +1180,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun getLogicalOperandsU(i: Instruction): Pair<UInt, UInt> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getUB(i.reg2!!).toUInt(), registers.getUB(i.reg3!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getUW(i.reg2!!).toUInt(), registers.getUW(i.reg3!!).toUInt())
|
||||
VmDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
|
||||
VmDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
@ -1191,8 +1191,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun getLogicalOperandsS(i: Instruction): Pair<Int, Int> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getSB(i.reg2!!).toInt(), registers.getSB(i.reg3!!).toInt())
|
||||
VmDataType.WORD -> Pair(registers.getSW(i.reg2!!).toInt(), registers.getSW(i.reg3!!).toInt())
|
||||
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
|
||||
VmDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
|
||||
VmDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
@ -1200,10 +1200,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSetOnConditionOperands(ins: Instruction): Triple<Int, Int, Int> {
|
||||
private fun getSetOnConditionOperands(ins: Instruction): Pair<Int, Int> {
|
||||
return when(ins.type) {
|
||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getSW(ins.reg2!!).toInt(), registers.getSW(ins.reg3!!).toInt())
|
||||
VmDataType.BYTE -> Pair(registers.getSB(ins.reg1!!).toInt(), registers.getSB(ins.reg2!!).toInt())
|
||||
VmDataType.WORD -> Pair(registers.getSW(ins.reg1!!).toInt(), registers.getSW(ins.reg2!!).toInt())
|
||||
VmDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
@ -1211,10 +1211,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSetOnConditionOperandsU(ins: Instruction): Triple<Int, UInt, UInt> {
|
||||
private fun getSetOnConditionOperandsU(ins: Instruction): Pair<UInt, UInt> {
|
||||
return when(ins.type) {
|
||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getUB(ins.reg2!!).toUInt(), registers.getUB(ins.reg3!!).toUInt())
|
||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getUW(ins.reg2!!).toUInt(), registers.getUW(ins.reg3!!).toUInt())
|
||||
VmDataType.BYTE -> Pair(registers.getUB(ins.reg1!!).toUInt(), registers.getUB(ins.reg2!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getUW(ins.reg1!!).toUInt(), registers.getUW(ins.reg2!!).toUInt())
|
||||
VmDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ class TestInstructions: FunSpec({
|
||||
ins.type shouldBe null
|
||||
ins.reg1 shouldBe null
|
||||
ins.reg2 shouldBe null
|
||||
ins.reg3 shouldBe null
|
||||
ins.value shouldBe null
|
||||
ins.symbol shouldBe null
|
||||
ins.toString() shouldBe "nop"
|
||||
@ -28,7 +27,6 @@ class TestInstructions: FunSpec({
|
||||
ins.type shouldBe VmDataType.BYTE
|
||||
ins.reg1 shouldBe 42
|
||||
ins.reg2 shouldBe null
|
||||
ins.reg3 shouldBe null
|
||||
ins.value shouldBe 9999
|
||||
ins.symbol shouldBe null
|
||||
ins.toString() shouldBe "bz.b r42,9999"
|
||||
@ -40,7 +38,6 @@ class TestInstructions: FunSpec({
|
||||
ins.type shouldBe VmDataType.WORD
|
||||
ins.reg1 shouldBe 11
|
||||
ins.reg2 shouldBe null
|
||||
ins.reg3 shouldBe null
|
||||
ins.value shouldBe null
|
||||
ins.symbol shouldBe listOf("a","b","c")
|
||||
ins.toString() shouldBe "bz.w r11,_a.b.c"
|
||||
|
Loading…
x
Reference in New Issue
Block a user