From 125f6205f2e0cfb2106cb77de5d85f2632f0d8db Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 22 Nov 2020 17:16:07 +0100 Subject: [PATCH] optimizing assigning an array value to a var --- .../codegen/assignment/AssignmentAsmGen.kt | 61 +++++++++++--- .../assignment/AugmentableAssignmentAsmGen.kt | 2 +- docs/source/todo.rst | 2 - examples/test.p8 | 81 +++++++------------ 4 files changed, 80 insertions(+), 66 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 43ab63342..16d1b9e93 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -68,12 +68,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen // constant array index value val indexValue = value.indexer.constIndex()!! * elementDt.memorySize() when (elementDt) { - in ByteDatatypes -> - asmgen.out(" lda $arrayVarName+$indexValue | sta P8ESTACK_LO,x | dex") - in WordDatatypes -> - asmgen.out(" lda $arrayVarName+$indexValue | sta P8ESTACK_LO,x | lda $arrayVarName+$indexValue+1 | sta P8ESTACK_HI,x | dex") - DataType.FLOAT -> - asmgen.out(" lda #<$arrayVarName+$indexValue | ldy #>$arrayVarName+$indexValue | jsr floats.push_float") + in ByteDatatypes -> { + asmgen.out(" lda $arrayVarName+$indexValue") + assignRegisterByte(assign.target, CpuRegister.A) + } + in WordDatatypes -> { + 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 -> throw AssemblyError("weird array type") } @@ -81,11 +87,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen when (elementDt) { in ByteDatatypes -> { 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 -> { 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 -> { asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.A) @@ -95,13 +103,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen adc #<$arrayVarName bcc + iny -+ jsr floats.push_float""") ++""") + assignFloatFromAY(assign.target) } else -> throw AssemblyError("weird array elt type") } } - assignStackValue(assign.target) } SourceStorageKind.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) { when(target.kind) { TargetStorageKind.VARIABLE -> { diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index d7c80b2bc..4e6e97370 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -184,7 +184,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, else -> { if(asmgen.options.slowCodegenWarnings) 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") val zp = CompilationTarget.instance.machine.zeropage when { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 94f60312d..755605602 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,6 @@ TODO ==== - 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 '_' - 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 diff --git a/examples/test.p8 b/examples/test.p8 index f43f8b365..ff30856c9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,65 +7,40 @@ main { sub start() { - float uw1 - const float uw2 = 2.2 + ubyte[] ubarray = [1,2,3,4] + 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 - if uw1uw2 - txt.chrout('!') - else - txt.chrout('.') + ubyte ub + byte bb + uword uw + word ww + float fl - if uw1>=uw2 - txt.chrout('!') - else - txt.chrout('.') - if uw1==uw2 - txt.chrout('!') - else - txt.chrout('.') - if uw1!=uw2 - txt.chrout('.') - else - txt.chrout('!') + const ubyte i = 2 + const ubyte j = 3 + ub = ubarray[i] + txt.print_ub(ub) + txt.chrout('\n') - txt.chrout(' ') - uw1 = 2.2 + bb = barray[i] + txt.print_b(bb) + txt.chrout('\n') - if uw1uw2 - txt.chrout('!') - else - txt.chrout('.') + uw = uwarray[i] + txt.print_uw(uw) + txt.chrout('\n') - if uw1>=uw2 - txt.chrout('.') - else - txt.chrout('!') - if uw1==uw2 - txt.chrout('.') - else - txt.chrout('!') - if uw1!=uw2 - txt.chrout('!') - else - txt.chrout('.') + ww = warray[i] + txt.print_w(ww) + txt.chrout('\n') + + fl = farray[i] + floats.print_f(fl) + txt.chrout('\n') test_stack.test() txt.chrout('\n')