diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 964b04fc4..9cbd0db51 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -762,4 +762,6 @@ class CodeGen(internal val program: PtProgram, builtinFuncGen.translate(call, resultRegister) internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0 + + internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0 } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index 660113ebf..3615854f5 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -363,24 +363,33 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, signed: Boolean): VmCodeChunk { val code = VmCodeChunk() - // TODO if shift is 1, use ASR/LSR instruction instead of multishift - val leftResultReg = codeGen.vmRegisters.nextFree() - val rightResultReg = codeGen.vmRegisters.nextFree() - code += translateExpression(binExpr.left, leftResultReg, -1) - code += translateExpression(binExpr.right, rightResultReg, -1) - val opc = if(signed) Opcode.ASRN else Opcode.LSRN - code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) + if(codeGen.isOne(binExpr.right)) { + code += translateExpression(binExpr.left, resultRegister, -1) + val opc = if (signed) Opcode.ASR else Opcode.LSR + code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister) + } else { + val leftResultReg = codeGen.vmRegisters.nextFree() + val rightResultReg = codeGen.vmRegisters.nextFree() + code += translateExpression(binExpr.left, leftResultReg, -1) + code += translateExpression(binExpr.right, rightResultReg, -1) + val opc = if (signed) Opcode.ASRN else Opcode.LSRN + code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister, reg2 = leftResultReg, reg3 = rightResultReg) + } return code } private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - // TODO if shift is 1, use LSL instruction instead of multishift - val leftResultReg = codeGen.vmRegisters.nextFree() - val rightResultReg = codeGen.vmRegisters.nextFree() - code += translateExpression(binExpr.left, leftResultReg, -1) - code += translateExpression(binExpr.right, rightResultReg, -1) - code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) + if(codeGen.isOne(binExpr.right)){ + code += translateExpression(binExpr.left, resultRegister, -1) + code += VmCodeInstruction(Opcode.LSL, vmDt, reg1=resultRegister) + } else { + val leftResultReg = codeGen.vmRegisters.nextFree() + val rightResultReg = codeGen.vmRegisters.nextFree() + code += translateExpression(binExpr.left, leftResultReg, -1) + code += translateExpression(binExpr.right, rightResultReg, -1) + code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) + } return code } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b1e534ec6..91060705c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: use more instructions in codegen: shift one +- vm: expressiongen: use resultRegister arg instead of allocating new leftResultReg - vm: use more instructions in codegen: branching - 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. diff --git a/examples/test.p8 b/examples/test.p8 index a1514d9f0..b369ad7b6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,63 +7,61 @@ ; NOTE: meant to test to virtual machine output target (use -target vitual) main { -; ubyte value = 42 -; -; sub inline_candidate() -> ubyte { -; return math.sin8u(value) -; } -; -; sub add(ubyte first, ubyte second) -> ubyte { -; return first + second -; } -; -; sub mul(ubyte first, ubyte second) -> ubyte { -; return first * second -; } + ubyte value = 42 + + sub inline_candidate() -> ubyte { + return math.sin8u(value) + } + + sub add(ubyte first, ubyte second) -> ubyte { + return first + second + } + + sub mul(ubyte first, ubyte second) -> ubyte { + return first * second + } sub start() { - uword[] arrayuw = [1111,2222,3333,4444] - txt.print_uw(arrayuw[1]) - txt.nl() - arrayuw[1] = 9999 - txt.print_uw(arrayuw[1]) - txt.nl() - arrayuw[1] = 0 - txt.print_uw(arrayuw[1]) - txt.nl() - float[] array = [1.1, 2.2, 3.3, 4.4] - floats.print_f(array[1]) + ubyte @shared value = inline_candidate() + value = %01011100 + byte @shared svalue = 99 + svalue = -svalue + @($5000) = not @($5000) + sys.set_carry() + rol(value) + rol(@($5000)) + txt.print_ub(value) txt.nl() - array[1] = 99.99 - floats.print_f(array[1]) + sys.set_carry() + ror(value) + ror(@($5000)) + txt.print_ub(value) txt.nl() - array[1] = 0 - floats.print_f(array[1]) txt.nl() - -; ubyte value = inline_candidate() -; byte svalue = 99 -; svalue = -svalue -; @($5000) = not @($5000) -; rol(value) -; rol(@($5000)) -; ror(value) -; ror(@($5000)) -; rol2(value) -; rol2(@($5000)) -; ror2(value) -; ror2(@($5000)) -; @($5000) <<= 1 -; @($5000) >>= 1 -; value <<= 1 -; value >>= 1 -; @($5000) <<= 3 -; @($5000) >>= 3 -; value <<= 3 -; value >>= 3 -; txt.print_ub(value) -; txt.nl() + value = %01011100 + sys.set_carry() + rol2(value) + rol2(@($5000)) + txt.print_ub(value) + txt.nl() + sys.clear_carry() + ror2(value) + ror2(@($5000)) + txt.print_ub(value) + txt.nl() + @($5000) <<= 1 + @($5000) >>= 1 + value <<= 1 + value >>= 1 + txt.print_ub(value) + txt.nl() + @($5000) <<= 3 + @($5000) >>= 3 + value <<= 3 + value >>= 3 + txt.print_ub(value) + txt.nl() ; txt.print_ub(inline_candidate()) ; txt.nl() diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index 337bad923..d3584afcb 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -124,8 +124,8 @@ asr reg1 - shift reg1 right by 1 bits (signe lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit -rol reg1 - rotate reg1 left by 1bits, not using carry + set Carry to shifted bit -roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit +rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit +roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit FLOATING POINT CONVERSIONS AND FUNCTIONS @@ -227,9 +227,9 @@ enum class Opcode { ASRN, LSRN, LSLN, - ASR, // TODO not used in codegen of shift 1 - LSR, // TODO not used in codegen of shift 1 - LSL, // TODO not used in codegen of shift 1 + ASR, + LSR, + LSL, ROR, ROXR, ROL,