IR: added signed multiplication opcodes

This commit is contained in:
Irmen de Jong
2025-05-20 21:36:05 +02:00
parent acc630972a
commit 25d7f8808f
8 changed files with 237 additions and 58 deletions
@@ -134,7 +134,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val chunks = when (augAssign.operator) {
"+=" -> operatorPlusInplace(symbol, array, constAddress, memTarget, targetDt, value)
"-=" -> operatorMinusInplace(symbol, array, constAddress, memTarget, targetDt, value)
"*=" -> operatorMultiplyInplace(symbol, array, constAddress, memTarget, targetDt, value)
"*=" -> operatorMultiplyInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
"/=" -> operatorDivideInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
"|=" -> operatorOrInplace(symbol, array, constAddress, memTarget, targetDt, value)
"or=" -> operatorLogicalOrInplace(symbol, array, constAddress, memTarget, targetDt, value)
@@ -231,7 +231,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val tr = expressionEval.translateExpression(array.index)
addToResult(result, tr, tr.resultReg, -1)
if(!array.splitWords && eltSize>1)
result += codeGen.multiplyByConst(IRDataType.BYTE, tr.resultReg, eltSize)
result += codeGen.multiplyByConst(DataType.UBYTE, tr.resultReg, eltSize)
return tr.resultReg
}
@@ -793,7 +793,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
return result
}
private fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
private fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
if(array!=null) {
val eltSize = codeGen.program.memsizer.memorySize(array.type, null)
val result = mutableListOf<IRCodeChunkBase>()
@@ -807,7 +807,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val valueReg=codeGen.registers.next(eltDt)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.LOAD, eltDt, reg1=valueReg, immediate = constValue)
it += IRInstruction(Opcode.MULM, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
it += IRInstruction(opcode, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
}
}
return result
@@ -827,22 +828,23 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val tr = expressionEval.translateExpression(operand)
addToResult(result, tr, -1, tr.resultFpReg)
addInstr(result, if(constAddress!=null)
IRInstruction(Opcode.MULM, vmDt, fpReg1 = tr.resultFpReg, address = constAddress)
IRInstruction(Opcode.MULSM, vmDt, fpReg1 = tr.resultFpReg, address = constAddress)
else
IRInstruction(Opcode.MULM, vmDt, fpReg1 = tr.resultFpReg, labelSymbol = symbol)
IRInstruction(Opcode.MULSM, vmDt, fpReg1 = tr.resultFpReg, labelSymbol = symbol)
, null)
}
} else {
if(constFactorRight!=null && !constFactorRight.type.isFloat) {
val factor = constFactorRight.number.toInt()
result += codeGen.multiplyByConstInplace(vmDt, constAddress, symbol, factor)
result += codeGen.multiplyByConstInplace(vmDt, signed, constAddress, symbol, factor)
} else {
val tr = expressionEval.translateExpression(operand)
addToResult(result, tr, tr.resultReg, -1)
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
addInstr(result, if(constAddress!=null)
IRInstruction(Opcode.MULM, vmDt, reg1=tr.resultReg, address = constAddress)
IRInstruction(opcode, vmDt, reg1=tr.resultReg, address = constAddress)
else
IRInstruction(Opcode.MULM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
IRInstruction(opcode, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
, null)
}
}
@@ -3,6 +3,7 @@ package prog8.codegen.intermediate
import prog8.code.ast.*
import prog8.code.core.AssemblyError
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.intermediate.*
@@ -662,7 +663,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
addToResult(result, indexTr, indexTr.resultReg, -1)
result += IRCodeChunk(null, null).also {
if(eltSize>1)
it += codeGen.multiplyByConst(IRDataType.BYTE, indexTr.resultReg, eltSize)
it += codeGen.multiplyByConst(DataType.UBYTE, indexTr.resultReg, eltSize)
if(msb)
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=indexTr.resultReg)
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1=indexTr.resultReg, labelSymbol = target.variable.name)
@@ -683,7 +684,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
addToResult(result, indexTr, indexTr.resultReg, -1)
result += IRCodeChunk(null, null).also {
if(eltSize>1)
it += codeGen.multiplyByConst(IRDataType.BYTE, indexTr.resultReg, eltSize)
it += codeGen.multiplyByConst(DataType.UBYTE, indexTr.resultReg, eltSize)
if(msb)
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=indexTr.resultReg)
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexTr.resultReg, labelSymbol = target.variable.name)
@@ -2,10 +2,7 @@ package prog8.codegen.intermediate
import prog8.code.*
import prog8.code.ast.*
import prog8.code.core.AssemblyError
import prog8.code.core.BaseDataType
import prog8.code.core.Cx16VirtualRegisters
import prog8.code.core.Statusflag
import prog8.code.core.*
import prog8.intermediate.*
@@ -392,7 +389,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val tr = translateExpression(arrayIx.index)
addToResult(result, tr, tr.resultReg, -1)
if(eltSize>1)
result += codeGen.multiplyByConst(IRDataType.BYTE, tr.resultReg, eltSize)
result += codeGen.multiplyByConst(DataType.UBYTE, tr.resultReg, eltSize)
if(vmDt==IRDataType.FLOAT) {
resultFpRegister = codeGen.registers.next(IRDataType.FLOAT)
addInstr(result, IRInstruction(Opcode.LOADX, IRDataType.FLOAT, fpReg1 = resultFpRegister, reg1=tr.resultReg, labelSymbol = arrayVarSymbol), null)
@@ -565,8 +562,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
return when(binExpr.operator) {
"+" -> operatorPlus(binExpr, vmDt)
"-" -> operatorMinus(binExpr, vmDt)
"*" -> operatorMultiply(binExpr, vmDt)
"/" -> operatorDivide(binExpr, vmDt, signed)
"*" -> operatorMultiply(binExpr, binExpr.left.type)
"/" -> operatorDivide(binExpr, binExpr.left.type)
"%" -> operatorModulo(binExpr, vmDt)
"|" -> operatorOr(binExpr, vmDt, true)
"&" -> operatorAnd(binExpr, vmDt, true)
@@ -1224,7 +1221,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult {
private fun operatorDivide(binExpr: PtBinaryExpression, dt: DataType): ExpressionCodeResult {
val vmDt = irType(dt)
val result = mutableListOf<IRCodeChunkBase>()
val constFactorRight = binExpr.right as? PtNumber
if(vmDt==IRDataType.FLOAT) {
@@ -1239,7 +1237,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg)
addInstr(result, if(signed)
addInstr(result, if(dt.isSigned)
IRInstruction(Opcode.DIVSR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2=rightTr.resultFpReg)
else
IRInstruction(Opcode.DIVR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2=rightTr.resultFpReg)
@@ -1251,13 +1249,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val tr = translateExpression(binExpr.left)
addToResult(result, tr, tr.resultReg, -1)
val factor = constFactorRight.number.toInt()
result += codeGen.divideByConst(vmDt, tr.resultReg, factor, signed)
result += codeGen.divideByConst(vmDt, tr.resultReg, factor, dt.isSigned)
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
} else {
if(binExpr.right is PtNumber) {
val leftTr = translateExpression(binExpr.left)
addToResult(result, leftTr, leftTr.resultReg, -1)
addInstr(result, if (signed)
addInstr(result, if (dt.isSigned)
IRInstruction(Opcode.DIVS, vmDt, reg1 = leftTr.resultReg, immediate = (binExpr.right as PtNumber).number.toInt())
else
IRInstruction(Opcode.DIV, vmDt, reg1 = leftTr.resultReg, immediate = (binExpr.right as PtNumber).number.toInt())
@@ -1268,7 +1266,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addToResult(result, leftTr, leftTr.resultReg, -1)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, rightTr.resultReg, -1)
addInstr(result, if (signed)
addInstr(result, if (dt.isSigned)
IRInstruction(Opcode.DIVSR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg)
else
IRInstruction(Opcode.DIVR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg)
@@ -1279,7 +1277,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
}
private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
private fun operatorMultiply(binExpr: PtBinaryExpression, dt: DataType): ExpressionCodeResult {
val vmDt = irType(dt)
val result = mutableListOf<IRCodeChunkBase>()
val constFactorLeft = binExpr.left as? PtNumber
val constFactorRight = binExpr.right as? PtNumber
@@ -1301,7 +1300,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg)
addInstr(result, IRInstruction(Opcode.MULR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
addInstr(result, IRInstruction(Opcode.MULSR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
ExpressionCodeResult(result, vmDt, -1, leftTr.resultFpReg)
}
} else {
@@ -1309,20 +1308,21 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val tr = translateExpression(binExpr.right)
addToResult(result, tr, tr.resultReg, -1)
val factor = constFactorLeft.number.toInt()
result += codeGen.multiplyByConst(vmDt, tr.resultReg, factor)
result += codeGen.multiplyByConst(dt, tr.resultReg, factor)
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
} else if(constFactorRight!=null && !constFactorRight.type.isFloat) {
val tr = translateExpression(binExpr.left)
addToResult(result, tr, tr.resultReg, -1)
val factor = constFactorRight.number.toInt()
result += codeGen.multiplyByConst(vmDt, tr.resultReg, factor)
result += codeGen.multiplyByConst(dt, tr.resultReg, factor)
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
} else {
val leftTr = translateExpression(binExpr.left)
addToResult(result, leftTr, leftTr.resultReg, -1)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, rightTr.resultReg, -1)
addInstr(result, IRInstruction(Opcode.MULR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
val opcode = if(dt.isSigned) Opcode.MULSR else Opcode.MULR
addInstr(result, IRInstruction(opcode, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
ExpressionCodeResult(result, vmDt, leftTr.resultReg, -1)
}
}
@@ -780,7 +780,7 @@ class IRCodeGen(
code += if(factor==0.0) {
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = 0.0)
} else {
IRInstruction(Opcode.MUL, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
IRInstruction(Opcode.MULS, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
}
return code
}
@@ -798,38 +798,40 @@ class IRCodeGen(
val factorReg = registers.next(IRDataType.FLOAT)
code += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1=factorReg, immediateFp = factor)
code += if(knownAddress!=null)
IRInstruction(Opcode.MULM, IRDataType.FLOAT, fpReg1 = factorReg, address = knownAddress)
IRInstruction(Opcode.MULSM, IRDataType.FLOAT, fpReg1 = factorReg, address = knownAddress)
else
IRInstruction(Opcode.MULM, IRDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
IRInstruction(Opcode.MULSM, IRDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
}
return code
}
internal fun multiplyByConst(dt: IRDataType, reg: Int, factor: Int): IRCodeChunk {
internal fun multiplyByConst(dt: DataType, reg: Int, factor: Int): IRCodeChunk {
val irdt = irType(dt)
val code = IRCodeChunk(null, null)
if(factor==1)
return code
val pow2 = powersOfTwoInt.indexOf(factor)
if(pow2==1) {
// just shift 1 bit
code += IRInstruction(Opcode.LSL, dt, reg1=reg)
code += IRInstruction(Opcode.LSL, irdt, reg1=reg)
}
else if(pow2>=1) {
// just shift multiple bits
val pow2reg = registers.next(IRDataType.BYTE)
code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=pow2reg, immediate = pow2)
code += IRInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
code += IRInstruction(Opcode.LSLN, irdt, reg1=reg, reg2=pow2reg)
} else {
code += if (factor == 0) {
IRInstruction(Opcode.LOAD, dt, reg1=reg, immediate = 0)
IRInstruction(Opcode.LOAD, irdt, reg1=reg, immediate = 0)
} else {
IRInstruction(Opcode.MUL, dt, reg1=reg, immediate = factor)
val opcode = if(dt.isSigned) Opcode.MULS else Opcode.MUL
IRInstruction(opcode, irdt, reg1=reg, immediate = factor)
}
}
return code
}
internal fun multiplyByConstInplace(dt: IRDataType, knownAddress: Int?, symbol: String?, factor: Int): IRCodeChunk {
internal fun multiplyByConstInplace(dt: IRDataType, signed: Boolean, knownAddress: Int?, symbol: String?, factor: Int): IRCodeChunk {
val code = IRCodeChunk(null, null)
if(factor==1)
return code
@@ -859,10 +861,11 @@ class IRCodeGen(
else {
val factorReg = registers.next(dt)
code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, immediate = factor)
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
code += if(knownAddress!=null)
IRInstruction(Opcode.MULM, dt, reg1=factorReg, address = knownAddress)
IRInstruction(opcode, dt, reg1=factorReg, address = knownAddress)
else
IRInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = symbol)
IRInstruction(opcode, dt, reg1=factorReg, labelSymbol = symbol)
}
}
return code
@@ -357,7 +357,7 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
var changed = false
indexedInstructions.reversed().forEach { (idx, ins) ->
when (ins.opcode) {
Opcode.DIV, Opcode.DIVS, Opcode.MUL, Opcode.MOD -> {
Opcode.DIV, Opcode.DIVS, Opcode.MUL, Opcode.MULS, Opcode.MOD -> {
if (ins.immediate == 1) {
chunk.instructions.removeAt(idx)
changed = true
+49 -12
View File
@@ -4,18 +4,55 @@
main {
sub start() {
bool status
cx16.r0L, status = func()
if_cs {
cx16.r0L++
}
}
word w1, w2, w3, w4
uword uw1, uw2, uw3
asmsub func() -> ubyte @A, bool @Pv {
%asm {{
lda #99
sec
rts
}}
w1 = -111
w2 = 222
w3 = -333
w4 = -20
uw1 = 111
uw2 = 222
uw3 = 333
txt.print_w(w2*w3)
txt.spc()
w1 = w2 * w3
txt.print_w(w1)
txt.nl()
txt.print_w(w3*w4)
txt.nl()
txt.print_uw(uw2*uw3)
txt.spc()
uw1 = uw2 * uw3
txt.print_uw(uw1)
txt.nl()
txt.nl()
w1 = -111
w2 = 22222
w3 = -333
w4 = -17
uw1 = 111
uw2 = 22222
uw3 = 333
txt.print_w(w2/w3)
txt.spc()
w1 = w2 / w3
txt.print_w(w1)
txt.nl()
txt.print_w(w3/w4)
txt.nl()
txt.print_uw(uw2/uw3)
txt.spc()
uw1 = uw2 / uw3
txt.print_uw(uw1)
txt.nl()
}
}
@@ -146,13 +146,16 @@ subr reg1, reg2 - reg1 -= reg2
sub reg1, value - reg1 -= value
subm reg1, address - memory at address -= reg1
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
mulsr reg1, reg2 - signed 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!
muls reg1, value - signed multiply reg1 *= value note: byte*byte->byte, no type extension to word!
mulm reg1, address - unsigned memory at address *= reg2 note: byte*byte->byte, no type extension to word!
mulsm reg1, address - signed memory at address *= reg2 note: byte*byte->byte, no type extension to word!
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
divsr reg1, reg2 - signed division reg1 /= reg2 note: division by zero yields max signed int 127 / 32767
div reg1, value - unsigned division reg1 /= value note: division by zero yields max int $ff/$ffff
divs reg1, value - signed division reg1 /= value note: division by zero yields max signed int 127 / 32767
divm reg1, address - memory at address /= reg2 note: division by zero yields max int $ff/$ffff
divsm reg1, address - signed memory at address /= reg2 note: division by zero yields max signed int 127 / 32767
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
@@ -327,6 +330,9 @@ enum class Opcode {
MULR,
MUL,
MULM,
MULSR,
MULS,
MULSM,
DIVR,
DIV,
DIVM,
@@ -664,9 +670,12 @@ val instructionFormats = mutableMapOf(
Opcode.SUBR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.SUB to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.SUBM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.MUL to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.MULM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.MUL to InstructionFormat.from("BW,<>r1,<i"),
Opcode.MULM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.MULSR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.MULS to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.MULSM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.DIVR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.DIV to InstructionFormat.from("BW,<>r1,<i"),
Opcode.DIVM to InstructionFormat.from("BW,<r1,<>a"),
@@ -258,6 +258,9 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.MULR -> InsMULR(ins)
Opcode.MUL -> InsMUL(ins)
Opcode.MULM -> InsMULM(ins)
Opcode.MULSR -> InsMULSR(ins)
Opcode.MULS -> InsMULS(ins)
Opcode.MULSM -> InsMULSM(ins)
Opcode.DIVR -> InsDIVR(ins)
Opcode.DIV -> InsDIV(ins)
Opcode.DIVM -> InsDIVM(ins)
@@ -1118,6 +1121,48 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc()
}
private fun InsMULSR(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteSigned("*", i.reg1!!, i.reg2!!)
IRDataType.WORD -> plusMinusMultAnyWordSigned("*", i.reg1!!, i.reg2!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result = arithFloat(left, "*", right)
registers.setFloat(i.fpReg1!!, result)
}
}
nextPc()
}
private fun InsMULS(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultConstByteSigned("*", i.reg1!!, i.immediate!!.toByte())
IRDataType.WORD -> plusMinusMultConstWordSigned("*", i.reg1!!, i.immediate!!.toShort())
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "*", i.immediateFp!!)
registers.setFloat(i.fpReg1!!, result)
}
}
nextPc()
}
private fun InsMULSM(i: IRInstruction) {
val address = i.address!!
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteSignedInplace("*", i.reg1!!, address)
IRDataType.WORD -> plusMinusMultAnyWordSignedInplace("*", i.reg1!!, address)
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "*", right)
memory.setFloat(address, result)
}
}
nextPc()
}
private fun InsDIVR(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> divOrModByteUnsigned("/", i.reg1!!, i.reg2!!)
@@ -1355,6 +1400,18 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUB(reg1, result.toUByte())
}
private fun plusMinusMultAnyByteSigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getSB(reg1)
val right = registers.getSB(reg2)
val result = when(operator) {
"+" -> left + right
"-" -> left - right
"*" -> left * right
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setSB(reg1, result.toByte())
}
private fun plusMinusMultConstByte(operator: String, reg1: Int, value: UByte) {
val left = registers.getUB(reg1)
val result = when(operator) {
@@ -1366,6 +1423,17 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUB(reg1, result.toUByte())
}
private fun plusMinusMultConstByteSigned(operator: String, reg1: Int, value: Byte) {
val left = registers.getSB(reg1)
val result = when(operator) {
"+" -> left + value
"-" -> left - value
"*" -> left * value
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setSB(reg1, result.toByte())
}
private fun plusMinusMultAnyByteInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUB(address)
val operand = registers.getUB(reg1)
@@ -1378,6 +1446,18 @@ class VirtualMachine(irProgram: IRProgram) {
memory.setUB(address, result.toUByte())
}
private fun plusMinusMultAnyByteSignedInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getSB(address)
val operand = registers.getSB(reg1)
val result = when(operator) {
"+" -> memvalue + operand
"-" -> memvalue - operand
"*" -> memvalue * operand
else -> throw IllegalArgumentException("operator byte $operator")
}
memory.setSB(address, result.toByte())
}
private fun divModByteSigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getSB(reg1)
val right = registers.getSB(reg2)
@@ -1528,6 +1608,22 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(reg1, result.toUShort())
}
private fun plusMinusMultAnyWordSigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getSW(reg1)
val right = registers.getSW(reg2)
val result: Int
when(operator) {
"+" -> result = left + right
"-" -> result = left - right
"*" -> {
result = left.toInt() * right
mul16LastUpper = result.toUInt() shr 16
}
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setSW(reg1, result.toShort())
}
private fun plusMinusMultConstWord(operator: String, reg1: Int, value: UShort) {
val left = registers.getUW(reg1)
val result: UInt
@@ -1543,6 +1639,21 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(reg1, result.toUShort())
}
private fun plusMinusMultConstWordSigned(operator: String, reg1: Int, value: Short) {
val left = registers.getSW(reg1)
val result: Int
when(operator) {
"+" -> result = left + value
"-" -> result = left - value
"*" -> {
result = left.toInt() * value
mul16LastUpper = result.toUInt() shr 16
}
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setSW(reg1, result.toShort())
}
private fun plusMinusMultAnyWordInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUW(address)
val operand = registers.getUW(reg1)
@@ -1559,6 +1670,22 @@ class VirtualMachine(irProgram: IRProgram) {
memory.setUW(address, result.toUShort())
}
private fun plusMinusMultAnyWordSignedInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getSW(address)
val operand = registers.getSW(reg1)
val result: Int
when(operator) {
"+" -> result = memvalue + operand
"-" -> result = memvalue - operand
"*" -> {
result = memvalue.toInt() * operand
mul16LastUpper = result.toUInt() shr 16
}
else -> throw IllegalArgumentException("operator word $operator")
}
memory.setSW(address, result.toShort())
}
private fun divOrModWordUnsigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getUW(reg1)
val right = registers.getUW(reg2)