vm: limit int instructions to just 2 register args

This commit is contained in:
Irmen de Jong 2022-05-11 22:35:02 +02:00
parent 4be7bc8323
commit 517cf61d11
10 changed files with 141 additions and 183 deletions

View File

@ -77,22 +77,19 @@ internal class VmCodeInstruction(
type: VmDataType?=null, type: VmDataType?=null,
reg1: Int?=null, // 0-$ffff reg1: Int?=null, // 0-$ffff
reg2: Int?=null, // 0-$ffff reg2: Int?=null, // 0-$ffff
reg3: Int?=null, // 0-$ffff
fpReg1: Int?=null, // 0-$ffff fpReg1: Int?=null, // 0-$ffff
fpReg2: Int?=null, // 0-$ffff fpReg2: Int?=null, // 0-$ffff
value: Int?=null, // 0-$ffff value: Int?=null, // 0-$ffff
fpValue: Float?=null, fpValue: Float?=null,
symbol: List<String>?=null // alternative to value symbol: List<String>?=null // alternative to value
): VmCodeLine() { ): 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 { init {
if(reg1!=null && (reg1<0 || reg1>65536)) if(reg1!=null && (reg1<0 || reg1>65536))
throw IllegalArgumentException("reg1 out of bounds") throw IllegalArgumentException("reg1 out of bounds")
if(reg2!=null && (reg2<0 || reg2>65536)) if(reg2!=null && (reg2<0 || reg2>65536))
throw IllegalArgumentException("reg2 out of bounds") 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)) if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
throw IllegalArgumentException("fpReg1 out of bounds") throw IllegalArgumentException("fpReg1 out of bounds")
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536)) if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))

View File

@ -115,7 +115,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val andReg = codeGen.vmRegisters.nextFree() val andReg = codeGen.vmRegisters.nextFree()
val notNegativeLabel = codeGen.createLabelName() val notNegativeLabel = codeGen.createLabelName()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80) 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.BZ, VmDataType.BYTE, reg1=andReg, symbol = notNegativeLabel)
code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister) code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
code += VmCodeInstruction(Opcode.EXT, 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 andReg = codeGen.vmRegisters.nextFree()
val notNegativeLabel = codeGen.createLabelName() val notNegativeLabel = codeGen.createLabelName()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000) 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.BZ, VmDataType.WORD, reg1=andReg, symbol = notNegativeLabel)
code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister) code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
code += VmCodeLabel(notNegativeLabel) 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 { private fun funcMkword(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val msbReg = codeGen.vmRegisters.nextFree() val msbReg = codeGen.vmRegisters.nextFree()
val lsbReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], msbReg, -1) code += exprGen.translateExpression(call.args[0], msbReg, -1)
code += exprGen.translateExpression(call.args[1], lsbReg, -1) code += exprGen.translateExpression(call.args[1], resultRegister, -1)
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg) code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg)
return code return code
} }

View File

@ -331,11 +331,11 @@ class CodeGen(internal val program: PtProgram,
val valueReg = vmRegisters.nextFree() val valueReg = vmRegisters.nextFree()
if(value>0) { if(value>0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value= value) 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 { else {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value= -value) 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) { if(value>0) {
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt()) code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=value) 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()) code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
} }
else { else {
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt()) code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=-value) 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()) code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
} }
} }
@ -409,7 +409,7 @@ class CodeGen(internal val program: PtProgram,
// just shift multiple bits // just shift multiple bits
val pow2reg = vmRegisters.nextFree() val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) 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 { } else {
if (factor == 0) { if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0) code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
@ -417,7 +417,7 @@ class CodeGen(internal val program: PtProgram,
else { else {
val factorReg = vmRegisters.nextFree() val factorReg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor) 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 return code
@ -450,7 +450,7 @@ class CodeGen(internal val program: PtProgram,
// just shift multiple bits // just shift multiple bits
val pow2reg = vmRegisters.nextFree() val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) 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 { } else {
if (factor == 0) { if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff) code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
@ -458,7 +458,7 @@ class CodeGen(internal val program: PtProgram,
else { else {
val factorReg = vmRegisters.nextFree() val factorReg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor) 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 return code

View File

@ -185,7 +185,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val regMask = codeGen.vmRegisters.nextFree() val regMask = codeGen.vmRegisters.nextFree()
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask) 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" -> { "not" -> {
val label = codeGen.createLabelName() val label = codeGen.createLabelName()
@ -194,7 +194,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeLabel(label) code += VmCodeLabel(label)
val regMask = codeGen.vmRegisters.nextFree() val regMask = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=1) 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") else -> throw AssemblyError("weird prefix operator")
} }
@ -329,7 +329,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
} else { } else {
if (greaterEquals) Opcode.SGE else Opcode.SGT 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 { } else {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
@ -339,7 +339,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
} else { } else {
if (greaterEquals) Opcode.SGE else Opcode.SGT 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 return code
} }
@ -365,7 +365,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
} else { } else {
if (lessEquals) Opcode.SLE else Opcode.SLT 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 { } else {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
@ -375,7 +375,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
} else { } else {
if (lessEquals) Opcode.SLE else Opcode.SLT 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 return code
} }
@ -395,14 +395,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeLabel(label) code += VmCodeLabel(label)
val regMask = codeGen.vmRegisters.nextFree() val regMask = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=regMask, value=1) 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 { } else {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1) code += translateExpression(binExpr.right, rightResultReg, -1)
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ 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 return code
} }
@ -418,7 +418,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1) code += translateExpression(binExpr.right, rightResultReg, -1)
val opc = if (signed) Opcode.ASRN else Opcode.LSRN 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 return code
} }
@ -432,7 +432,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
} }
@ -442,7 +442,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
} }
@ -451,7 +451,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
} }
@ -460,7 +460,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
} }
@ -471,7 +471,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
} }
@ -498,7 +498,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
@ -536,7 +536,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
@ -564,7 +564,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code
@ -600,7 +600,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1) code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -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 return code

