optimizing assigning an array value to a var

This commit is contained in:
Irmen de Jong 2020-11-22 17:16:07 +01:00
parent 8136f3df5c
commit 125f6205f2
4 changed files with 80 additions and 66 deletions

View File

@ -68,12 +68,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
// constant array index value // constant array index value
val indexValue = value.indexer.constIndex()!! * elementDt.memorySize() val indexValue = value.indexer.constIndex()!! * elementDt.memorySize()
when (elementDt) { when (elementDt) {
in ByteDatatypes -> in ByteDatatypes -> {
asmgen.out(" lda $arrayVarName+$indexValue | sta P8ESTACK_LO,x | dex") asmgen.out(" lda $arrayVarName+$indexValue")
in WordDatatypes -> assignRegisterByte(assign.target, CpuRegister.A)
asmgen.out(" lda $arrayVarName+$indexValue | sta P8ESTACK_LO,x | lda $arrayVarName+$indexValue+1 | sta P8ESTACK_HI,x | dex") }
DataType.FLOAT -> in WordDatatypes -> {
asmgen.out(" lda #<$arrayVarName+$indexValue | ldy #>$arrayVarName+$indexValue | jsr floats.push_float") asmgen.out(" lda $arrayVarName+$indexValue | ldy $arrayVarName+$indexValue+1")
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
}
DataType.FLOAT -> {
asmgen.out(" lda #<$arrayVarName+$indexValue | ldy #>$arrayVarName+$indexValue")
assignFloatFromAY(assign.target)
}
else -> else ->
throw AssemblyError("weird array type") throw AssemblyError("weird array type")
} }
@ -81,11 +87,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
when (elementDt) { when (elementDt) {
in ByteDatatypes -> { in ByteDatatypes -> {
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y) asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y)
asmgen.out(" lda $arrayVarName,y | sta P8ESTACK_LO,x | dex") asmgen.out(" lda $arrayVarName,y")
assignRegisterByte(assign.target, CpuRegister.A)
} }
in WordDatatypes -> { in WordDatatypes -> {
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y) asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y)
asmgen.out(" lda $arrayVarName,y | sta P8ESTACK_LO,x | lda $arrayVarName+1,y | sta P8ESTACK_HI,x | dex") asmgen.out(" lda $arrayVarName,y | pha | lda $arrayVarName+1,y | tay | pla")
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.A) asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.A)
@ -95,13 +103,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
adc #<$arrayVarName adc #<$arrayVarName
bcc + bcc +
iny iny
+ jsr floats.push_float""") +""")
assignFloatFromAY(assign.target)
} }
else -> else ->
throw AssemblyError("weird array elt type") throw AssemblyError("weird array elt type")
} }
} }
assignStackValue(assign.target)
} }
SourceStorageKind.MEMORY -> { SourceStorageKind.MEMORY -> {
val value = assign.source.memory!! val value = assign.source.memory!!
@ -726,6 +734,39 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
} }
private fun assignFloatFromAY(target: AsmAssignTarget) {
when(target.kind) {
TargetStorageKind.VARIABLE -> {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #<${target.asmVarname}
ldy #>${target.asmVarname}
jsr floats.copy_float""")
}
TargetStorageKind.ARRAY -> {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #<${target.asmVarname}
ldy #>${target.asmVarname}
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1""")
if(target.array!!.indexer.indexNum!=null) {
val index = target.array.indexer.constIndex()!!
asmgen.out(" lda #$index")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
asmgen.out(" lda $asmvarname")
}
asmgen.out(" jsr floats.set_array_float")
}
TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to mem byte")
TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register")
TargetStorageKind.STACK -> asmgen.out(" jsr floats.push_float")
}
}
private fun assignVariableFloat(target: AsmAssignTarget, sourceName: String) { private fun assignVariableFloat(target: AsmAssignTarget, sourceName: String) {
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {

View File

@ -184,7 +184,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
else -> { else -> {
if(asmgen.options.slowCodegenWarnings) if(asmgen.options.slowCodegenWarnings)
println("warning: slow stack evaluation used (1): ${memory.addressExpression::class.simpleName} at ${memory.addressExpression.position}") // TODO optimize... println("warning: slow stack evaluation used (1): ${memory.addressExpression::class.simpleName} at ${memory.addressExpression.position}") // TODO optimize...
asmgen.translateExpression(memory.addressExpression) // TODO directly into P8ZP_SCRATCH_W2 asmgen.translateExpression(memory.addressExpression) // TODO directly into P8ZP_SCRATCH_W2?
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1") asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
val zp = CompilationTarget.instance.machine.zeropage val zp = CompilationTarget.instance.machine.zeropage
when { when {

View File

@ -3,8 +3,6 @@ TODO
==== ====
- check cpu stack consistency in all examples - check cpu stack consistency in all examples
- reduce the amount of translateExpression() calls when the result can be directly assigned to register or variable
- cc = xbuf[i] + ybuf[ii] generates unnecessary stack push/pulls (and no slow warning is given for it)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
- see if we can group some errors together for instance the (now single) errors about unidentified symbols - see if we can group some errors together for instance the (now single) errors about unidentified symbols

View File

@ -7,65 +7,40 @@ main {
sub start() { sub start() {
float uw1 ubyte[] ubarray = [1,2,3,4]
const float uw2 = 2.2 byte[] barray = [1,2,3,4]
uword[] uwarray = [1,2,3,4]
word[] warray = [1,2,3,4]
float[] farray = [1.1,2.2,3.3,4.4]
uw1 = 1.1 ubyte ub
if uw1<uw2 byte bb
txt.chrout('.') uword uw
else word ww
txt.chrout('!') float fl
if uw1<=uw2
txt.chrout('.')
else
txt.chrout('!')
if uw1>uw2
txt.chrout('!')
else
txt.chrout('.')
if uw1>=uw2 const ubyte i = 2
txt.chrout('!') const ubyte j = 3
else
txt.chrout('.')
if uw1==uw2
txt.chrout('!')
else
txt.chrout('.')
if uw1!=uw2
txt.chrout('.')
else
txt.chrout('!')
ub = ubarray[i]
txt.print_ub(ub)
txt.chrout('\n')
txt.chrout(' ') bb = barray[i]
uw1 = 2.2 txt.print_b(bb)
txt.chrout('\n')
if uw1<uw2 uw = uwarray[i]
txt.chrout('!') txt.print_uw(uw)
else txt.chrout('\n')
txt.chrout('.')
if uw1<=uw2
txt.chrout('.')
else
txt.chrout('!')
if uw1>uw2
txt.chrout('!')
else
txt.chrout('.')
if uw1>=uw2 ww = warray[i]
txt.chrout('.') txt.print_w(ww)
else txt.chrout('\n')
txt.chrout('!')
if uw1==uw2 fl = farray[i]
txt.chrout('.') floats.print_f(fl)
else txt.chrout('\n')
txt.chrout('!')
if uw1!=uw2
txt.chrout('!')
else
txt.chrout('.')
test_stack.test() test_stack.test()
txt.chrout('\n') txt.chrout('\n')