diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index f33726136..e8a1c7985 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -383,18 +383,47 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val tr = expressionEval.translateExpression(targetMemory.address) val addressReg = tr.resultReg addToResult(result, tr, tr.resultReg, -1) - result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, targetDt, reg1=addressReg) } + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.STOREZI, targetDt, reg1=addressReg) + } } } else { - if(targetMemory.address is PtNumber) { - val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, targetDt, reg1=valueRegister, address=(targetMemory.address as PtNumber).number.toInt()) } - result += chunk - } else { - val tr = expressionEval.translateExpression(targetMemory.address) - val addressReg = tr.resultReg - addToResult(result, tr, tr.resultReg, -1) - result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, targetDt, reg1=valueRegister, reg2=addressReg) } + val constAddress = targetMemory.address as? PtNumber + if(constAddress!=null) { + addInstr(result, IRInstruction(Opcode.STOREM, targetDt, reg1=valueRegister, address=constAddress.number.toInt()), null) + return result } + val ptrWithOffset = targetMemory.address as? PtBinaryExpression + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) { + if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) { + // STOREIX only works with byte index. + val ptrName = (ptrWithOffset.left as PtIdentifier).name + val offsetReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger()) + it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=valueRegister, reg2=offsetReg, labelSymbol = ptrName) + } + return result + } + } + val offsetTypecast = ptrWithOffset?.right as? PtTypeCast + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier + && (ptrWithOffset.right.type in ByteDatatypes || offsetTypecast?.value?.type in ByteDatatypes)) { + // STOREIX only works with byte index. + val tr = if(offsetTypecast?.value?.type in ByteDatatypes) + expressionEval.translateExpression(offsetTypecast!!.value) + else + expressionEval.translateExpression(ptrWithOffset.right) + addToResult(result, tr, tr.resultReg, -1) + val ptrName = (ptrWithOffset.left as PtIdentifier).name + addInstr(result, IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=valueRegister, reg2=tr.resultReg, labelSymbol = ptrName), null) + return result + } + val tr = expressionEval.translateExpression(targetMemory.address) + val addressReg = tr.resultReg + addToResult(result, tr, tr.resultReg, -1) + addInstr(result, IRInstruction(Opcode.STOREI, targetDt, reg1=valueRegister, reg2=addressReg), null) + return result } return result diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index c4678b476..bc33a676b 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -93,21 +93,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } ExpressionCodeResult(result, vmDt, resultRegister, -1) } - is PtMemoryByte -> { - val result = mutableListOf() - if(expr.address is PtNumber) { - val address = (expr.address as PtNumber).number.toInt() - val resultRegister = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, address = address), null) - ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) - } else { - val tr = translateExpression(expr.address) - addToResult(result, tr, tr.resultReg, -1) - val resultReg = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1=resultReg, reg2=tr.resultReg), null) - ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) - } - } + is PtMemoryByte -> translate(expr) is PtTypeCast -> translate(expr) is PtPrefix -> translate(expr) is PtArrayIndexer -> translate(expr) @@ -122,6 +108,49 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } } + private fun translate(mem: PtMemoryByte): ExpressionCodeResult { + val result = mutableListOf() + val resultRegister = codeGen.registers.nextFree() + + val constAddress = mem.address as? PtNumber + if(constAddress!=null) { + addInstr(result, IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, address = constAddress.number.toInt()), null) + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) + } + + val ptrWithOffset = mem.address as? PtBinaryExpression + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) { + if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) { + // LOADIX only works with byte index. + val ptrName = (ptrWithOffset.left as PtIdentifier).name + val offsetReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger()) + it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=resultRegister, reg2=offsetReg, labelSymbol = ptrName) + } + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) + } + } + val offsetTypecast = ptrWithOffset?.right as? PtTypeCast + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier + && (ptrWithOffset.right.type in ByteDatatypes || offsetTypecast?.value?.type in ByteDatatypes)) { + // LOADIX only works with byte index. + val tr = if(offsetTypecast?.value?.type in ByteDatatypes) + translateExpression(offsetTypecast!!.value) + else + translateExpression(ptrWithOffset.right) + addToResult(result, tr, tr.resultReg, -1) + val ptrName = (ptrWithOffset.left as PtIdentifier).name + addInstr(result, IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=resultRegister, reg2=tr.resultReg, labelSymbol = ptrName), null) + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) + } + + val tr = translateExpression(mem.address) + addToResult(result, tr, tr.resultReg, -1) + addInstr(result, IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1=resultRegister, reg2=tr.resultReg), null) + return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) + } + private fun translate(check: PtContainmentCheck): ExpressionCodeResult { val result = mutableListOf() when(check.iterable.type) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 26989bc40..484fac069 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1516,19 +1516,54 @@ class IRCodeGen( if(ident!=null) { addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null) } else if(memory!=null) { - if(memory.address is PtNumber) { - val address = (memory.address as PtNumber).number.toInt() - addInstr(result, IRInstruction(operationMem, irDt, address = address), null) - } else { - val tr = expressionEval.translateExpression(memory.address) - addToResult(result, tr, tr.resultReg, -1) - result += IRCodeChunk(null, null).also { + val constAddress = memory.address as? PtNumber + if(constAddress!=null) { + addInstr(result, IRInstruction(operationMem, irDt, address = constAddress.number.toInt()), null) + return result + } + val ptrWithOffset = memory.address as? PtBinaryExpression + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) { + if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) { + // LOADIX only works with byte index. + val ptrName = (ptrWithOffset.left as PtIdentifier).name + val offsetReg = registers.nextFree() val incReg = registers.nextFree() - it += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = tr.resultReg) - it += IRInstruction(operationRegister, irDt, reg1 = incReg) - it += IRInstruction(Opcode.STOREI, irDt, reg1 = incReg, reg2 = tr.resultReg) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger()) + it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=incReg, reg2=offsetReg, labelSymbol = ptrName) + it += IRInstruction(operationRegister, irDt, reg1 = incReg) + it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=incReg, reg2=offsetReg, labelSymbol = ptrName) + } + return result } } + val offsetTypecast = ptrWithOffset?.right as? PtTypeCast + if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier + && (ptrWithOffset.right.type in ByteDatatypes || offsetTypecast?.value?.type in ByteDatatypes)) { + // LOADIX only works with byte index. + val tr = if(offsetTypecast?.value?.type in ByteDatatypes) + expressionEval.translateExpression(offsetTypecast!!.value) + else + expressionEval.translateExpression(ptrWithOffset.right) + addToResult(result, tr, tr.resultReg, -1) + val ptrName = (ptrWithOffset.left as PtIdentifier).name + result += IRCodeChunk(null, null).also { + val incReg = registers.nextFree() + it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=incReg, reg2=tr.resultReg, labelSymbol = ptrName) + it += IRInstruction(operationRegister, irDt, reg1 = incReg) + it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=incReg, reg2=tr.resultReg, labelSymbol = ptrName) + } + return result + } + val tr = expressionEval.translateExpression(memory.address) + addToResult(result, tr, tr.resultReg, -1) + result += IRCodeChunk(null, null).also { + val incReg = registers.nextFree() + it += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = tr.resultReg) + it += IRInstruction(operationRegister, irDt, reg1 = incReg) + it += IRInstruction(Opcode.STOREI, irDt, reg1 = incReg, reg2 = tr.resultReg) + } + return result } else if (array!=null) { val variable = array.variable.name val itemsize = program.memsizer.memorySize(array.type) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 81a34d384..61b777273 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,8 +1,6 @@ TODO ==== -VM textelite is now a lot larger due to the ptr[i] -> @(ptr+i) rewrite. Fix this. - (after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type. ... diff --git a/examples/test.p8 b/examples/test.p8 index 437c7da47..903b0fd2f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -11,9 +11,16 @@ main { uword @shared az = $4000 ubyte @shared value = 22 - cx16.r0H = value*4 + az[value] - cx16.r0L = az[value] + value*4 - + az[20] = 99 + az[2000] = 99 + az[value] = 99 + az[cx16.r0] = 99 +; cx16.r0L = az[200] +; cx16.r1L = az[2000] +; cx16.r0L = az[value] +; cx16.r0H = value*4 + az[value] +; cx16.r0L = az[value] + value*4 +; ; @($4004) = 99 ; az[4]-- ; @(az + offset)-- @@ -26,15 +33,6 @@ main { ; cx16.r0L = az[4] + value*5 ; cx16.r1L = value*5 + az[4] -; ubyte @shared idx = 1 -; txt.print_w(array[idx]) -; txt.nl() -; txt.print_w(-array[idx]) -; txt.nl() -; array[idx] = -array[idx] -; txt.print_w(array[idx]) -; txt.nl() -; ; ubyte @shared xx ; ubyte[3] ubarr