vm: implement float divide multiply sub add

This commit is contained in:
Irmen de Jong 2022-05-02 21:49:35 +02:00
parent 30c2e3e8ff
commit 10c8cc35c5
4 changed files with 69 additions and 53 deletions

View File

@ -422,8 +422,20 @@ class CodeGen(internal val program: PtProgram,
return code
}
internal fun divideByConstFloat(fpReg: Int, factor: Float): VmCodeChunk {
val code = VmCodeChunk()
if(factor==1f)
return code
if(factor==0f) {
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = Float.MAX_VALUE)
} else {
val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.DIV, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = fpReg, fpReg3 = factorReg)
}
return code
}
internal fun divideByConst(dt: VmDataType, reg: Int, factor: Int): VmCodeChunk {
// TODO support floating-point factors
val code = VmCodeChunk()
if(factor==1)
return code
@ -439,7 +451,7 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(Opcode.LSRX, dt, reg1=reg, reg2=reg, reg3=pow2reg)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
}
else {
val factorReg = vmRegisters.nextFree()

View File

@ -273,10 +273,10 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val vmDt = codeGen.vmType(binExpr.left.type)
val signed = binExpr.left.type in SignedDatatypes
return when(binExpr.operator) {
"+" -> operatorPlus(binExpr, vmDt, resultRegister)
"-" -> operatorMinus(binExpr, vmDt, resultRegister)
"*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister )
"/" -> operatorDivide(binExpr, vmDt, resultRegister)
"+" -> operatorPlus(binExpr, vmDt, resultRegister, resultFpRegister)
"-" -> operatorMinus(binExpr, vmDt, resultRegister, resultFpRegister)
"*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister)
"/" -> operatorDivide(binExpr, vmDt, resultRegister, resultFpRegister)
"%" -> operatorModulo(binExpr, vmDt, resultRegister)
"|", "or" -> operatorOr(binExpr, vmDt, resultRegister)
"&", "and" -> operatorAnd(binExpr, vmDt, resultRegister)
@ -409,11 +409,21 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
val constFactorRight = binExpr.right as? PtNumber
if(vmDt==VmDataType.FLOAT) {
TODO("div float")
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
val factor = constFactorRight.number.toFloat()
code += codeGen.divideByConstFloat(resultFpRegister, factor)
} else {
val leftResultFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftResultFpReg)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.DIV, vmDt, fpReg1 = resultFpRegister, fpReg2=leftResultFpReg, fpReg3=rightResultFpReg)
}
} else {
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
code += translateExpression(binExpr.left, resultRegister, -1)
@ -448,7 +458,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftResultFpReg)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, reg2=leftResultFpReg, reg3=rightResultFpReg)
code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, fpReg2 = leftResultFpReg, fpReg3 = rightResultFpReg)
}
} else {
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
@ -470,10 +480,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
if(vmDt==VmDataType.FLOAT) {
TODO("minus float")
if((binExpr.right as? PtNumber)?.number==1.0) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += VmCodeInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister)
}
else {
val leftResultFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftResultFpReg)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.SUB, vmDt, fpReg1=resultFpRegister, fpReg2=leftResultFpReg, fpReg3=rightResultFpReg)
}
} else {
if((binExpr.right as? PtNumber)?.number==1.0) {
code += translateExpression(binExpr.left, resultRegister, -1)
@ -490,10 +510,24 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
if(vmDt==VmDataType.FLOAT) {
TODO("plus float")
if((binExpr.left as? PtNumber)?.number==1.0) {
code += translateExpression(binExpr.right, -1, resultFpRegister)
code += VmCodeInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
}
else if((binExpr.right as? PtNumber)?.number==1.0) {
code += translateExpression(binExpr.left, -1, resultFpRegister)
code += VmCodeInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
}
else {
val leftResultFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftResultFpReg)
code += translateExpression(binExpr.right, -1, rightResultFpReg)
code += VmCodeInstruction(Opcode.ADD, vmDt, fpReg1=resultFpRegister, fpReg2=leftResultFpReg, fpReg3=rightResultFpReg)
}
} else {
if((binExpr.left as? PtNumber)?.number==1.0) {
code += translateExpression(binExpr.right, resultRegister, -1)

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm: implement float div, minus, plus
- vm: implement float type casts to integer types
- vm: implement float any, all, reverse, sort
- vm: fix test fp calc result being 0
@ -31,6 +30,7 @@ Future Things and Ideas
Compiler:
- vm: codeGen: various TODOs to tweak code
- vm: codeGen: optimize codegen for comparison expressions in if statements, such as if x==0 ... else ...
- vm: make registers typed? so that it's immediately obvious what type they represent. Much like regular variables in memory.
so we have a set of byte registers, a set of word registers, and other sets if we introduce other types.
- vm: don't store symbol names in instructions to make optimizing the IR easier? but what about jumps to labels. And it's no longer readable by humans.

View File

@ -8,49 +8,19 @@
main {
sub start() {
ubyte ub = conv.str2ubyte("234")
txt.print_ub(ub)
txt.nl()
byte sb = conv.str2byte("-123")
txt.print_b(sb)
txt.nl()
uword uw = conv.str2uword("54321")
txt.print_uw(uw)
txt.nl()
word sw = conv.str2word("-12345")
txt.print_w(sw)
txt.nl()
float fl1 = 500.0
float fzero = 0.0
floats.print_f(fl1 / fzero)
txt.nl()
; TODO fix hex2uword and bin2uword
uw = conv.hex2uword("0")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("1")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("a")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("0")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("1")
txt.print_uw(uw)
txt.nl()
ubyte ub1 = 50
ubyte ubzero = 0
txt.print_ub(ub1/ubzero)
txt.nl()
uw = conv.hex2uword("$ea31")
txt.print_uw(uw)
txt.nl()
uw = conv.hex2uword("ea31")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("%100000111011101")
txt.print_uw(uw)
txt.nl()
uw = conv.bin2uword("100000111011101")
txt.print_uw(uw)
uword uw1 = 5000
uword uwzero = 0
txt.print_uw(uw1/uwzero)
txt.nl()
; float fl = 500.0