IR: working on inplace +/-

This commit is contained in:
Irmen de Jong 2024-01-28 21:19:52 +01:00
parent 9553248ed6
commit e0055bc431
3 changed files with 189 additions and 21 deletions

View File

@ -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<IRCodeChunks, NotImplementedError> {
if(array!=null) {
TODO("&")
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
if(array!=null) {
TODO("|")
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
if(array!=null) {
TODO("-")
val eltSize = codeGen.program.memsizer.memorySize(array.type)
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
if(array!=null) {
TODO("+")
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
val result = mutableListOf<IRCodeChunkBase>()
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<IRCodeChunks, NotImplementedError> {
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<IRCodeChunks, NotImplementedError> {
if(array!=null) {
TODO("xor")
val result = mutableListOf<IRCodeChunkBase>()
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

View File

@ -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)?

View File

@ -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