diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 51c0f7d9c..e89115647 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -1001,7 +1001,30 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { internal fun operatorAndInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result { if(array!=null) { - TODO("&") + val result = mutableListOf() + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + val eltSize = codeGen.program.memsizer.memorySize(array.type) + if(constIndex!=null && constValue!=null) { + if(array.splitWords) { + val valueRegLsb = codeGen.registers.nextFree() + val valueRegMsb = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) + it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegLsb, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) + } + } else { + val valueReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) + it += IRInstruction(Opcode.ANDM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) + } + } + return Ok(result) + } + return Err(NotImplementedError("inplace word array &")) // TODO? } if(constAddress==null && memory!=null) return Err(NotImplementedError("optimized memory in-place &")) // TODO @@ -1055,7 +1078,30 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { internal fun operatorOrInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result { if(array!=null) { - TODO("|") + val result = mutableListOf() + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + val eltSize = codeGen.program.memsizer.memorySize(array.type) + if(constIndex!=null && constValue!=null) { + if(array.splitWords) { + val valueRegLsb = codeGen.registers.nextFree() + val valueRegMsb = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) + it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegLsb, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + it += IRInstruction(Opcode.ORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) + } + } else { + val valueReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) + it += IRInstruction(Opcode.ORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) + } + } + return Ok(result) + } + return Err(NotImplementedError("inplace word array |")) // TODO? } if(constAddress==null && memory!=null) return Err(NotImplementedError("optimized memory in-place |")) // TODO @@ -1203,7 +1249,29 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { internal fun operatorMinusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result { if(array!=null) { - TODO("-") + val eltSize = codeGen.program.memsizer.memorySize(array.type) + val result = mutableListOf() + if(array.splitWords) + return operatorMinusInplaceSplitArray(array, operand) + if(array.usesPointerVariable) { + TODO("inplace - for pointer variable") + } + val vmDt = irType(array.type) + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + if(constIndex!=null && constValue!=null) { + if(constValue==1) { + addInstr(result, IRInstruction(Opcode.DECM, vmDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) + } else { + val valueReg=codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate = constValue) + it += IRInstruction(Opcode.SUBM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) + } + } + return Ok(result) + } + return Err(NotImplementedError("inplace array -")) // TODO? } if(constAddress==null && memory!=null) return Err(NotImplementedError("optimized memory in-place -")) // TODO @@ -1247,9 +1315,55 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { return Ok(result) } + private fun operatorMinusInplaceSplitArray(array: PtArrayIndexer, operand: PtExpression): Result { + val result = mutableListOf() + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + if(constIndex!=null) { + val skip = codeGen.createLabelName() + if(constValue==1) { + val lsbReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lsbReg, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + it += IRInstruction(Opcode.BSTNE, labelSymbol = skip) + it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) + } + result += IRCodeChunk(skip, null).also { + it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + } + return Ok(result) + } else { + return Err(NotImplementedError("inplace split word array +")) // TODO? + } + } + return Err(NotImplementedError("inplace split word array +")) // TODO? + } + internal fun operatorPlusInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result { if(array!=null) { - TODO("+") + val result = mutableListOf() + if(array.splitWords) + return operatorPlusInplaceSplitArray(array, operand) + if(array.usesPointerVariable) { + TODO("inplace + for pointer variable") + } + val eltSize = codeGen.program.memsizer.memorySize(array.type) + val elementDt = irType(array.type) + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + if(constIndex!=null && constValue!=null) { + if(constValue==1) { + addInstr(result, IRInstruction(Opcode.INCM, elementDt, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize), null) + } else { + val valueReg=codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, elementDt, reg1=valueReg, immediate = constValue) + it += IRInstruction(Opcode.ADDM, elementDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) + } + } + return Ok(result) + } + return Err(NotImplementedError("inplace array +")) // TODO? } if(constAddress==null && memory!=null) return Err(NotImplementedError("optimized memory in-place +")) // TODO @@ -1293,6 +1407,27 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { return Ok(result) } + private fun operatorPlusInplaceSplitArray(array: PtArrayIndexer, operand: PtExpression): Result { + val result = mutableListOf() + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + if(constIndex!=null) { + val skip = codeGen.createLabelName() + if(constValue==1) { + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + it += IRInstruction(Opcode.BSTNE, labelSymbol = skip) + it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) + } + result += IRCodeChunk(skip, null) + return Ok(result) + } else { + return Err(NotImplementedError("inplace split word array +")) // TODO? + } + } + return Err(NotImplementedError("inplace split word array +")) // TODO? + } + internal fun operatorShiftRightInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): Result { if(array!=null) { TODO(">>") @@ -1349,7 +1484,30 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { internal fun operatorXorInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): Result { if(array!=null) { - TODO("xor") + val result = mutableListOf() + val constIndex = array.index.asConstInteger() + val constValue = operand.asConstInteger() + val eltSize = codeGen.program.memsizer.memorySize(array.type) + if(constIndex!=null && constValue!=null) { + if(array.splitWords) { + val valueRegLsb = codeGen.registers.nextFree() + val valueRegMsb = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegLsb, immediate=constValue and 255) + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegMsb, immediate=constValue shr 8) + it += IRInstruction(Opcode.XORM, vmDt, reg1=valueRegLsb, labelSymbol = array.variable.name+"_lsb", symbolOffset = constIndex) + it += IRInstruction(Opcode.XORM, vmDt, reg1=valueRegMsb, labelSymbol = array.variable.name+"_msb", symbolOffset = constIndex) + } + } else { + val valueReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, vmDt, reg1=valueReg, immediate=constValue) + it += IRInstruction(Opcode.XORM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize) + } + } + return Ok(result) + } + return Err(NotImplementedError("inplace word array ^")) // TODO? } if(constAddress==null && memory!=null) return Err(NotImplementedError("optimized memory in-place xor")) // TODO diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 49fb7ccb5..e743852a8 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,6 @@ TODO ==== -IR ExpressionGen: implement all in-place operators TODOs. Starting with operatorPlusInplace - - maze: if cell & UP!=0 and @(celladdr(cx,cy-1)) & (WALKED|BACKTRACKED) ==0 ^^ adding this !=0 caused a weird beq + / lda #1 / + to appear in front of the shortcircuit beq... @@ -88,6 +85,7 @@ What if we were to re-introduce Structs in prog8? Some thoughts: Other language/syntax features to think about --------------------------------------------- +- remove ++/-- (just use Pythonesque x+=1) OR make ++/-- into a postfix expression (but then we need a prefix variant of them too?) maybe via a new builtin function like postincr__w() etc? - support for assigning multiple return values from romsub/asmsub to multiple variables. - add (rom/ram)bank support to romsub. A call will then automatically switch banks, use callfar and something else when in banked ram. challenges: how to not make this too X16 specific? How does the compiler know what bank to switch (ram/rom)? diff --git a/examples/test.p8 b/examples/test.p8 index 51f9fea3e..91c34c530 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -37,10 +37,22 @@ main { ubyte @shared xx ubyte[3] ubarr + uword[3] @split uwarr byte[3] sbarr bool[3] barr float[3] flarr bool @shared bb + uword ptr = &ubarr + + ptr[1]++ + ptr[1]++ + ptr[1]-- + txt.print_ub(ubarr[1]) + txt.nl() + ptr[1]+=4 + ptr[1]-=3 + txt.print_ub(ubarr[1]) + txt.nl() ; sbarr[1] = sbarr[1] == 0 ; sbarr[1] = sbarr[1] != 0 @@ -58,19 +70,19 @@ main { ; sbarr[xx] = sbarr[xx] > 0 ; sbarr[xx] = sbarr[xx] >= 0 - sbarr[1] = sbarr[1] == 2 - sbarr[1] = sbarr[1] != 2 - sbarr[1] = sbarr[1] < 2 - sbarr[1] = sbarr[1] <= 2 - sbarr[1] = sbarr[1] > 2 - sbarr[1] = sbarr[1] >= 2 - xx = 1 - sbarr[xx] = sbarr[xx] == 2 - sbarr[xx] = sbarr[xx] != 2 - sbarr[xx] = sbarr[xx] < 2 - sbarr[xx] = sbarr[xx] <= 2 - sbarr[xx] = sbarr[xx] > 2 - sbarr[xx] = sbarr[xx] >= 2 +; sbarr[1] = sbarr[1] == 2 +; sbarr[1] = sbarr[1] != 2 +; sbarr[1] = sbarr[1] < 2 +; sbarr[1] = sbarr[1] <= 2 +; sbarr[1] = sbarr[1] > 2 +; sbarr[1] = sbarr[1] >= 2 +; xx = 1 +; sbarr[xx] = sbarr[xx] == 2 +; sbarr[xx] = sbarr[xx] != 2 +; sbarr[xx] = sbarr[xx] < 2 +; sbarr[xx] = sbarr[xx] <= 2 +; sbarr[xx] = sbarr[xx] > 2 +; sbarr[xx] = sbarr[xx] >= 2 ; ubarr[1] = ubarr[1] == 2 ; ubarr[1] = ubarr[1] < 2