vm: fix postincr/decr on indexed pointervariables

This commit is contained in:
Irmen de Jong 2023-07-31 19:35:57 +02:00
parent 0cba736446
commit 9bb16e293c
6 changed files with 58 additions and 37 deletions

View File

@ -118,6 +118,9 @@ class PtArrayIndexer(elementType: DataType, position: Position): PtExpression(el
val splitWords: Boolean
get() = variable.type in SplitWordArrayTypes
val usesPointerVariable: Boolean
get() = variable.type==DataType.UWORD
init {
require(elementType in NumericDatatypes)
}

View File

@ -61,8 +61,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val elementDt = assign.source.datatype
val arrayVarName = asmgen.asmVariableName(value.variable)
if(value.variable.type==DataType.UWORD) {
// indexing a pointer var instead of a real array or string
if(value.usesPointerVariable) {
if(elementDt !in ByteDatatypes)
throw AssemblyError("non-array var indexing requires bytes dt")
if(value.type != DataType.UBYTE)
@ -2267,14 +2266,13 @@ internal class AssignmentAsmGen(private val program: PtProgram,
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) {
// assigning an indexed pointer var
if(assignsIndexedPointerVar(target)) {
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda $sourceName")
asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable)
asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) {
if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
asmgen.out(" lda $sourceName | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
@ -2489,8 +2487,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
TODO("assign register as word into Array not yet supported")
if(target.array!!.splitWords)
TODO("assign register into split words ${target.position}")
if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) {
// assigning an indexed pointer var
if(assignsIndexedPointerVar(target)) {
if (target.constArrayIndexValue!=null) {
when (register) {
CpuRegister.A -> {}
@ -2515,7 +2512,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
CpuRegister.X -> asmgen.out(" txa")
CpuRegister.Y -> asmgen.out(" tya")
}
val indexVar = target.array!!.index as PtIdentifier
val indexVar = target.array.index as PtIdentifier
if(asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta (${target.asmVarname}),y")
} else {
@ -2545,7 +2542,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
CpuRegister.X -> asmgen.out(" txa")
CpuRegister.Y -> asmgen.out(" tya")
}
val indexVar = target.array!!.index as PtIdentifier
val indexVar = target.array.index as PtIdentifier
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
}
}
@ -2987,14 +2984,13 @@ internal class AssignmentAsmGen(private val program: PtProgram,
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) {
// assigning an indexed pointer var
if(assignsIndexedPointerVar(target)) {
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda #0")
asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable)
asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) {
if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
asmgen.out(" lda #0 | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
@ -3042,14 +3038,13 @@ internal class AssignmentAsmGen(private val program: PtProgram,
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) {
// assigning an indexed pointer var
if(assignsIndexedPointerVar(target)) {
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda #${byte.toHex()}")
asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable)
asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) {
if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) {
asmgen.out(" lda #${byte.toHex()} | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
@ -3095,6 +3090,9 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
private fun assignsIndexedPointerVar(target: AsmAssignTarget): Boolean =
target.origAstTarget?.array?.variable?.type==DataType.UWORD
internal fun assignConstantFloat(target: AsmAssignTarget, float: Double) {
if (float == 0.0) {
// optimized case for float zero

View File

@ -198,8 +198,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val variable = targetArray.variable.name
val itemsize = codeGen.program.memsizer.memorySize(targetArray.type)
if(targetArray.variable.type==DataType.UWORD) {
// indexing a pointer var instead of a real array or string
if(targetArray.usesPointerVariable) {
if(itemsize!=1)
throw AssemblyError("non-array var indexing requires bytes dt")
if(targetArray.index.type!=DataType.UBYTE)

View File

@ -147,8 +147,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val result = mutableListOf<IRCodeChunkBase>()
val arrayVarSymbol = arrayIx.variable.name
if(arrayIx.variable.type==DataType.UWORD) {
// indexing a pointer var instead of a real array or string
if(arrayIx.usesPointerVariable) {
if(eltSize!=1)
throw AssemblyError("non-array var indexing requires bytes dt")
if(arrayIx.index.type!=DataType.UBYTE)

View File

@ -1469,7 +1469,19 @@ class IRCodeGen(
val fixedIndex = constIntValue(array.index)
if(fixedIndex!=null) {
val offset = fixedIndex*itemsize
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol="$variable+$offset"), null)
val indexReg = registers.nextFree()
val dataReg = registers.nextFree()
if(array.usesPointerVariable) {
// we don't have an indirect dec/inc so do it via an intermediate register
result += IRCodeChunk(null,null).also {
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = indexReg, immediate = offset)
it += IRInstruction(Opcode.LOADIX, irDt, reg1 = dataReg, reg2 = indexReg, labelSymbol = variable)
it += IRInstruction(operationRegister, irDt, reg1=dataReg)
it += IRInstruction(Opcode.STOREIX, irDt, reg1 = dataReg, reg2 = indexReg, labelSymbol = variable)
}
} else {
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = "$variable+$offset"), null)
}
} else {
val indexTr = expressionEval.translateExpression(array.index)
addToResult(result, indexTr, indexTr.resultReg, -1)
@ -1477,9 +1489,15 @@ class IRCodeGen(
result += multiplyByConst(IRDataType.BYTE, indexTr.resultReg, itemsize)
result += IRCodeChunk(null, null).also {
val incReg = registers.nextFree()
it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
it += IRInstruction(operationRegister, irDt, reg1=incReg)
it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
if(array.usesPointerVariable) {
it += IRInstruction(Opcode.LOADIX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
it += IRInstruction(operationRegister, irDt, reg1=incReg)
it += IRInstruction(Opcode.STOREIX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
} else {
it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
it += IRInstruction(operationRegister, irDt, reg1=incReg)
it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
}
}
}
} else

View File

@ -1,16 +1,20 @@
%import textio
%zeropage basicsafe
main {
sub start() {
ubyte var = 0
ubyte[2] data = [100, 100]
uword dRef = &data
when var {
1 -> txt.print("one")
2 -> txt.print("two")
0 -> {
}
else -> txt.print("other")
}
}
sub start() {
dRef[0]--
dRef[1]++
cx16.r0L = 0
cx16.r1L = 1
dRef[cx16.r0L]--
dRef[cx16.r1L]++
txt.print_ub(data[0])
txt.spc()
txt.print_ub(data[1])
}
}