added immediate value vm arithmetic instructions because these are so common

This commit is contained in:
Irmen de Jong 2022-07-12 15:15:28 +02:00
parent 840331347b
commit 314398ba4c
7 changed files with 287 additions and 86 deletions

View File

@ -349,14 +349,10 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(Opcode.DEC, dt, reg1=reg)
}
else -> {
val valueReg = vmRegisters.nextFree()
if(value>0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value= value)
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 = valueReg)
code += if(value>0) {
VmCodeInstruction(Opcode.ADD, dt, reg1 = reg, value=value)
} else {
VmCodeInstruction(Opcode.SUB, dt, reg1 = reg, value=-value)
}
}
}
@ -387,13 +383,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 = operandReg)
code += VmCodeInstruction(Opcode.ADDR, 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 = operandReg)
code += VmCodeInstruction(Opcode.SUBR, dt, reg1 = valueReg, reg2 = operandReg)
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
}
}
@ -405,12 +401,10 @@ class CodeGen(internal val program: PtProgram,
val code = VmCodeChunk()
if(factor==1f)
return code
if(factor==0f) {
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = 0f)
code += if(factor==0f) {
VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = 0f)
} else {
val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
code += VmCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = factorReg)
VmCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
}
return code
}
@ -446,13 +440,10 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
}
else {
val factorReg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=factorReg)
code += if (factor == 0) {
VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
} else {
VmCodeInstruction(Opcode.MUL, dt, reg1=reg, value=factor)
}
}
return code
@ -489,12 +480,10 @@ class CodeGen(internal val program: PtProgram,
val code = VmCodeChunk()
if(factor==1f)
return code
if(factor==0f) {
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = Float.MAX_VALUE)
code += if(factor==0f) {
VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = Float.MAX_VALUE)
} else {
val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
code += VmCodeInstruction(Opcode.DIVS, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = factorReg)
VmCodeInstruction(Opcode.DIVS, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
}
return code
}
@ -536,16 +525,13 @@ class CodeGen(internal val program: PtProgram,
else
VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
}
else {
val factorReg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
code += if(signed)
VmCodeInstruction(Opcode.DIVS, dt, reg1=reg, reg2=factorReg)
code += if (factor == 0) {
VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
} else {
if(signed)
VmCodeInstruction(Opcode.DIVS, dt, reg1=reg, value=factor)
else
VmCodeInstruction(Opcode.DIV, dt, reg1=reg, reg2=factorReg)
VmCodeInstruction(Opcode.DIV, dt, reg1=reg, value=factor)
}
}
return code

View File

@ -516,9 +516,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
throw IllegalArgumentException("floating-point modulo not supported")
val code = VmCodeChunk()
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=rightResultReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, resultRegister, -1)
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
} else {
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.MODR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
}
return code
}
@ -539,9 +544,9 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += if(signed)
VmCodeInstruction(Opcode.DIVS, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
VmCodeInstruction(Opcode.DIVSR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
else
VmCodeInstruction(Opcode.DIV, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
VmCodeInstruction(Opcode.DIVR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
}
} else {
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
@ -550,12 +555,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += codeGen.divideByConst(vmDt, resultRegister, factor, signed)
} else {
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += if(signed)
VmCodeInstruction(Opcode.DIVS, vmDt, reg1=resultRegister, reg2=rightResultReg)
else
VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=rightResultReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, resultRegister, -1)
code += if (signed)
VmCodeInstruction(Opcode.DIVS, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
else
VmCodeInstruction(Opcode.DIV, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
} else {
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += if (signed)
VmCodeInstruction(Opcode.DIVSR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
else
VmCodeInstruction(Opcode.DIVR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
}
}
}
return code
@ -609,7 +622,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
code += VmCodeInstruction(Opcode.MULR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
}
} else {
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
@ -624,7 +637,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=rightResultReg)
code += VmCodeInstruction(Opcode.MULR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
}
}
return code
@ -663,10 +676,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister)
}
else {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.SUB, vmDt, fpReg1=resultFpRegister, fpReg2=rightResultFpReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += VmCodeInstruction(Opcode.SUB, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
} else {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.SUBR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
}
}
} else {
if((binExpr.right as? PtNumber)?.number==1.0) {
@ -674,10 +692,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
}
else {
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=rightResultReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, resultRegister, -1)
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1 = resultRegister, value = (binExpr.right as PtNumber).number.toInt())
} else {
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.SUBR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
}
}
}
return code
@ -719,10 +742,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
}
else {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.ADD, vmDt, fpReg1=resultFpRegister, fpReg2=rightResultFpReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += VmCodeInstruction(Opcode.ADD, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
} else {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.ADDR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
}
}
} else {
if((binExpr.left as? PtNumber)?.number==1.0) {
@ -734,10 +762,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
}
else {
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=rightResultReg)
if(binExpr.right is PtNumber) {
code += translateExpression(binExpr.left, resultRegister, -1)
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
} else {
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.ADDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
}
}
}
return code

