From e2882d37bfe9c7ad4573399d1806434c33407d41 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 27 Dec 2024 18:22:15 +0100 Subject: [PATCH] ir: remove a bunch of strange in-place assignment operators, and problematic opcodes --- .../codegen/intermediate/AssignmentGen.kt | 295 ------------------ .../codegen/intermediate/ExpressionGen.kt | 47 ++- docs/source/todo.rst | 1 + examples/test.p8 | 75 +++-- .../src/prog8/intermediate/IRInstructions.kt | 20 -- virtualmachine/src/prog8/vm/VirtualMachine.kt | 41 --- 6 files changed, 87 insertions(+), 392 deletions(-) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 0acd44d60..e9311a798 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -98,12 +98,6 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express "<<=" -> operatorShiftLeftInplace(symbol, array, constAddress, memTarget, targetDt, value) ">>=" -> operatorShiftRightInplace(symbol, array, constAddress, memTarget, targetDt, value, signed) "%=" -> operatorModuloInplace(symbol, array, constAddress, memTarget, targetDt, value) - "==" -> operatorEqualsInplace(symbol, array, constAddress, memTarget, targetDt, value) - "!=" -> operatorNotEqualsInplace(symbol, array, constAddress, memTarget, targetDt, value) - "<" -> operatorLessInplace(symbol, array, constAddress, memTarget, targetDt, value, signed) - ">" -> operatorGreaterInplace(symbol, array, constAddress, memTarget, targetDt, value, signed) - "<=" -> operatorLessEqualInplace(symbol, array, constAddress, memTarget, targetDt, value, signed) - ">=" -> operatorGreaterEqualInplace(symbol, array, constAddress, memTarget, targetDt, value, signed) in PrefixOperators -> inplacePrefix(augAssign.operator, symbol, array, constAddress, memTarget, targetDt) else -> throw AssemblyError("invalid augmented assign operator ${augAssign.operator}") @@ -1140,293 +1134,4 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } return result } - - private fun operatorEqualsInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, "==") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, Opcode.SEQ) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, Opcode.SEQ) - } - return chunks - } - - private fun operatorNotEqualsInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, "!=") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, Opcode.SNE) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, Opcode.SNE) - } - return chunks - } - - private fun operatorGreaterInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, ">") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val opcode = if(signed) Opcode.SGTS else Opcode.SGT - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, opcode) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, opcode) - } - return chunks - } - - private fun operatorLessInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, "<") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val opcode = if(signed) Opcode.SLTS else Opcode.SLT - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, opcode) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, opcode) - } - return chunks - } - - private fun operatorGreaterEqualInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, ">=") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val opcode = if(signed) Opcode.SGES else Opcode.SGE - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, opcode) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, opcode) - } - return chunks - } - - private fun operatorLessEqualInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? { - if(array!=null) - return createInplaceArrayComparison(array, operand, "<=") - if(constAddress==null && memory!=null) - return null // TODO("optimized memory in-place compare"") - - val opcode = if(signed) Opcode.SLES else Opcode.SLE - val chunks = if(vmDt==IRDataType.FLOAT) { - createInplaceFloatComparison(constAddress, symbol, operand, opcode) - } else { - createInplaceComparison(constAddress, symbol, vmDt, operand, opcode) - } - return chunks - } - - private fun createInplaceComparison( - constAddress: Int?, - symbol: String?, - vmDt: IRDataType, - operand: PtExpression, - compareAndSetOpcode: Opcode - ): MutableList { - val result = mutableListOf() - val valueReg = codeGen.registers.nextFree() - val cmpResultReg = codeGen.registers.nextFree() - if(operand is PtNumber || operand is PtBool) { - - if(operand is PtNumber && operand.number==0.0 && compareAndSetOpcode in arrayOf(Opcode.SEQ, Opcode.SNE)) { - // ==0 or !=0 optimized case - val compareAndSetOpcodeZero = if(compareAndSetOpcode==Opcode.SEQ) Opcode.SZ else Opcode.SNZ - if (constAddress != null) { - // in-place modify a memory location - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress) - it += IRInstruction(compareAndSetOpcodeZero, vmDt, reg1 = cmpResultReg, reg2 = valueReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress) - } - } else { - // in-place modify a symbol (variable) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol) - it += IRInstruction(compareAndSetOpcodeZero, vmDt, reg1=cmpResultReg, reg2 = valueReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol) - } - } - return result - } - - // compare against number that is not 0 - val numberReg = codeGen.registers.nextFree() - val value = if(operand is PtNumber) operand.number.toInt() else if(operand is PtBool) operand.asInt() else throw AssemblyError("wrong operand type") - if (constAddress != null) { - // in-place modify a memory location - val innervalue = if(operand is PtNumber) operand.number.toInt() else if(operand is PtBool) operand.asInt() else throw AssemblyError("wrong operand type") - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress) - it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, immediate = innervalue) - it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = cmpResultReg, reg2 = valueReg, reg3 = numberReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress) - } - } else { - // in-place modify a symbol (variable) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol) - it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, immediate = value) - it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = numberReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol) - } - } - } else { - val tr = expressionEval.translateExpression(operand) - addToResult(result, tr, tr.resultReg, -1) - if (constAddress != null) { - // in-place modify a memory location - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress) - it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress) - } - } else { - // in-place modify a symbol (variable) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol) - it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg) - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol) - } - } - } - return result - } - - private fun createInplaceFloatComparison( - constAddress: Int?, - symbol: String?, - operand: PtExpression, - compareAndSetOpcode: Opcode - ): MutableList { - val result = mutableListOf() - val valueReg = codeGen.registers.nextFreeFloat() - val cmpReg = codeGen.registers.nextFree() - val zeroReg = codeGen.registers.nextFree() - if(operand is PtNumber) { - val numberReg = codeGen.registers.nextFreeFloat() - val cmpResultReg = codeGen.registers.nextFree() - if (constAddress != null) { - // in-place modify a memory location - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress) - it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number) - it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0) - it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg) - it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg) - it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress) - } - } else { - // in-place modify a symbol (variable) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol) - it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number) - it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0) - it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg) - it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg) - it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol) - } - } - } else { - val tr = expressionEval.translateExpression(operand) - val cmpResultReg = codeGen.registers.nextFree() - addToResult(result, tr, -1, tr.resultFpReg) - if (constAddress != null) { - // in-place modify a memory location - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress) - it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0) - it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg) - it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg) - it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress) - } - } else { - // in-place modify a symbol (variable) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol) - it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0) - it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg) - it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg) - it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol) - } - } - } - return result - } - - private fun createInplaceArrayComparison(array: PtArrayIndexer, value: PtExpression, comparisonOperator: String): IRCodeChunks? { - if(array.type.isFloat) - return null // TODO("optimized in-place compare on float arrays")) - - val eltSize = codeGen.program.memsizer.memorySize(array.type, null) - val result = mutableListOf() - if(array.splitWords) - TODO("inplace compare for split word array") - val vmDt = irType(array.type) - val constIndex = array.index.asConstInteger() - val constValue = value.asConstInteger() - val cmpResultReg = codeGen.registers.nextFree() - if(constIndex!=null) { - if(constValue==0) { - // comparison against zero. - val valueReg = codeGen.registers.nextFree() - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) - it += when(comparisonOperator) { - "==" -> IRInstruction(Opcode.SZ, vmDt, reg1=cmpResultReg, reg2=valueReg) - "!=" -> IRInstruction(Opcode.SNZ, vmDt, reg1=cmpResultReg, reg2=valueReg) - "<" -> return null // TODO("array <0 inplace")) - "<=" -> return null // TODO("array <=0 inplace")) - ">" -> return null // TODO("array >0 inplace")) - ">=" -> return null // TODO("array >=0 inplace")) - else -> throw AssemblyError("invalid operator") - } - it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) - } - return result - } else { - return null // TODO("compare against non-zero value")) - } - } else { - if(constValue==0) { - // comparison against zero. - val valueReg = codeGen.registers.nextFree() - val indexTr = expressionEval.translateExpression(array.index) - addToResult(result, indexTr, indexTr.resultReg, -1) - result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOADX, vmDt, reg1=valueReg, reg2=indexTr.resultReg, labelSymbol = array.variable.name) - it += when(comparisonOperator) { - "==" -> IRInstruction(Opcode.SZ, vmDt, reg1=cmpResultReg, reg2=valueReg) - "!=" -> IRInstruction(Opcode.SNZ, vmDt, reg1=cmpResultReg, reg2=valueReg) - "<" -> return null // TODO("array <0 inplace")) - "<=" -> return null // TODO("array <=0 inplace")) - ">" -> return null // TODO("array >0 inplace")) - ">=" -> return null // TODO("array >=0 inplace")) - else -> throw AssemblyError("invalid operator") - } - it += IRInstruction(Opcode.STOREX, vmDt, reg1=valueReg, reg2=indexTr.resultReg, labelSymbol = array.variable.name) - } - return result - } - else - return null // TODO("compare against non-zero value")) - } - } - } \ No newline at end of file diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index ae2f7e1bf..7ccdb250e 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -429,10 +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) } valueDt.isWord -> { +// loadStatusAsBooleanResult(Opcode.BSTNE, result) actualResultReg2 = codeGen.registers.nextFree() addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg), null) } @@ -720,7 +722,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { finalReturnRegister = codeGen.registers.nextFree() when(statusFlagResult) { Statusflag.Pc -> { - addInstr(result, IRInstruction(Opcode.SCS, returnRegSpec.dt, reg1=finalReturnRegister), null) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, returnRegSpec.dt, reg1 = finalReturnRegister, immediate = 0) + it += IRInstruction(Opcode.ROXL, returnRegSpec.dt, reg1 = finalReturnRegister) + } } else -> { val branchOpcode = when(statusFlagResult) { @@ -956,14 +961,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val valueReg = codeGen.registers.nextFree() val label = codeGen.createLabelName() result += IRCodeChunk(null, null).also { - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 1) + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg) it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=valueReg, immediate = 0) it += if (notEquals) - IRInstruction(Opcode.BSTNE, labelSymbol = label) - else IRInstruction(Opcode.BSTEQ, labelSymbol = label) - it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0) + else + IRInstruction(Opcode.BSTNE, labelSymbol = label) + it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=resultRegister) } result += IRCodeChunk(label, null) return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) @@ -971,27 +976,41 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { 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") } else { - return if(binExpr.right.asConstValue()==0.0) { - val tr = translateExpression(binExpr.left) - addToResult(result, tr, tr.resultReg, -1) - val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ - val resultReg = codeGen.registers.nextFree() - addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultReg, reg2 = tr.resultReg), null) + val rightConst = binExpr.right.asConstValue() + return if(rightConst!=null) { + val leftTr = translateExpression(binExpr.left) + addToResult(result, leftTr, leftTr.resultReg, -1) + addInstr(result, IRInstruction(Opcode.CMPI, leftTr.dt, reg1 = leftTr.resultReg, immediate = rightConst.toInt()), null) + val resultReg = loadStatusAsBooleanResult(if(notEquals) Opcode.BSTNE else Opcode.BSTEQ, result) ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) } else { val leftTr = translateExpression(binExpr.left) addToResult(result, leftTr, leftTr.resultReg, -1) val rightTr = translateExpression(binExpr.right) addToResult(result, rightTr, rightTr.resultReg, -1) - val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ - val resultReg = codeGen.registers.nextFree() - addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultReg, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null) + addInstr(result, IRInstruction(Opcode.CMP, leftTr.dt, reg1=leftTr.resultReg, reg2=rightTr.resultReg), null) + val resultReg = loadStatusAsBooleanResult(if(notEquals) Opcode.BSTNE else Opcode.BSTEQ, result) ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) } } } } + private fun loadStatusAsBooleanResult(branchForTrue: Opcode, 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, 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/docs/source/todo.rst b/docs/source/todo.rst index a39b716fa..d78b1f5a6 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -54,6 +54,7 @@ Future Things and Ideas IR/VM ----- +- add BZ and BNZ instructions? To replace CMPI #0 + Branch? - getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!) - addUsedRegistersCounts() doesn't always determine the datatype correctly. --> GET RID OF THE Sxxx OPCODES FOR NOW? - fix TODO("IR rol/ror on split words array") diff --git a/examples/test.p8 b/examples/test.p8 index 6400a0c65..4ce4d4626 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,32 +1,63 @@ %import textio +%import floats %zeropage basicsafe %option no_sysinit main { sub start() { - cx16.r2 = $eeee - txt.print_uwhex(cx16.r2, true) - txt.nl() - cx16.r2,void = thing2() ; TODO fix IR+6502 codegen missing an ext.b (it is present when thing only returns single returnvalue) - txt.print_uwhex(cx16.r2, true) - txt.nl() - cx16.r2 = thing() ; codegen does ext.b correctly here - txt.print_uwhex(cx16.r2, true) - txt.nl() - } + bool derp - asmsub thing() -> ubyte @A { - %asm {{ - lda #$44 - rts - }} - } + float @shared f1,f2 + txt.nl() - asmsub thing2() -> ubyte @A, bool @Pc { - %asm {{ - lda #$aa - clc - rts - }} + + derp = cx16.r0L as bool + cx16.r0++ + derp = cx16.r0 as bool + + cx16.r0L=0 + derp=true + if cx16.r0L==0 and derp + txt.print("fl is 0\n") + else + txt.print("fl is not 0\n") + if cx16.r0L!=0 and derp + txt.print("fl is not 0\n") + else + txt.print("fl is 0\n") + + cx16.r0L = 1 + if cx16.r0L==0 and derp + txt.print("fl is 0\n") + else + txt.print("fl is not 0\n") + if cx16.r0L!=0 and derp + txt.print("fl is not 0\n") + else + txt.print("fl is 0\n") + + + + cx16.r0L=99 + derp=true + if cx16.r0L==99 and derp + txt.print("fl is 99\n") + else + txt.print("fl is not 99\n") + if cx16.r0L!=99 and derp + txt.print("fl is not 99\n") + else + txt.print("fl is 99\n") + + cx16.r0L = 122 + if cx16.r0L==99 and derp + txt.print("fl is 99\n") + else + txt.print("fl is not 99\n") + if cx16.r0L!=99 and derp + txt.print("fl is not 99\n") + else + txt.print("fl is 99\n") } } + diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 1cee91ded..6783d3444 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -123,12 +123,7 @@ 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 -scc reg1 - set reg1=1 if Carry flag is clear, else 0 -scs reg1 - set reg1=1 if Carry flag is set, else 0 -sz reg1, reg2 - set reg1=1 if reg2==0, else 0 snz reg1, reg2 - set reg1=1 if reg2!=0, else 0 -seq reg1, reg2, reg3 - set reg1=1 if reg2 == reg3, else 0 -sne reg1, reg2, reg3 - set reg1=1 if reg2 != reg3, 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 @@ -323,12 +318,7 @@ enum class Opcode { BGESR, BGES, BLES, - SCC, - SCS, - SZ, SNZ, - SEQ, - SNE, SLT, SLTS, SGT, @@ -526,12 +516,7 @@ val OpcodesThatDependOnCarry = arrayOf( ) val OpcodesThatSetRegFromStatusbits = arrayOf( - Opcode.SCC, - Opcode.SCS, - Opcode.SZ, Opcode.SNZ, - Opcode.SEQ, - Opcode.SNE, Opcode.SLT, Opcode.SLTS, Opcode.SGT, @@ -692,12 +677,7 @@ val instructionFormats = mutableMapOf( Opcode.BGESR to InstructionFormat.from("BW,r1"), - Opcode.SCS to InstructionFormat.from("BW,>r1"), - Opcode.SZ to InstructionFormat.from("BW,>r1,r1,r1,r1,r1,r1,r1, InsBLE(ins) Opcode.BGES -> InsBGES(ins) Opcode.BLES -> InsBLES(ins) - Opcode.SCC -> InsSCC(ins) - Opcode.SCS -> InsSCS(ins) - Opcode.SZ -> InsSZ(ins) Opcode.SNZ -> InsSNZ(ins) - Opcode.SEQ -> InsSEQ(ins) - Opcode.SNE -> InsSNE(ins) Opcode.SLT -> InsSLT(ins) Opcode.SLTS -> InsSLTS(ins) Opcode.SGT -> InsSGT(ins) @@ -895,28 +890,6 @@ class VirtualMachine(irProgram: IRProgram) { nextPc() } - private fun InsSCC(i: IRInstruction) { - setResultReg(i.reg1!!, if(statusCarry) 0 else 1, i.type!!) - nextPc() - } - - private fun InsSCS(i: IRInstruction) { - setResultReg(i.reg1!!, if(statusCarry) 1 else 0, i.type!!) - nextPc() - } - - private fun InsSZ(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 InsSNZ(i: IRInstruction) { val right = when(i.type) { IRDataType.BYTE -> registers.getSB(i.reg2!!).toInt() @@ -929,20 +902,6 @@ class VirtualMachine(irProgram: IRProgram) { nextPc() } - private fun InsSEQ(i: IRInstruction) { - val (left: Int, right: Int) = getSetOnConditionOperands(i) - val value = if(left==right) 1 else 0 - setResultReg(i.reg1!!, value, i.type!!) - nextPc() - } - - private fun InsSNE(i: IRInstruction) { - val (left: Int, right: Int) = getSetOnConditionOperands(i) - val value = if(left!=right) 1 else 0 - setResultReg(i.reg1!!, value, i.type!!) - nextPc() - } - private fun InsSLT(i: IRInstruction) { val (left, right) = getSetOnConditionOperandsU(i) val value = if(left