more array access optimizations

This commit is contained in:
Irmen de Jong 2020-08-23 22:36:49 +02:00
parent 5c62f612cc
commit 1f17c22132
2 changed files with 190 additions and 45 deletions

View File

@ -181,12 +181,68 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", target.memory!!) storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// if(target.constArrayIndexValue!=null) { val index = target.array!!.arrayspec.index
// TODO("const index ${target.constArrayIndexValue}") when {
// } target.constArrayIndexValue!=null -> {
asmgen.translateExpression(target.array!!.arrayspec.index) val scaledIdx = target.constArrayIndexValue!! * target.datatype.memorySize()
asmgen.out(" inx | lda $ESTACK_LO_HEX,x") when(target.datatype) {
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname) in ByteDatatypes -> {
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta ${target.asmVarname}+$scaledIdx")
}
in WordDatatypes -> {
asmgen.out("""
inx
lda $ESTACK_LO_HEX,x
sta ${target.asmVarname}+$scaledIdx
lda $ESTACK_HI_HEX,x
sta ${target.asmVarname}+$scaledIdx+1
""")
}
DataType.FLOAT -> {
asmgen.out("""
lda #<${target.asmVarname}+$scaledIdx
ldy #>${target.asmVarname}+$scaledIdx
jsr c64flt.pop_float
""")
}
else -> throw AssemblyError("weird target variable type ${target.datatype}")
}
}
index is IdentifierReference -> {
when(target.datatype) {
DataType.UBYTE, DataType.BYTE -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta ${target.asmVarname},y")
}
DataType.UWORD, DataType.WORD -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out("""
inx
lda $ESTACK_LO_HEX,x
sta ${target.asmVarname},y
lda $ESTACK_HI_HEX,x
sta ${target.asmVarname}+1,y
""")
}
DataType.FLOAT -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.A)
asmgen.out("""
ldy #>${target.asmVarname}
clc
adc #<${target.asmVarname}
bcc +
iny
+ jsr c64flt.pop_float""")
}
else -> throw AssemblyError("weird dt")
}
}
else -> {
asmgen.translateExpression(index)
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname)
}
}
} }
TargetStorageKind.REGISTER -> TODO() TargetStorageKind.REGISTER -> TODO()
TargetStorageKind.STACK -> TODO() TargetStorageKind.STACK -> TODO()
@ -242,14 +298,75 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
throw AssemblyError("no asm gen for assign wordvar $sourceName to memory ${target.memory}") throw AssemblyError("no asm gen for assign wordvar $sourceName to memory ${target.memory}")
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}")
// }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | lda $sourceName+1 | sta $ESTACK_HI_HEX,x | dex") when {
asmgen.translateExpression(index) target.constArrayIndexValue!=null -> {
asmgen.out(" inx | lda $ESTACK_LO_HEX,x") val scaledIdx = target.constArrayIndexValue!! * target.datatype.memorySize()
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname) when(target.datatype) {
in ByteDatatypes -> {
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
}
in WordDatatypes -> {
asmgen.out("""
lda $sourceName
sta ${target.asmVarname}+$scaledIdx
lda $sourceName+1
sta ${target.asmVarname}+$scaledIdx+1
""")
}
DataType.FLOAT -> {
asmgen.out("""
lda #<$sourceName
ldy #>$sourceName
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1+1}
lda #<${target.asmVarname}+$scaledIdx
ldy #>${target.asmVarname}+$scaledIdx
jsr c64flt.copy_float
""")
}
else -> throw AssemblyError("weird target variable type ${target.datatype}")
}
}
index is IdentifierReference -> {
when(target.datatype) {
DataType.UBYTE, DataType.BYTE -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
}
DataType.UWORD, DataType.WORD -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out("""
lda $sourceName
sta ${target.asmVarname},y
lda $sourceName+1
sta ${target.asmVarname}+1,y
""")
}
DataType.FLOAT -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.A)
asmgen.out("""
ldy #<$sourceName
sty ${C64Zeropage.SCRATCH_W1}
ldy #>$sourceName
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #>${target.asmVarname}
clc
adc #<${target.asmVarname}
bcc +
iny
+ jsr c64flt.copy_float""")
}
else -> throw AssemblyError("weird dt")
}
}
else -> {
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | lda $sourceName+1 | sta $ESTACK_HI_HEX,x | dex")
asmgen.translateExpression(index)
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname)
}
}
} }
TargetStorageKind.REGISTER -> TODO() TargetStorageKind.REGISTER -> TODO()
TargetStorageKind.STACK -> TODO() TargetStorageKind.STACK -> TODO()
@ -274,8 +391,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
""") """)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// TODO optimize this, but the situation doesn't occur very often
// if(target.constArrayIndexValue!=null) { // if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}") // TODO("const index ${target.constArrayIndexValue}")
// } else if(target.array!!.arrayspec.index is IdentifierReference) {
// TODO("array[var] ${target.constArrayIndexValue}")
// } // }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr c64flt.push_float") asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr c64flt.push_float")
@ -299,14 +419,23 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!) storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}")
// }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | dex") when {
asmgen.translateExpression(index) target.constArrayIndexValue!=null -> {
asmgen.out(" inx | lda $ESTACK_LO_HEX,x") val scaledIdx = target.constArrayIndexValue!! * target.datatype.memorySize()
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname) asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
}
index is IdentifierReference -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out(" lda $sourceName | sta ${target.asmVarname},y")
}
else -> {
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | dex")
asmgen.translateExpression(index)
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
popAndWriteArrayvalueWithUnscaledIndexA(target.datatype, target.asmVarname)
}
}
} }
TargetStorageKind.REGISTER -> TODO() TargetStorageKind.REGISTER -> TODO()
TargetStorageKind.STACK -> TODO() TargetStorageKind.STACK -> TODO()
@ -323,9 +452,6 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
storeRegisterInMemoryAddress(register, target.memory!!) storeRegisterInMemoryAddress(register, target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}")
// }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
when (index) { when (index) {
is NumericLiteralValue -> { is NumericLiteralValue -> {
@ -338,16 +464,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
is IdentifierReference -> { is IdentifierReference -> {
when (register) { when (register) {
CpuRegister.A -> asmgen.out(" sta ${C64Zeropage.SCRATCH_B1}") CpuRegister.A -> {}
CpuRegister.X -> asmgen.out(" stx ${C64Zeropage.SCRATCH_B1}") CpuRegister.X -> asmgen.out(" txa")
CpuRegister.Y -> asmgen.out(" sty ${C64Zeropage.SCRATCH_B1}") CpuRegister.Y -> asmgen.out(" tya")
} }
asmgen.out(""" asmgen.out(" ldy ${asmgen.asmIdentifierName(index)} | sta ${target.asmVarname},y")
lda ${asmgen.asmIdentifierName(index)}
tay
lda ${C64Zeropage.SCRATCH_B1}
sta ${target.asmVarname},y
""")
} }
else -> { else -> {
asmgen.saveRegister(register) asmgen.saveRegister(register)
@ -396,8 +517,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
throw AssemblyError("no asm gen for assign word $word to memory ${target.memory}") throw AssemblyError("no asm gen for assign word $word to memory ${target.memory}")
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// TODO optimize this, but the situation doesn't occur very often
// if(target.constArrayIndexValue!=null) { // if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}") // TODO("const index ${target.constArrayIndexValue}")
// } else if(target.array!!.arrayspec.index is IdentifierReference) {
// TODO("array[var] ${target.constArrayIndexValue}")
// } // }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
asmgen.translateExpression(index) asmgen.translateExpression(index)
@ -420,23 +544,32 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
private fun assignConstantByte(target: AsmAssignTarget, byte: Short) { private fun assignConstantByte(target: AsmAssignTarget, byte: Short) {
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname} ") asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname} ")
} }
TargetStorageKind.MEMORY -> { TargetStorageKind.MEMORY -> {
storeByteViaRegisterAInMemoryAddress("#${byte.toHex()}", target.memory!!) storeByteViaRegisterAInMemoryAddress("#${byte.toHex()}", target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}")
// }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
asmgen.translateExpression(index) when {
asmgen.out(""" target.constArrayIndexValue!=null -> {
inx val indexValue = target.constArrayIndexValue!!
ldy $ESTACK_LO_HEX,x asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue")
lda #${byte.toHex()} }
sta ${target.asmVarname},y index is IdentifierReference -> {
""") asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UBYTE, CpuRegister.Y)
asmgen.out(" lda #<${byte.toHex()} | sta ${target.asmVarname},y | lda #>${byte.toHex()} | sta ${target.asmVarname}+1,y")
}
else -> {
asmgen.translateExpression(index)
asmgen.out("""
inx
ldy $ESTACK_LO_HEX,x
lda #${byte.toHex()}
sta ${target.asmVarname},y
""")
}
}
} }
else -> throw AssemblyError("no asm gen for assign byte $byte to $target") else -> throw AssemblyError("no asm gen for assign byte $byte to $target")
} }
@ -457,8 +590,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
""") """)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// TODO optimize this, but the situation doesn't occur very often
// if(target.constArrayIndexValue!=null) { // if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}") // TODO("const index ${target.constArrayIndexValue}")
// } else if(target.array!!.arrayspec.index is IdentifierReference) {
// TODO("array[var] ${target.constArrayIndexValue}")
// } // }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
if (index is NumericLiteralValue) { if (index is NumericLiteralValue) {
@ -503,8 +639,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
""") """)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
// TODO optimize this, but the situation doesn't occur very often
// if(target.constArrayIndexValue!=null) { // if(target.constArrayIndexValue!=null) {
// TODO("const index ${target.constArrayIndexValue}") // TODO("const index ${target.constArrayIndexValue}")
// } else if(target.array!!.arrayspec.index is IdentifierReference) {
// TODO("array[var] ${target.constArrayIndexValue}")
// } // }
val index = target.array!!.arrayspec.index val index = target.array!!.arrayspec.index
val arrayVarName = target.asmVarname val arrayVarName = target.asmVarname

View File

@ -11,11 +11,17 @@ main {
uword[] array=[1111 ,2222,3333] uword[] array=[1111 ,2222,3333]
float[] farr = [1.111, 2.222, 3.333] float[] farr = [1.111, 2.222, 3.333]
ubyte ub
uword uw
float ff float ff
ubyte i = 1 ubyte i = 1
farr[2] = farr[i] arr1[i] = ub
c64flt.print_f(farr[2]) array[i] = uw
farr[2] = 3.15
farr[2] = ff
farr[i] = ff
c64flt.print_f(farr[1])
c64.CHROUT('\n') c64.CHROUT('\n')
; c64scr.print_ub(arr1[1]) ; c64scr.print_ub(arr1[1])