View File

@ -109,7 +109,7 @@ bges reg1, reg2, location - jump to location in program given by l
}
private fun removeUselessArithmetic(block: VmCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
// TODO this is hard to solve atm because the values are loaded into registers first
// TODO this is hard to solve for the non-immediate instructions atm because the values are loaded into registers first
var changed = false
indexedInstructions.reversed().forEach { (idx, ins) ->
when (ins.opcode) {

View File

@ -3,7 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- add VM instructions to add/sub/mul/div/mod by an immediate value
- vm: add logical instructions taking immediate value as well
...

View File

@ -6,9 +6,11 @@ main {
sub start() {
bool @shared zz
ubyte xx
ubyte yy
while xx<42 {
xx++
xx = yy+99
xx = yy*5
}
txt.print_ub(xx)

View File

@ -97,17 +97,23 @@ dec reg1 - reg1 = reg1-1
decm address - memory at address -= 1
neg reg1 - reg1 = sign negation of reg1
negm address - sign negate memory at address
add reg1, reg2 - reg1 += reg2 (unsigned + signed)
addr reg1, reg2 - reg1 += reg2 (unsigned + signed)
add reg1, value - reg1 += value (unsigned + signed)
addm reg1, address - memory at address += reg1 (unsigned + signed)
sub reg1, reg2 - reg1 -= reg2 (unsigned + signed)
subr reg1, reg2 - reg1 -= reg2 (unsigned + signed)
sub reg1, value - reg1 -= value (unsigned + signed)
subm reg1, address - memory at address -= reg2 (unsigned + signed)
mul reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
mul reg1, value - unsigned multiply reg1 *= value note: byte*byte->byte, no type extension to word!
mulm reg1, address - memory at address *= reg2 note: byte*byte->byte, no type extension to word!
div reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max int $ff/$ffff
divr reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max int $ff/$ffff
div reg1, value - unsigned division reg1 /= value note: division by zero yields max int $ff/$ffff
divm reg1, address - memory at address /= reg2 note: division by zero yields max int $ff/$ffff
divs reg1, reg2 - signed division reg1 /= reg2 note: division by zero yields max signed int 127 / 32767
divsr reg1, reg2 - signed division reg1 /= reg2 note: division by zero yields max signed int 127 / 32767
divs reg1, value - signed division reg1 /= value note: division by zero yields max signed int 127 / 32767
divsm reg1, address - signed memory at address /= reg2 note: division by zero yields max signed int 127 / 32767
mod reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
modr reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
mod reg1, value - remainder (modulo) of unsigned division reg1 %= value 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)
@ -235,16 +241,22 @@ enum class Opcode {
DECM,
NEG,
NEGM,
ADDR,
ADD,
ADDM,
SUBR,
SUB,
SUBM,
MULR,
MUL,
MULM,
DIVR,
DIV,
DIVM,
DIVSR,
DIVS,
DIVSM,
MODR,
MOD,
SQRT,
SGN,
@ -532,20 +544,26 @@ val instructionFormats = mutableMapOf(
Opcode.DECM to InstructionFormat.from("BW,v"),
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
Opcode.NEGM to InstructionFormat.from("BW,v | F,v"),
Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.ADDR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.ADD to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.ADDM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SUBR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SUB to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.SUBM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.MULR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.MUL to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.MULM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.DIV to InstructionFormat.from("BW,r1,r2"),
Opcode.DIVR to InstructionFormat.from("BW,r1,r2"),
Opcode.DIV to InstructionFormat.from("BW,r1,v"),
Opcode.DIVM to InstructionFormat.from("BW,r1,v"),
Opcode.DIVS to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.DIVSR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.DIVS to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.DIVSM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
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.MODR to InstructionFormat.from("BW,r1,r2"),
Opcode.MOD to InstructionFormat.from("BW,r1,v"),
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
Opcode.EXT to InstructionFormat.from("BW,r1"),
Opcode.EXTS to InstructionFormat.from("BW,r1"),

View File

@ -140,16 +140,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.DECM -> InsDECM(ins)
Opcode.NEG -> InsNEG(ins)
Opcode.NEGM -> InsNEGM(ins)
Opcode.ADDR -> InsADDR(ins)
Opcode.ADD -> InsADD(ins)
Opcode.ADDM -> InsADDM(ins)
Opcode.SUBR -> InsSUBR(ins)
Opcode.SUB -> InsSUB(ins)
Opcode.SUBM -> InsSUBM(ins)
Opcode.MULR -> InsMULR(ins)
Opcode.MUL -> InsMUL(ins)
Opcode.MULM -> InsMULM(ins)
Opcode.DIVR -> InsDIVR(ins)
Opcode.DIV -> InsDIV(ins)
Opcode.DIVM -> InsDIVM(ins)
Opcode.DIVSR -> InsDIVSR(ins)
Opcode.DIVS -> InsDIVS(ins)
Opcode.DIVSM -> InsDIVSM(ins)
Opcode.MODR -> InsMODR(ins)
Opcode.MOD -> InsMOD(ins)
Opcode.SGN -> InsSGN(ins)
Opcode.CMP -> InsCMP(ins)
@ -715,7 +721,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsADD(i: Instruction) {
private fun InsADDR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("+", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("+", i.reg1!!, i.reg2!!)
@ -729,6 +735,19 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsADD(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultConstByte("+", i.reg1!!, i.value!!.toUByte())
VmDataType.WORD -> plusMinusMultConstWord("+", i.reg1!!, i.value!!.toUShort())
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "+", i.fpValue!!)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsADDM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
@ -744,7 +763,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsSUB(i: Instruction) {
private fun InsSUBR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("-", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("-", i.reg1!!, i.reg2!!)
@ -758,6 +777,19 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsSUB(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultConstByte("-", i.reg1!!, i.value!!.toUByte())
VmDataType.WORD -> plusMinusMultConstWord("-", i.reg1!!, i.value!!.toUShort())
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "-", i.fpValue!!)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsSUBM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
@ -773,7 +805,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsMUL(i: Instruction) {
private fun InsMULR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("*", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("*", i.reg1!!, i.reg2!!)
@ -787,6 +819,19 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsMUL(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultConstByte("*", i.reg1!!, i.value!!.toUByte())
VmDataType.WORD -> plusMinusMultConstWord("*", i.reg1!!, i.value!!.toUShort())
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "*", i.fpValue!!)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsMULM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
@ -802,7 +847,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsDIV(i: Instruction) {
private fun InsDIVR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModByteUnsigned("/", i.reg1!!, i.reg2!!)
VmDataType.WORD -> divModWordUnsigned("/", i.reg1!!, i.reg2!!)
@ -811,6 +856,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsDIV(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModConstByteUnsigned("/", i.reg1!!, i.value!!.toUByte())
VmDataType.WORD -> divModConstWordUnsigned("/", i.reg1!!, i.value!!.toUShort())
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
pc++
}
private fun InsDIVM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
@ -821,7 +875,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsDIVS(i: Instruction) {
private fun InsDIVSR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModByteSigned("/", i.reg1!!, i.reg2!!)
VmDataType.WORD -> divModWordSigned("/", i.reg1!!, i.reg2!!)
@ -835,6 +889,19 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsDIVS(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModConstByteSigned("/", i.reg1!!, i.value!!.toByte())
VmDataType.WORD -> divModConstWordSigned("/", i.reg1!!, i.value!!.toShort())
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "/", i.fpValue!!)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsDIVSM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
@ -850,7 +917,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsMOD(i: Instruction) {
private fun InsMODR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModByteUnsigned("%", i.reg1!!, i.reg2!!)
VmDataType.WORD -> divModWordUnsigned("%", i.reg1!!, i.reg2!!)
@ -859,6 +926,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsMOD(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> divModConstByteUnsigned("%", i.reg1!!, i.value!!.toUByte())
VmDataType.WORD -> divModConstWordUnsigned("%", i.reg1!!, i.value!!.toUShort())
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
pc++
}
private fun InsSGN(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> registers.setSB(i.reg1!!, registers.getSB(i.reg2!!).toInt().sign.toByte())
@ -928,6 +1004,17 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUB(reg1, result.toUByte())
}
private fun plusMinusMultConstByte(operator: String, reg1: Int, value: UByte) {
val left = registers.getUB(reg1)
val result = when(operator) {
"+" -> left + value
"-" -> left - value
"*" -> left * value
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setUB(reg1, result.toUByte())
}
private fun plusMinusMultAnyByteInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUB(address)
val operand = registers.getUB(reg1)
@ -957,6 +1044,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setSB(reg1, result.toByte())
}
private fun divModConstByteSigned(operator: String, reg1: Int, value: Byte) {
val left = registers.getSB(reg1)
val result = when(operator) {
"/" -> {
if(value==0.toByte()) 127
else left / value
}
"%" -> {
if(value==0.toByte()) 127
else left % value
}
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setSB(reg1, result.toByte())
}
private fun divModByteSignedInplace(operator: String, reg1: Int, address: Int) {
val left = memory.getSB(address)
val right = registers.getSB(reg1)
@ -991,6 +1094,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUB(reg1, result.toUByte())
}
private fun divModConstByteUnsigned(operator: String, reg1: Int, value: UByte) {
val left = registers.getUB(reg1)
val result = when(operator) {
"/" -> {
if(value==0.toUByte()) 0xffu
else left / value
}
"%" -> {
if(value==0.toUByte()) 0xffu
else left % value
}
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setUB(reg1, result.toUByte())
}
private fun divModByteUnsignedInplace(operator: String, reg1: Int, address: Int) {
val left = memory.getUB(address)
val right = registers.getUB(reg1)
@ -1020,6 +1139,17 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUW(reg1, result.toUShort())
}
private fun plusMinusMultConstWord(operator: String, reg1: Int, value: UShort) {
val left = registers.getUW(reg1)
val result = when(operator) {
"+" -> left + value
"-" -> left - value
"*" -> left * value
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setUW(reg1, result.toUShort())
}
private fun plusMinusMultAnyWordInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUW(address)
val operand = registers.getUW(reg1)
@ -1049,6 +1179,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUW(reg1, result.toUShort())
}
private fun divModConstWordUnsigned(operator: String, reg1: Int, value: UShort) {
val left = registers.getUW(reg1)
val result = when(operator) {
"/" -> {
if(value==0.toUShort()) 0xffffu
else left / value
}
"%" -> {
if(value==0.toUShort()) 0xffffu
else left % value
}
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setUW(reg1, result.toUShort())
}
private fun divModWordUnsignedInplace(operator: String, reg1: Int, address: Int) {
val left = memory.getUW(address)
val right = registers.getUW(reg1)
@ -1083,6 +1229,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setSW(reg1, result.toShort())
}
private fun divModConstWordSigned(operator: String, reg1: Int, value: Short) {
val left = registers.getSW(reg1)
val result = when(operator) {
"/" -> {
if(value==0.toShort()) 32767
else left / value
}
"%" -> {
if(value==0.toShort()) 32767
else left % value
}
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setSW(reg1, result.toShort())
}
private fun divModWordSignedInplace(operator: String, reg1: Int, address: Int) {
val left = memory.getSW(address)
val right = registers.getSW(reg1)