From 0a65dfdd10e7d5a8cafb9e2720abd35ef4dff57f Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 6 Jun 2022 22:54:54 +0200 Subject: [PATCH] optimized codegen for some more simple expressions with +/- --- .../cpu6502/assignment/AssignmentAsmGen.kt | 139 +++++++++++++++++- examples/test.p8 | 64 ++------ 2 files changed, 149 insertions(+), 54 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 8ea5bb3fd..1edb4d223 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -318,7 +318,7 @@ internal class AssignmentAsmGen(private val program: Program, // no orig ast assign target so can't use the workaround, so fallback to stack eval fallbackToStackEval(assign) } - } else { + } else if(!attemptAssignOptimizedBinexpr(value, assign)) { // All remaining binary expressions just evaluate via the stack for now. // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // because the code here is the implementation of exactly that...) @@ -329,6 +329,143 @@ internal class AssignmentAsmGen(private val program: Program, } } + private fun attemptAssignOptimizedBinexpr(expr: BinaryExpression, assign: AsmAssignment): Boolean { + if(!expr.inferType(program).isInteger) + return false + if(expr.operator!="+" && expr.operator!="-") + return false + + val dt = expr.inferType(program).getOrElse { throw AssemblyError("invalid dt") } + val left = expr.left + val right = expr.right + if(dt in ByteDatatypes) { + when (right) { + is IdentifierReference -> { + assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE) + val symname = asmgen.asmVariableName(right) + if(expr.operator=="+") + asmgen.out(" clc | adc $symname") + else + asmgen.out(" sec | sbc $symname") + assignRegisterByte(assign.target, CpuRegister.A) + return true + } + is NumericLiteral -> { + assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE) + if(expr.operator=="+") + asmgen.out(" clc | adc #${right.number.toHex()}") + else + asmgen.out(" sec | sbc #${right.number.toHex()}") + assignRegisterByte(assign.target, CpuRegister.A) + return true + } + else -> return false + } + } else if(dt in WordDatatypes) { + when (right) { + is AddressOf -> { + assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) + val symbol = asmgen.asmVariableName(right.identifier) + if(expr.operator=="+") + asmgen.out(""" + clc + adc #<$symbol + pha + tya + adc #>$symbol + tay + pla""") + else + asmgen.out(""" + sec + sbc #<$symbol + pha + tya + sbc #>$symbol + tay + pla""") + assignRegisterpairWord(assign.target, RegisterOrPair.AY) + return true + } + is IdentifierReference -> { + val symname = asmgen.asmVariableName(right) + assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) + if(expr.operator=="+") + asmgen.out(""" + clc + adc $symname + pha + tya + adc $symname+1 + tay + pla""") + else + asmgen.out(""" + sec + sbc $symname + pha + tya + sbc $symname+1 + tay + pla""") + assignRegisterpairWord(assign.target, RegisterOrPair.AY) + return true + } + is NumericLiteral -> { + assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) + if(expr.operator=="+") { + asmgen.out(""" + clc + adc #<${right.number.toHex()} + pha + tya + adc #>${right.number.toHex()} + tay + pla""") + } else if(expr.operator=="-") { + asmgen.out(""" + sec + sbc #<${right.number.toHex()} + pha + tya + sbc #>${right.number.toHex()} + tay + pla""") + } + assignRegisterpairWord(assign.target, RegisterOrPair.AY) + return true + } + is TypecastExpression -> { + val castedValue = right.expression + if(right.type in WordDatatypes && castedValue.inferType(program).isBytes) { + if(castedValue is IdentifierReference) { + val castedSymname = asmgen.asmVariableName(castedValue) + assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD) + if(expr.operator=="+") + asmgen.out(""" + clc + adc $castedSymname + bcc + + iny ++""") + else + asmgen.out(""" + sec + sbc $castedSymname + bcs + + dey ++""") + assignRegisterpairWord(assign.target, RegisterOrPair.AY) + return true + } + } + } + else -> return false + } + } + return false + } + private fun fallbackToStackEval(assign: AsmAssignment) { // TODO DON'T STACK-EVAL... perhaps by using a temp var? so that it becomes augmentable assignment expression? // or don't try to solve it here in this one case and rather rewrite the whole stack based value evaluation. diff --git a/examples/test.p8 b/examples/test.p8 index ffe552870..f023cafe0 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -33,64 +33,22 @@ main { ; mcCarthy() ;test_stack.test() - ubyte value = 0 ubyte one = 1 ubyte two = 2 - ubyte[10] data = [11,22,33,4,5,6,7,8,9,10] + uword onew = 1 + uword twow = 2 + ubyte[10] data = [1,2,3,4,5,6,7,8,9,10] uword bitmapbuf = &data - ; 11 22 33 - txt.print_ub(bitmapbuf[0]) - txt.spc() - txt.print_ub(bitmapbuf[1]) - txt.spc() - txt.print_ub(bitmapbuf[2]) - txt.nl() - rol(bitmapbuf[0]) - rol(bitmapbuf[0]) - txt.print_ub(bitmapbuf[0]) ; 44 - txt.spc() - ror(bitmapbuf[0]) - ror(bitmapbuf[0]) - txt.print_ub(bitmapbuf[0]) ; 11 - txt.nl() - - ; 22 44 66 - txt.print_ub(bitmapbuf[0]*2) - txt.spc() - txt.print_ub(bitmapbuf[1]*2) - txt.spc() - txt.print_ub(bitmapbuf[2]*2) - txt.nl() - - value = one+one+one+one+one - txt.print_ub(value) ; 5 - txt.nl() - - bitmapbuf[0] = one+one+one - bitmapbuf[0] = one+one+one - bitmapbuf[0] = one+one+one - bitmapbuf[1] = one+one - bitmapbuf[1] = one+one - bitmapbuf[1] = one+one - bitmapbuf[2] = one - bitmapbuf[2] = one - bitmapbuf[2] = one - bitmapbuf[3] = 42 - bitmapbuf[2] += 100 - bitmapbuf[2] -= 1 - bitmapbuf[2] -= 1 - bitmapbuf[2] -= 1 - bitmapbuf[2] -= 1 - - ; 3 2 97 - txt.print_ub(bitmapbuf[0]) - txt.spc() - txt.print_ub(bitmapbuf[1]) - txt.spc() - txt.print_ub(bitmapbuf[2]) - txt.nl() +; @(bitmapbuf+onew) = 90+one +; @(bitmapbuf+twow) = 90+two + bitmapbuf += 5 +; @(bitmapbuf-1) = 90+one +; @(bitmapbuf-2) = 90+two + @(bitmapbuf-onew) = 90+one + @(bitmapbuf-twow) = 90+two + ubyte value for value in data { txt.print_ub(value) ; 3 2 97 42 5 6 7 8 9 10 txt.spc()