From 10c8cc35c5fd785691dd7ff529e97b4ee2dff525 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 2 May 2022 21:49:35 +0200 Subject: [PATCH] vm: implement float divide multiply sub add --- .../src/prog8/codegen/virtual/CodeGen.kt | 16 +++++- .../prog8/codegen/virtual/ExpressionGen.kt | 56 +++++++++++++++---- docs/source/todo.rst | 2 +- examples/test.p8 | 48 +++------------- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index adbd61625..32ce1ce82 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -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() diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index ed82dc614..e43aebff6 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -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) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 44104dfb4..1db6e94ac 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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. diff --git a/examples/test.p8 b/examples/test.p8 index f41a7d46c..a02c64d3b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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