diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 7ccdb250e..0ea32d43e 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -429,14 +429,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { BaseDataType.BOOL -> { when { valueDt.isByte -> { -// loadStatusAsBooleanResult(Opcode.BSTNE, result) - actualResultReg2 = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg), null) + addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=tr.resultReg, immediate = 0), null) + actualResultReg2 = loadStatusAsBooleanResult(Opcode.BSTNE, result) } valueDt.isWord -> { -// loadStatusAsBooleanResult(Opcode.BSTNE, result) - actualResultReg2 = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg), null) + addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.WORD, reg1=tr.resultReg, immediate = 0), null) + actualResultReg2 =loadStatusAsBooleanResult(Opcode.BSTNE, result) } valueDt.isFloat -> { actualResultReg2 = codeGen.registers.nextFree() @@ -914,7 +912,6 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { lessEquals: Boolean ): ExpressionCodeResult { val result = mutableListOf() - val cmpResultRegister = codeGen.registers.nextFree() if(vmDt==IRDataType.FLOAT) { val leftTr = translateExpression(binExpr.left) addToResult(result, leftTr, -1, leftTr.resultFpReg) @@ -922,15 +919,29 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, rightTr, -1, rightTr.resultFpReg) val resultRegister = codeGen.registers.nextFree() addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) - val zeroRegister = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, immediate = 0), null) - val ins = if (signed) { - if (lessEquals) Opcode.SLES else Opcode.SLTS + addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultRegister, immediate = 0), null) + val other = codeGen.createLabelName() + val after = codeGen.createLabelName() + val resultReg = codeGen.registers.nextFree() + // TODO can this be done more efficiently? + if(lessEquals) { + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.BSTNEG, labelSymbol = other) + it += IRInstruction(Opcode.BSTEQ, labelSymbol = other) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0) + it += IRInstruction(Opcode.JUMP, labelSymbol = after) + } + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultReg, immediate = 1), other) } else { - if (lessEquals) Opcode.SLE else Opcode.SLT + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.BSTNEG, labelSymbol = other) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0) + it += IRInstruction(Opcode.JUMP, labelSymbol = after) + } + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultReg, immediate = 1), other) } - addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1=cmpResultRegister, reg2 = resultRegister, reg3 = zeroRegister), null) - return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultRegister, -1) + result += IRCodeChunk(after, null) + return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) } else { if(binExpr.left.type.isString || binExpr.right.type.isString) { throw AssemblyError("str compares should have been replaced with builtin function call to do the compare") @@ -939,13 +950,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { addToResult(result, leftTr, leftTr.resultReg, -1) val rightTr = translateExpression(binExpr.right) addToResult(result, rightTr, rightTr.resultReg, -1) - val ins = if (signed) { - if (lessEquals) Opcode.SLES else Opcode.SLTS + val branch = if (signed) { + if (lessEquals) Opcode.BGESR else Opcode.BGTSR } else { - if (lessEquals) Opcode.SLE else Opcode.SLT + if (lessEquals) Opcode.BGER else Opcode.BGTR } - addInstr(result, IRInstruction(ins, vmDt, reg1=cmpResultRegister, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null) - return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultRegister, -1) + val resultReg = compareRegisterAsBooleanResult(branch, leftTr.dt, rightTr.resultReg, leftTr.resultReg, result) + return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) } } } @@ -968,7 +979,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { IRInstruction(Opcode.BSTEQ, labelSymbol = label) else IRInstruction(Opcode.BSTNE, labelSymbol = label) - it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=resultRegister) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 1) } result += IRCodeChunk(label, null) return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) @@ -1011,6 +1022,21 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { return resultReg } + private fun compareRegisterAsBooleanResult(branchForTrue: Opcode, dt: IRDataType, reg1: Int, reg2: Int, result: MutableList): Int { + // TODO this used to be a single instruction like SCC, SCS, SZ etc but those were problematic + val other = codeGen.createLabelName() + val after = codeGen.createLabelName() + val resultReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(branchForTrue, dt, reg1=reg1, reg2=reg2, labelSymbol = other) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0) + it += IRInstruction(Opcode.JUMP, labelSymbol = after) + } + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultReg, immediate = 1), other) + result += IRCodeChunk(after, null) + return resultReg + } + private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult { val result = mutableListOf() return if(codeGen.isOne(binExpr.right)) { diff --git a/examples/test.p8 b/examples/test.p8 index 4ce4d4626..f4d5ac78f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -10,10 +10,22 @@ main { float @shared f1,f2 txt.nl() - - derp = cx16.r0L as bool - cx16.r0++ - derp = cx16.r0 as bool + cx16.r0 = $aaaa + cx16.r1 = $2222 + f1 = 9999 + cx16.r0=9999 + txt.print_bool(f1 < 8000) + txt.spc() + txt.print_bool(f1 < 10000) + txt.spc() + txt.print_bool(f1 < 20000) + txt.nl() + txt.print_bool(cx16.r0 < 8000) + txt.spc() + txt.print_bool(cx16.r0 < 10000) + txt.spc() + txt.print_bool(cx16.r0 < 20000) + txt.nl() cx16.r0L=0 derp=true diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 6783d3444..8e7b5fbe7 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -123,11 +123,6 @@ bles reg1, value, address - jump to location in program given by l bgesr reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed) 'blesr' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) ==> use bgesr with swapped operands -snz reg1, reg2 - set reg1=1 if reg2!=0, else 0 -slt reg1, reg2, reg3 - set reg1=1 if reg2 < reg3 (unsigned), else 0 -slts reg1, reg2, reg3 - set reg1=1 if reg2 < reg3 (signed), else 0 -sle reg1, reg2, reg3 - set reg1=1 if reg2 <= reg3 (unsigned), else 0 -sles reg1, reg2, reg3 - set reg1=1 if reg2 <= reg3 (signed), else 0 sgt reg1, reg2, reg3 - set reg1=1 if reg2 > reg3 (unsigned), else 0 sgts reg1, reg2, reg3 - set reg1=1 if reg2 > reg3 (signed), else 0 sge reg1, reg2, reg3 - set reg1=1 if reg2 >= reg3 (unsigned), else 0 @@ -318,13 +313,8 @@ enum class Opcode { BGESR, BGES, BLES, - SNZ, - SLT, - SLTS, SGT, SGTS, - SLE, - SLES, SGE, SGES, @@ -516,13 +506,8 @@ val OpcodesThatDependOnCarry = arrayOf( ) val OpcodesThatSetRegFromStatusbits = arrayOf( - Opcode.SNZ, - Opcode.SLT, - Opcode.SLTS, Opcode.SGT, Opcode.SGTS, - Opcode.SLE, - Opcode.SLES, Opcode.SGE, Opcode.SGES ) @@ -677,13 +662,8 @@ val instructionFormats = mutableMapOf( Opcode.BGESR to InstructionFormat.from("BW,r1,r1,r1,r1,r1,r1,r1,r1,r1,r1 | F,<>fr1"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 12f30f306..9746dd397 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -236,13 +236,8 @@ class VirtualMachine(irProgram: IRProgram) { Opcode.BLE -> InsBLE(ins) Opcode.BGES -> InsBGES(ins) Opcode.BLES -> InsBLES(ins) - Opcode.SNZ -> InsSNZ(ins) - Opcode.SLT -> InsSLT(ins) - Opcode.SLTS -> InsSLTS(ins) Opcode.SGT -> InsSGT(ins) Opcode.SGTS -> InsSGTS(ins) - Opcode.SLE -> InsSLE(ins) - Opcode.SLES -> InsSLES(ins) Opcode.SGE -> InsSGE(ins) Opcode.SGES -> InsSGES(ins) Opcode.INC -> InsINC(ins) @@ -890,32 +885,6 @@ class VirtualMachine(irProgram: IRProgram) { nextPc() } - private fun InsSNZ(i: IRInstruction) { - val right = when(i.type) { - IRDataType.BYTE -> registers.getSB(i.reg2!!).toInt() - IRDataType.WORD -> registers.getSW(i.reg2!!).toInt() - IRDataType.FLOAT -> throw IllegalArgumentException("can't use float here") - null -> throw IllegalArgumentException("need type for branch instruction") - } - val value = if(right!=0) 1 else 0 - setResultReg(i.reg1!!, value, i.type!!) - nextPc() - } - - private fun InsSLT(i: IRInstruction) { - val (left, right) = getSetOnConditionOperandsU(i) - val value = if(leftright) 1 else 0 @@ -930,20 +899,6 @@ class VirtualMachine(irProgram: IRProgram) { nextPc() } - private fun InsSLE(i: IRInstruction) { - val (left, right) = getSetOnConditionOperandsU(i) - val value = if(left<=right) 1 else 0 - setResultReg(i.reg1!!, value, i.type!!) - nextPc() - } - - private fun InsSLES(i: IRInstruction) { - val (left, right) = getSetOnConditionOperands(i) - val value = if(left<=right) 1 else 0 - setResultReg(i.reg1!!, value, i.type!!) - nextPc() - } - private fun InsSGE(i: IRInstruction) { val (left, right) = getSetOnConditionOperandsU(i) val value = if(left>=right) 1 else 0