diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 53a4196ac..4f140f37a 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -72,27 +72,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } result } - is PtTypeCast -> { - translate(expr, resultRegister, resultFpRegister) - } - is PtPrefix -> { - translate(expr, resultRegister, resultFpRegister) - } - is PtArrayIndexer -> { - translate(expr, resultRegister, resultFpRegister) - } - is PtBinaryExpression -> { - translate(expr, resultRegister, resultFpRegister) - } - is PtBuiltinFunctionCall -> { - codeGen.translateBuiltinFunc(expr, resultRegister) - } - is PtFunctionCall -> { - translate(expr, resultRegister, resultFpRegister) - } - is PtContainmentCheck -> { - translate(expr, resultRegister, resultFpRegister) - } + is PtTypeCast -> translate(expr, resultRegister, resultFpRegister) + is PtPrefix -> translate(expr, resultRegister, resultFpRegister) + is PtArrayIndexer -> translate(expr, resultRegister, resultFpRegister) + is PtBinaryExpression -> translate(expr, resultRegister, resultFpRegister) + is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr, resultRegister) + is PtFunctionCall -> translate(expr, resultRegister, resultFpRegister) + is PtContainmentCheck -> translate(expr, resultRegister, resultFpRegister) is PtRange, is PtArray, is PtString -> throw AssemblyError("range/arrayliteral/string should no longer occur as expression") @@ -430,11 +416,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1) } } else { - val rightResultReg = codeGen.registers.nextFree() - result += translateExpression(binExpr.left, resultRegister, -1) - result += translateExpression(binExpr.right, rightResultReg, -1) - val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ - addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + if(constValue(binExpr.right)==0.0) { + result += translateExpression(binExpr.left, resultRegister, -1) + val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ + addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister), null) + } else { + val rightResultReg = codeGen.registers.nextFree() + result += translateExpression(binExpr.left, resultRegister, -1) + result += translateExpression(binExpr.right, rightResultReg, -1) + val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ + addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null) + } } } return result diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 8c6d20915..a084d939a 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -835,6 +835,8 @@ internal class AstChecker(private val program: Program, else if(expr.operator == "~") { if(dt !in IntegerDatatypes) errors.err("can only use bitwise invert on integer types", expr.position) + if(dt==DataType.BOOL) + errors.err("bitwise invert is for integer types, use 'not' on booleans", expr.position) } super.visit(expr) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 803723088..5819f2aa1 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -6,7 +6,6 @@ For next release - make sure bool value is always 0 or 1 (all casts should convert), then: - rewrite bool=bool^1 into bool=not bool - should solve: bool bb = not bb -> larger code than bool bb ^= 1 - - should solve: bool xx = ~xx -> larger code than xx ^= 1 ... diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 2101f1e2d..e4215d49a 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -85,16 +85,18 @@ bgts reg1, reg2, address - jump to location in program given by l bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned) bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed) ( NOTE: there are no blt/ble instructions because these are equivalent to bgt/bge with the operands swapped around.) -seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0 -sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0 -slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0 -slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0 -sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0 -sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0 -sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0 -sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0 -sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0 -sges reg1, reg2 - set reg=1 if reg1 >= reg2 (signed), otherwise set reg1=0 +sz reg1, reg2 - set reg1=1 if reg2==0, otherwise set reg1=0 +snz reg1, reg2 - set reg1=1 if reg2!=0, otherwise set reg1=0 +seq reg1, reg2 - set reg1=1 if reg1 == reg2, otherwise set reg1=0 +sne reg1, reg2 - set reg1=1 if reg1 != reg2, otherwise set reg1=0 +slt reg1, reg2 - set reg1=1 if reg1 < reg2 (unsigned), otherwise set reg1=0 +slts reg1, reg2 - set reg1=1 if reg1 < reg2 (signed), otherwise set reg1=0 +sle reg1, reg2 - set reg1=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0 +sles reg1, reg2 - set reg1=1 if reg1 <= reg2 (signed), otherwise set reg1=0 +sgt reg1, reg2 - set reg1=1 if reg1 > reg2 (unsigned), otherwise set reg1=0 +sgts reg1, reg2 - set reg1=1 if reg1 > reg2 (signed), otherwise set reg1=0 +sge reg1, reg2 - set reg1=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0 +sges reg1, reg2 - set reg1=1 if reg1 >= reg2 (signed), otherwise set reg1=0 ARITHMETIC @@ -253,6 +255,8 @@ enum class Opcode { BGTS, BGE, BGES, + SZ, + SNZ, SEQ, SNE, SLT, @@ -569,6 +573,8 @@ val instructionFormats = mutableMapOf( Opcode.BGTS to InstructionFormat.from("BW,r1,r1,r1,r1,r1, InsBGTS(ins) Opcode.BGE -> InsBGEU(ins) Opcode.BGES -> InsBGES(ins) + Opcode.SZ -> InsSZ(ins) + Opcode.SNZ -> InsSNZ(ins) Opcode.SEQ -> InsSEQ(ins) Opcode.SNE -> InsSNE(ins) Opcode.SLT -> InsSLT(ins) @@ -782,6 +784,20 @@ class VirtualMachine(irProgram: IRProgram) { nextPc() } + private fun InsSZ(i: IRInstruction) { + val (_: Int, right: Int) = getSetOnConditionOperands(i) + val value = if(right==0) 1 else 0 + setResultReg(i.reg1!!, value, i.type!!) + nextPc() + } + + private fun InsSNZ(i: IRInstruction) { + val (_: Int, right: Int) = getSetOnConditionOperands(i) + val value = if(right!=0) 1 else 0 + setResultReg(i.reg1!!, value, i.type!!) + nextPc() + } + private fun InsSEQ(i: IRInstruction) { val (left: Int, right: Int) = getSetOnConditionOperands(i) val value = if(left==right) 1 else 0