mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
ir: add scaled indexing (S=) to LOADX/STOREX/STOREZX
Remove byte-offset pre-scaling from IR generation and encode element index + explicit scale in the IR. Effective address is base + index*scale + disp (disp = symbolOffset).
This commit is contained in:
1 parent
60eeaba791
commit
59c41ad129
12 files changed
+303
-248
No files matched your search
@@ -441,9 +441,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
fun loadIndex(): Int {
|
||||
val tr = exprGen.translateExpression(array.index)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val (indexReg, indexDt) = normalizeArrayIndex(result, tr)
|
||||
if(!array.splitWords && eltSize>1)
|
||||
result += codeGen.multiplyByConst(indexDt, indexReg, eltSize)
|
||||
val (indexReg, _) = normalizeArrayIndex(result, tr)
|
||||
return indexReg
|
||||
}
|
||||
|
||||
@@ -517,9 +515,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
val indexReg = loadIndex()
|
||||
val register = codeGen.registers.next(vmDt)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName)
|
||||
it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName, scale = eltSize)
|
||||
it += IRInstruction(Opcode.NEG, vmDt, reg1 = register)
|
||||
it += IRInstruction(Opcode.STOREX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName)
|
||||
it += IRInstruction(Opcode.STOREX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName, scale = eltSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -531,9 +529,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
val indexReg = loadIndex()
|
||||
val register = codeGen.registers.next(vmDt)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName)
|
||||
it += IRInstruction(Opcode.LOADX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName, scale = eltSize)
|
||||
it += IRInstruction(Opcode.INV, vmDt, reg1 = register)
|
||||
it += IRInstruction(Opcode.STOREX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName)
|
||||
it += IRInstruction(Opcode.STOREX, vmDt, reg1 = register, reg2 = indexReg, labelSymbol = arrayVariableName, scale = eltSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -786,6 +784,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
} else {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
|
||||
result += code
|
||||
if(eltSize!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1=pointerReg, reg2=indexReg), null)
|
||||
}
|
||||
codeGen.storeValueAtPointersLocation(result, pointerReg, 0u, targetIdent.type.dereference(), true, -1)
|
||||
@@ -796,6 +796,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
} else {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
|
||||
result += code
|
||||
if(eltSize!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1=pointerReg, reg2=indexReg), null)
|
||||
}
|
||||
val realValueReg = if(targetDt == IRDataType.FLOAT) valueFpRegister else valueRegister
|
||||
@@ -829,13 +831,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
} else {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, codeGen.wordArrayIndex, targetArray.splitWords)
|
||||
result += code
|
||||
val scaleZX = if(targetArray.splitWords) 1 else eltSize
|
||||
result += IRCodeChunk(null, null).also {
|
||||
if(targetArray.splitWords) {
|
||||
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_lsb")
|
||||
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_msb")
|
||||
}
|
||||
else
|
||||
it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable)
|
||||
it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable, scale = scaleZX)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -850,7 +853,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, codeGen.wordArrayIndex, targetArray.splitWords)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.STOREX, targetDt, reg1 = indexReg, fpReg1 = RegisterNum(valueFpRegister), labelSymbol = variable)
|
||||
it += IRInstruction(Opcode.STOREX, targetDt, reg1 = indexReg, fpReg1 = RegisterNum(valueFpRegister), labelSymbol = variable, scale = eltSize)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -879,7 +882,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = lsbmsbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
else
|
||||
it += IRInstruction(Opcode.STOREX, targetDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable)
|
||||
it += IRInstruction(Opcode.STOREX, targetDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable, scale = eltSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -918,6 +921,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val exprGen
|
||||
// index is an expression
|
||||
val (code, indexReg) = codeGen.loadIndexReg(targetArray.index, eltSize, true, targetArray.splitWords)
|
||||
result += code
|
||||
if(eltSize!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1 = pointerReg, reg2 = indexReg), null)
|
||||
if(zero) {
|
||||
addInstr(result, IRInstruction(Opcode.STOREZI, targetDt, reg1 = pointerReg, immediate = 0), null)
|
||||
|
||||
@@ -5,6 +5,7 @@ import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataType
|
||||
import prog8.intermediate.*
|
||||
|
||||
|
||||
@@ -872,6 +873,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
} else {
|
||||
val (code, indexWordReg) = codeGen.loadIndexReg(target.index, eltSize, true, false)
|
||||
result += code
|
||||
if(eltSize!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexWordReg, eltSize)
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1 = pointerTr.resultReg, reg2 = indexWordReg), null)
|
||||
if(elementByteOffset > 0)
|
||||
addInstr(result, IRInstruction(Opcode.ADD, IRDataType.POINTER, reg1 = pointerTr.resultReg, immediate = elementByteOffset), null)
|
||||
@@ -940,12 +943,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
} else {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(target.index, eltSize, codeGen.wordArrayIndex, false)
|
||||
result += code
|
||||
val indexDt = if(codeGen.wordArrayIndex) IRDataType.WORD else IRDataType.BYTE
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val offset = byteOffset(eltSize)
|
||||
if(offset > 0)
|
||||
it += IRInstruction(Opcode.ADD, indexDt, reg1 = indexReg, immediate = offset)
|
||||
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1=indexReg, labelSymbol = targetVariable.name)
|
||||
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1=indexReg, labelSymbol = targetVariable.name, symbolOffset = if(offset!=0) offset else null, scale = eltSize)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -961,12 +961,9 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
} else {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(target.index, eltSize, codeGen.wordArrayIndex, false)
|
||||
result += code
|
||||
val indexDt = if(codeGen.wordArrayIndex) IRDataType.WORD else IRDataType.BYTE
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val offset = byteOffset(eltSize)
|
||||
if(offset > 0)
|
||||
it += IRInstruction(Opcode.ADD, indexDt, reg1 = indexReg, immediate = offset)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexReg, labelSymbol = targetVariable.name)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexReg, labelSymbol = targetVariable.name, symbolOffset = if(offset!=0) offset else null, scale = eltSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,13 +647,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
fun indexByExpression() {
|
||||
val (code, indexReg) = codeGen.loadIndexReg(arrayIx.index, eltSize, codeGen.wordArrayIndex, arrayIx.splitWords)
|
||||
result += code
|
||||
val scale = if(arrayIx.splitWords) 1 else eltSize
|
||||
if(vmDt==IRDataType.FLOAT) {
|
||||
resultFpRegister = codeGen.registers.next(IRDataType.FLOAT)
|
||||
addInstr(result, IRInstruction(Opcode.LOADX, IRDataType.FLOAT, fpReg1 = RegisterNum(resultFpRegister), reg1=indexReg, labelSymbol = arrayVarSymbol), null)
|
||||
addInstr(result, IRInstruction(Opcode.LOADX, IRDataType.FLOAT, fpReg1 = RegisterNum(resultFpRegister), reg1=indexReg, labelSymbol = arrayVarSymbol, scale = scale), null)
|
||||
}
|
||||
else {
|
||||
resultRegister = codeGen.registers.next(vmDt)
|
||||
addInstr(result, IRInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=indexReg, labelSymbol = arrayVarSymbol), null)
|
||||
addInstr(result, IRInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=indexReg, labelSymbol = arrayVarSymbol, scale = scale), null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -682,6 +683,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
else {
|
||||
val (code, indexWordReg) = codeGen.loadIndexReg(index, eltSize, true, false)
|
||||
result += code
|
||||
if(eltSize!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexWordReg, eltSize)
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1=pointerReg, reg2=indexWordReg), null)
|
||||
}
|
||||
|
||||
@@ -1885,6 +1888,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
val (chunks, indexReg) = codeGen.loadIndexReg(left.index, struct.size.toInt(), true, false)
|
||||
result += chunks
|
||||
if(struct.size.toInt()!=1)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexReg, struct.size.toInt())
|
||||
addInstr(result, IRInstruction(Opcode.ADDR, IRDataType.POINTER, reg1 = pointerReg, reg2 = indexReg), null)
|
||||
}
|
||||
field = struct.getField(right.name, codeGen.program.memsizer)
|
||||
|
||||
@@ -774,19 +774,18 @@ class IRCodeGen(
|
||||
else -> {
|
||||
val arrElementDt = iterable.type.elementType()
|
||||
val elementSize = program.memsizer.memorySize(arrElementDt, null)
|
||||
val lengthBytes = iterableLength!! * elementSize
|
||||
val arrElementIR = irType(arrElementDt)
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, indexRegType, reg1=indexReg, immediate = 0), null)
|
||||
val loopChunk = IRCodeChunk(loopLabel, null)
|
||||
loopChunk += IRInstruction(Opcode.LOADX, arrElementIR, reg1=tmpReg, reg2=indexReg, labelSymbol=iterable.name)
|
||||
loopChunk += IRInstruction(Opcode.LOADX, arrElementIR, reg1=tmpReg, reg2=indexReg, labelSymbol=iterable.name, scale = elementSize)
|
||||
val (storeReg, storeDt) = emitWidening(loopChunk, tmpReg, arrElementIR)
|
||||
loopChunk += IRInstruction(Opcode.STOREM, storeDt, reg1=storeReg, labelSymbol = loopvarSymbol)
|
||||
result += loopChunk
|
||||
result += translateNode(forLoop.statements)
|
||||
result += addConstToReg(indexReg, elementSize, indexRegType)
|
||||
result += addConstToReg(indexReg, 1, indexRegType)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
if(lengthBytes!=256 || indexRegType==IRDataType.WORD || elementSize!=1)
|
||||
it += IRInstruction(Opcode.CMPI, indexRegType, reg1=indexReg, immediate = lengthBytes)
|
||||
if(iterableLength!=256 || indexRegType==IRDataType.WORD)
|
||||
it += IRInstruction(Opcode.CMPI, indexRegType, reg1=indexReg, immediate = iterableLength!!)
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = loopLabel)
|
||||
}
|
||||
}
|
||||
@@ -2251,7 +2250,7 @@ class IRCodeGen(
|
||||
}
|
||||
indexReg = newReg
|
||||
}
|
||||
result += multiplyByConst(DataType.UWORD, indexReg, itemsize)
|
||||
// no pre-scaling - scale is encoded in the LOADX/STOREX instruction
|
||||
return Pair(result, indexReg)
|
||||
}
|
||||
|
||||
@@ -2279,10 +2278,7 @@ class IRCodeGen(
|
||||
indexReg = newReg
|
||||
}
|
||||
|
||||
if(itemsize==1 || arrayIsSplitWords)
|
||||
return Pair(result, indexReg)
|
||||
|
||||
result += multiplyByConst(if(indexRegType == IRDataType.WORD) DataType.UWORD else DataType.UBYTE, indexReg, itemsize)
|
||||
// no pre-scaling - scale is encoded in the LOADX/STOREX instruction
|
||||
return Pair(result, indexReg)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user