View File

@ -3,7 +3,6 @@ TODO
For next release 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: use more instructions in codegen: branching
- vm: add more instructions operating directly on memory instead of only registers? - 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. - in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird.

View File

@ -25,29 +25,10 @@ main {
ubyte @shared value = inline_candidate() ubyte @shared value = inline_candidate()
float fl1 = 1.1 ubyte lowb = $31
float fl2 = 2.2 ubyte highb = $ea
floats.print_f(floats.pow(fl1,fl2)) uword result = mkword(highb, lowb)
txt.print_uwhex(result, true)
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")
; txt.print_ub(inline_candidate()) ; txt.print_ub(inline_candidate())
; txt.nl() ; txt.nl()

View File

@ -157,10 +157,10 @@ class Assembler {
fpReg2 = fpReg3 fpReg2 = fpReg3
fpReg3 = null fpReg3 = null
} }
if(reg3!=null)
throw IllegalArgumentException("too many reg arguments $line")
if(fpReg3!=null) if(fpReg3!=null)
throw IllegalArgumentException("too many fpreg arguments $line") throw IllegalArgumentException("too many fpreg arguments $line")
// TODO also check reg3
if(type!=null && type !in formats) if(type!=null && type !in formats)
throw IllegalArgumentException("invalid type code for $line") throw IllegalArgumentException("invalid type code for $line")
@ -168,16 +168,12 @@ class Assembler {
throw IllegalArgumentException("needs reg1 for $line") throw IllegalArgumentException("needs reg1 for $line")
if(format.reg2 && reg2==null) if(format.reg2 && reg2==null)
throw IllegalArgumentException("needs reg2 for $line") throw IllegalArgumentException("needs reg2 for $line")
if(format.reg3 && reg3==null)
throw IllegalArgumentException("needs reg3 for $line")
if(format.value && value==null) if(format.value && value==null)
throw IllegalArgumentException("needs value for $line") throw IllegalArgumentException("needs value for $line")
if(!format.reg1 && reg1!=null) if(!format.reg1 && reg1!=null)
throw IllegalArgumentException("invalid reg1 for $line") throw IllegalArgumentException("invalid reg1 for $line")
if(!format.reg2 && reg2!=null) if(!format.reg2 && reg2!=null)
throw IllegalArgumentException("invalid reg2 for $line") throw IllegalArgumentException("invalid reg2 for $line")
if(!format.reg3 && reg3!=null)
throw IllegalArgumentException("invalid reg3 for $line")
if(value!=null && opcode !in OpcodesWithAddress) { if(value!=null && opcode !in OpcodesWithAddress) {
when (type) { when (type) {
VmDataType.BYTE -> { VmDataType.BYTE -> {
@ -200,7 +196,7 @@ class Assembler {
if(format.fpValue) if(format.fpValue)
floatValue = value!! 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))
} }
} }

View File

@ -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) 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) 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) 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 seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0
sne reg1, reg2, reg3 - set reg=1 if reg2 != reg3, otherwise set reg1=0 sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0
slt reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (unsigned), otherwise set reg1=0 slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
slts reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (signed), otherwise set reg1=0 slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0
sle reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (unsigned), otherwise set reg1=0 sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
sles reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (signed), otherwise set reg1=0 sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0
sgt reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (unsigned), otherwise set reg1=0 sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
sgts reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (signed), otherwise set reg1=0 sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0
sge reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (unsigned), otherwise set reg1=0 sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
sges reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (signed), otherwise set reg1=0 sges reg1, reg2 - set reg=1 if reg1 >= reg2 (signed), otherwise set reg1=0
ARITHMETIC ARITHMETIC
@ -96,11 +96,11 @@ incm address - memory at address += 1
dec reg1 - reg1 = reg1-1 dec reg1 - reg1 = reg1-1
decm address - memory at address -= 1 decm address - memory at address -= 1
neg reg1 - reg1 = sign negation of reg1 neg reg1 - reg1 = sign negation of reg1
add reg1, reg2, reg3 - reg1 = reg2+reg3 (unsigned + signed) add reg1, reg2 - reg1 += reg2 (unsigned + signed)
sub reg1, reg2, reg3 - reg1 = reg2-reg3 (unsigned + signed) sub reg1, reg2 - reg1 -= reg2 (unsigned + signed)
mul reg1, reg2, reg3 - unsigned multiply reg1=reg2*reg3 note: byte*byte->byte, no type extension to word! mul reg1, reg2 - unsigned multiply reg1 *= reg2 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 div reg1, reg2 - unsigned division reg1 /= reg2 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 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 sqrt reg1, reg2 - reg1 is the square root of reg2
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1) 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) 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. All have type b or w.
and reg1, reg2, reg3 - reg1 = reg2 bitwise and reg3 and reg1, reg2 - reg1 = reg1 bitwise and reg2
or reg1, reg2, reg3 - reg1 = reg2 bitwise or reg3 or reg1, reg2 - reg1 = reg1 bitwise or reg2
xor reg1, reg2, reg3 - reg1 = reg2 bitwise xor reg3 xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
lsrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
asrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + 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, reg3 - reg1 = multi-shift reg2 left by reg3 bits + 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 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 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 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 nop - do nothing
breakpoint - trigger a breakpoint 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) 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 push [b, w] reg1 - push value in reg1 on the stack
pop [b, w] reg1 - pop value from stack into reg1 pop [b, w] reg1 - pop value from stack into reg1
@ -289,7 +289,6 @@ data class Instruction(
val type: VmDataType?=null, val type: VmDataType?=null,
val reg1: Int?=null, // 0-$ffff val reg1: Int?=null, // 0-$ffff
val reg2: Int?=null, // 0-$ffff val reg2: Int?=null, // 0-$ffff
val reg3: Int?=null, // 0-$ffff
val fpReg1: Int?=null, // 0-$ffff val fpReg1: Int?=null, // 0-$ffff
val fpReg2: Int?=null, // 0-$ffff val fpReg2: Int?=null, // 0-$ffff
val value: Int?=null, // 0-$ffff val value: Int?=null, // 0-$ffff
@ -302,17 +301,13 @@ data class Instruction(
throw IllegalArgumentException("missing type") throw IllegalArgumentException("missing type")
val format = formats.getValue(type) val format = formats.getValue(type)
if(format.reg1 && reg1==null || if(format.reg1 && reg1==null || format.reg2 && reg2==null)
format.reg2 && reg2==null ||
format.reg3 && reg3==null)
throw IllegalArgumentException("missing a register (int)") throw IllegalArgumentException("missing a register (int)")
if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null) if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null)
throw IllegalArgumentException("missing a register (float)") throw IllegalArgumentException("missing a register (float)")
if(!format.reg1 && reg1!=null || if(!format.reg1 && reg1!=null || !format.reg2 && reg2!=null)
!format.reg2 && reg2!=null ||
!format.reg3 && reg3!=null)
throw IllegalArgumentException("too many registers (int)") throw IllegalArgumentException("too many registers (int)")
if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null) if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null)
@ -346,10 +341,6 @@ data class Instruction(
result.add("r$it") result.add("r$it")
result.add(",") result.add(",")
} }
reg3?.let {
result.add("r$it")
result.add(",")
}
fpReg1?.let { fpReg1?.let {
result.add("fr$it") result.add("fr$it")
result.add(",") result.add(",")
@ -376,7 +367,7 @@ data class Instruction(
} }
data class InstructionFormat(val datatype: VmDataType?, 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 fpReg1: Boolean, val fpReg2: Boolean,
val value: Boolean, val value: Boolean,
val fpValue: Boolean) { val fpValue: Boolean) {
@ -386,7 +377,6 @@ data class InstructionFormat(val datatype: VmDataType?,
for(part in spec.split('|').map{ it.trim() }) { for(part in spec.split('|').map{ it.trim() }) {
var reg1 = false var reg1 = false
var reg2 = false var reg2 = false
var reg3 = false
var fpreg1 = false var fpreg1 = false
var fpreg2 = false var fpreg2 = false
var value = false var value = false
@ -397,7 +387,6 @@ data class InstructionFormat(val datatype: VmDataType?,
when(splits.next()) { when(splits.next()) {
"r1" -> reg1=true "r1" -> reg1=true
"r2" -> reg2=true "r2" -> reg2=true
"r3" -> reg3=true
"fr1" -> fpreg1=true "fr1" -> fpreg1=true
"fr2" -> fpreg2=true "fr2" -> fpreg2=true
"v" -> value = true "v" -> value = true
@ -406,13 +395,13 @@ data class InstructionFormat(val datatype: VmDataType?,
} }
} }
if(typespec=="N") 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) 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) 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) 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 return result
} }
@ -456,38 +445,38 @@ val instructionFormats = mutableMapOf(
Opcode.BLES to InstructionFormat.from("BW,r1,r2,v"), Opcode.BLES to InstructionFormat.from("BW,r1,r2,v"),
Opcode.BGE 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.BGES to InstructionFormat.from("BW,r1,r2,v"),
Opcode.SEQ to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SEQ to InstructionFormat.from("BW,r1,r2"),
Opcode.SNE to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SNE to InstructionFormat.from("BW,r1,r2"),
Opcode.SLT to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SLT to InstructionFormat.from("BW,r1,r2"),
Opcode.SLTS to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SLTS to InstructionFormat.from("BW,r1,r2"),
Opcode.SGT to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SGT to InstructionFormat.from("BW,r1,r2"),
Opcode.SGTS to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SGTS to InstructionFormat.from("BW,r1,r2"),
Opcode.SLE to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SLE to InstructionFormat.from("BW,r1,r2"),
Opcode.SLES to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SLES to InstructionFormat.from("BW,r1,r2"),
Opcode.SGE to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SGE to InstructionFormat.from("BW,r1,r2"),
Opcode.SGES to InstructionFormat.from("BW,r1,r2,r3"), Opcode.SGES to InstructionFormat.from("BW,r1,r2"),
Opcode.INC to InstructionFormat.from("BW,r1"), Opcode.INC to InstructionFormat.from("BW,r1"),
Opcode.INCM to InstructionFormat.from("BW,v"), Opcode.INCM to InstructionFormat.from("BW,v"),
Opcode.DEC to InstructionFormat.from("BW,r1"), Opcode.DEC to InstructionFormat.from("BW,r1"),
Opcode.DECM to InstructionFormat.from("BW,v"), Opcode.DECM to InstructionFormat.from("BW,v"),
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"), Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
Opcode.ADD to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | 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.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SGN 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.RND to InstructionFormat.from("BW,r1 | F,fr1"),
Opcode.MOD to InstructionFormat.from("BW,r1,r2,r3"), Opcode.MOD to InstructionFormat.from("BW,r1,r2"),
Opcode.CMP to InstructionFormat.from("BW,r1,r2"), Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
Opcode.EXT to InstructionFormat.from("BW,r1"), Opcode.EXT to InstructionFormat.from("BW,r1"),
Opcode.EXTS to InstructionFormat.from("BW,r1"), Opcode.EXTS to InstructionFormat.from("BW,r1"),
Opcode.AND to InstructionFormat.from("BW,r1,r2,r3"), Opcode.AND to InstructionFormat.from("BW,r1,r2"),
Opcode.OR to InstructionFormat.from("BW,r1,r2,r3"), Opcode.OR to InstructionFormat.from("BW,r1,r2"),
Opcode.XOR to InstructionFormat.from("BW,r1,r2,r3"), Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
Opcode.ASRN to InstructionFormat.from("BW,r1,r2,r3"), Opcode.ASRN to InstructionFormat.from("BW,r1,r2"),
Opcode.LSRN to InstructionFormat.from("BW,r1,r2,r3"), Opcode.LSRN to InstructionFormat.from("BW,r1,r2"),
Opcode.LSLN to InstructionFormat.from("BW,r1,r2,r3"), Opcode.LSLN to InstructionFormat.from("BW,r1,r2"),
Opcode.ASR to InstructionFormat.from("BW,r1"), Opcode.ASR to InstructionFormat.from("BW,r1"),
Opcode.LSR to InstructionFormat.from("BW,r1"), Opcode.LSR to InstructionFormat.from("BW,r1"),
Opcode.LSL 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.MSIG to InstructionFormat.from("BW,r1,r2"),
Opcode.PUSH to InstructionFormat.from("BW,r1"), Opcode.PUSH to InstructionFormat.from("BW,r1"),
Opcode.POP 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.CLC to InstructionFormat.from("N"),
Opcode.SEC to InstructionFormat.from("N"), Opcode.SEC to InstructionFormat.from("N"),
Opcode.BREAKPOINT to InstructionFormat.from("N"), Opcode.BREAKPOINT to InstructionFormat.from("N"),

View File

@ -527,73 +527,73 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
} }
private fun InsSEQ(i: 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 val value = if(left==right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSNE(i: Instruction) { 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 val value = if(left!=right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSLT(i: Instruction) { private fun InsSLT(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperandsU(i) val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left<right) 1 else 0 val value = if(left<right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSLTS(i: Instruction) { private fun InsSLTS(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperands(i) val (left, right) = getSetOnConditionOperands(i)
val value = if(left<right) 1 else 0 val value = if(left<right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSGT(i: Instruction) { private fun InsSGT(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperandsU(i) val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left>right) 1 else 0 val value = if(left>right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSGTS(i: Instruction) { private fun InsSGTS(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperands(i) val (left, right) = getSetOnConditionOperands(i)
val value = if(left>right) 1 else 0 val value = if(left>right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSLE(i: Instruction) { private fun InsSLE(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperandsU(i) val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left<=right) 1 else 0 val value = if(left<=right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSLES(i: Instruction) { private fun InsSLES(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperands(i) val (left, right) = getSetOnConditionOperands(i)
val value = if(left<=right) 1 else 0 val value = if(left<=right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSGE(i: Instruction) { private fun InsSGE(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperandsU(i) val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left>=right) 1 else 0 val value = if(left>=right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
private fun InsSGES(i: Instruction) { private fun InsSGES(i: Instruction) {
val (resultReg, left, right) = getSetOnConditionOperands(i) val (left, right) = getSetOnConditionOperands(i)
val value = if(left>=right) 1 else 0 val value = if(left>=right) 1 else 0
setResultReg(resultReg, value, i.type!!) setResultReg(i.reg1!!, value, i.type!!)
pc++ pc++
} }
@ -645,8 +645,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsADD(i: Instruction) { private fun InsADD(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!)
VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!) VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!)
} }
pc++ pc++
@ -654,16 +654,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsSUB(i: Instruction) { private fun InsSUB(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!)
VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!) VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!)
} }
pc++ pc++
} }
private fun InsMUL(i: Instruction) { private fun InsMUL(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!)
VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!) VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!)
} }
pc++ pc++
@ -671,8 +671,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsDIV(i: Instruction) { private fun InsDIV(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!)
VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!) VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!)
} }
pc++ pc++
@ -680,8 +680,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsMOD(i: Instruction) { private fun InsMOD(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("%", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("%", i.reg1!!, i.reg2!!)
VmDataType.WORD -> arithWord("%", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("%", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
pc++ pc++
@ -744,9 +744,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++ pc++
} }
private fun arithByte(operator: String, reg1: Int, reg2: Int, reg3: Int) { private fun arithByte(operator: String, reg1: Int, reg2: Int) {
val left = registers.getUB(reg2) val left = registers.getUB(reg1)
val right = registers.getUB(reg3) val right = registers.getUB(reg2)
val result = when(operator) { val result = when(operator) {
"+" -> left + right "+" -> left + right
"-" -> left - right "-" -> left - right
@ -764,9 +764,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUB(reg1, result.toUByte()) registers.setUB(reg1, result.toUByte())
} }
private fun arithWord(operator: String, reg1: Int, reg2: Int, reg3: Int) { private fun arithWord(operator: String, reg1: Int, reg2: Int) {
val left = registers.getUW(reg2) val left = registers.getUW(reg1)
val right = registers.getUW(reg3) val right = registers.getUW(reg2)
val result = when(operator) { val result = when(operator) {
"+" -> left + right "+" -> left + right
"-" -> left - right "-" -> left - right
@ -1019,9 +1019,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsCONCAT(i: Instruction) { private fun InsCONCAT(i: Instruction) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> { VmDataType.BYTE -> {
val lsb = registers.getUB(i.reg1!!)
val msb = registers.getUB(i.reg2!!) 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.WORD -> TODO("concat.w not yet supported, requires 32-bits registers")
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") 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> { private fun getLogicalOperandsU(i: Instruction): Pair<UInt, UInt> {
return when(i.type) { return when(i.type) {
VmDataType.BYTE -> Pair(registers.getUB(i.reg2!!).toUInt(), registers.getUB(i.reg3!!).toUInt()) VmDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
VmDataType.WORD -> Pair(registers.getUW(i.reg2!!).toUInt(), registers.getUW(i.reg3!!).toUInt()) VmDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
VmDataType.FLOAT -> { VmDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") 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> { private fun getLogicalOperandsS(i: Instruction): Pair<Int, Int> {
return when(i.type) { return when(i.type) {
VmDataType.BYTE -> Pair(registers.getSB(i.reg2!!).toInt(), registers.getSB(i.reg3!!).toInt()) VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
VmDataType.WORD -> Pair(registers.getSW(i.reg2!!).toInt(), registers.getSW(i.reg3!!).toInt()) VmDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
VmDataType.FLOAT -> { VmDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") 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) { return when(ins.type) {
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt()) VmDataType.BYTE -> Pair(registers.getSB(ins.reg1!!).toInt(), registers.getSB(ins.reg2!!).toInt())
VmDataType.WORD -> Triple(ins.reg1!!, registers.getSW(ins.reg2!!).toInt(), registers.getSW(ins.reg3!!).toInt()) VmDataType.WORD -> Pair(registers.getSW(ins.reg1!!).toInt(), registers.getSW(ins.reg2!!).toInt())
VmDataType.FLOAT -> { VmDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") 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) { return when(ins.type) {
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getUB(ins.reg2!!).toUInt(), registers.getUB(ins.reg3!!).toUInt()) VmDataType.BYTE -> Pair(registers.getUB(ins.reg1!!).toUInt(), registers.getUB(ins.reg2!!).toUInt())
VmDataType.WORD -> Triple(ins.reg1!!, registers.getUW(ins.reg2!!).toUInt(), registers.getUW(ins.reg3!!).toUInt()) VmDataType.WORD -> Pair(registers.getUW(ins.reg1!!).toUInt(), registers.getUW(ins.reg2!!).toUInt())
VmDataType.FLOAT -> { VmDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use float here")
} }

View File

@ -16,7 +16,6 @@ class TestInstructions: FunSpec({
ins.type shouldBe null ins.type shouldBe null
ins.reg1 shouldBe null ins.reg1 shouldBe null
ins.reg2 shouldBe null ins.reg2 shouldBe null
ins.reg3 shouldBe null
ins.value shouldBe null ins.value shouldBe null
ins.symbol shouldBe null ins.symbol shouldBe null
ins.toString() shouldBe "nop" ins.toString() shouldBe "nop"
@ -28,7 +27,6 @@ class TestInstructions: FunSpec({
ins.type shouldBe VmDataType.BYTE ins.type shouldBe VmDataType.BYTE
ins.reg1 shouldBe 42 ins.reg1 shouldBe 42
ins.reg2 shouldBe null ins.reg2 shouldBe null
ins.reg3 shouldBe null
ins.value shouldBe 9999 ins.value shouldBe 9999
ins.symbol shouldBe null ins.symbol shouldBe null
ins.toString() shouldBe "bz.b r42,9999" ins.toString() shouldBe "bz.b r42,9999"
@ -40,7 +38,6 @@ class TestInstructions: FunSpec({
ins.type shouldBe VmDataType.WORD ins.type shouldBe VmDataType.WORD
ins.reg1 shouldBe 11 ins.reg1 shouldBe 11
ins.reg2 shouldBe null ins.reg2 shouldBe null
ins.reg3 shouldBe null
ins.value shouldBe null ins.value shouldBe null
ins.symbol shouldBe listOf("a","b","c") ins.symbol shouldBe listOf("a","b","c")
ins.toString() shouldBe "bz.w r11,_a.b.c" ins.toString() shouldBe "bz.w r11,_a.b.c"