From 68336a76c5da5b0dfa346cc43b1903e7b3962e7d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 7 May 2023 19:55:06 +0200 Subject: [PATCH] optimized word comparison expressions --- .../cpu6502/assignment/AssignmentAsmGen.kt | 123 +++++++++++++++--- docs/source/todo.rst | 3 +- examples/test.p8 | 46 ++++--- 3 files changed, 132 insertions(+), 40 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index cb93c7a4a..4df9f6812 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -820,7 +820,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } private fun assignOptimizedComparisonWords(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { - val signed = expr.left.type == DataType.BYTE || expr.right.type == DataType.BYTE + val signed = expr.left.type == DataType.WORD || expr.right.type == DataType.WORD fun assignExpressionOperandsLeftScratchRightAY() { if(expr.right.isSimple()) { assignExpressionToVariable(expr.left, "P8ZP_SCRATCH_W1", expr.left.type) @@ -834,6 +834,19 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.restoreRegisterStack(CpuRegister.A, false) } } + fun assignExpressionOperandsLeftAYRightScratch() { + if(expr.left.isSimple()) { + assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", expr.left.type) + assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed) + } else { + assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed) + asmgen.saveRegisterStack(CpuRegister.A, false) + asmgen.saveRegisterStack(CpuRegister.Y, false) + assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", expr.left.type) + asmgen.restoreRegisterStack(CpuRegister.Y, false) + asmgen.restoreRegisterStack(CpuRegister.A, false) + } + } when(expr.operator) { "==" -> { assignExpressionOperandsLeftScratchRightAY() @@ -861,42 +874,118 @@ internal class AssignmentAsmGen(private val program: PtProgram, } "<" -> { if(signed) { - // TODO("word <") - return false + assignExpressionOperandsLeftAYRightScratch() + asmgen.out(""" + cmp P8ZP_SCRATCH_W1 + tya + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #${'$'}80 ++ bpl ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } else { - // TODO("uword <") - return false + assignExpressionOperandsLeftAYRightScratch() + asmgen.out(""" + cpy P8ZP_SCRATCH_W1+1 + bcc + + bne ++ + cmp P8ZP_SCRATCH_W1 + bcs ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } } "<=" -> { if(signed) { - // TODO("word <=") - return false + assignExpressionOperandsLeftScratchRightAY() + asmgen.out(""" + cmp P8ZP_SCRATCH_W1 + tya + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #${'$'}80 ++ bmi + + lda #1 + bne ++ ++ lda #0 ++""") } else { - // TODO("uword =<") - return false + assignExpressionOperandsLeftScratchRightAY() + asmgen.out(""" + cpy P8ZP_SCRATCH_W1+1 + bcc ++ + bne + + cmp P8ZP_SCRATCH_W1 + bcc ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } } ">" -> { if(signed) { - // TODO("word >") - return false + assignExpressionOperandsLeftScratchRightAY() + asmgen.out(""" + cmp P8ZP_SCRATCH_W1 + tya + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #${'$'}80 ++ bpl ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } else { - // TODO("uword >") - return false + assignExpressionOperandsLeftScratchRightAY() + asmgen.out(""" + cpy P8ZP_SCRATCH_W1+1 + bcc + + bne ++ + cmp P8ZP_SCRATCH_W1 + bcs ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } } ">=" -> { if(signed) { - // TODO("word >=") - return false + assignExpressionOperandsLeftAYRightScratch() + asmgen.out(""" + cmp P8ZP_SCRATCH_W1 + tya + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #${'$'}80 ++ bmi + + lda #1 + bne ++ ++ lda #0 ++""") } else { - // TODO("uword >=") - return false + assignExpressionOperandsLeftAYRightScratch() + asmgen.out(""" + cpy P8ZP_SCRATCH_W1+1 + bcc ++ + bne + + cmp P8ZP_SCRATCH_W1 + bcc ++ ++ lda #1 + bne ++ ++ lda #0 ++""") } } else -> return false diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 02c0bbbb5..2af475381 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,7 @@ TODO For next minor release ^^^^^^^^^^^^^^^^^^^^^^ -- finish assignOptimizedComparisonWords() -- find bcc/bcs branches that could be a rol? +- find bcc/bcs + lda branches that could be a rol? - find adc #0 that could be a rol? - try to optimize newexpr a bit more diff --git a/examples/test.p8 b/examples/test.p8 index 8d78adc6a..bff14ebfd 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,50 +6,54 @@ main { sub start() { ubyte[10] envelope_attacks = 99 - - ; signed and unsigned word: + ; signed word: ; > - ; >= - ; < - ; <= - ; expect nope nope yep yep yep - cx16.r0 = $ea30 - cx16.r2 = $ea31 - if (cx16.r0 > cx16.r2) or (envelope_attacks[cx16.r1L]==0) { + ; expect yep nope nope nope yep nope + cx16.r0s = -1000 + cx16.r2s = -999 + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { txt.print("\nyep\n") } else { txt.print("\nnope\n") } - cx16.r0 = $ea31 - cx16.r2 = $ea31 - if (cx16.r0 > cx16.r2) or (envelope_attacks[cx16.r1L]==0) { + cx16.r0s = -999 + cx16.r2s = -999 + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { txt.print("\nyep\n") } else { txt.print("\nnope\n") } - cx16.r0 = $ea32 - cx16.r2 = $ea31 - if (cx16.r0 > cx16.r2) or (envelope_attacks[cx16.r1L]==0) { + cx16.r0s = -998 + cx16.r2s = -999 + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { txt.print("\nyep\n") } else { txt.print("\nnope\n") } - cx16.r0 = $ee30 - cx16.r2 = $ea31 - if (cx16.r0 > cx16.r2) or (envelope_attacks[cx16.r1L]==0) { + cx16.r0s = 0 + cx16.r2s = -999 + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { txt.print("\nyep\n") } else { txt.print("\nnope\n") } - cx16.r0 = $ffff - cx16.r2 = $ee31 - if (cx16.r0 > cx16.r2) or (envelope_attacks[cx16.r1L]==0) { + cx16.r0s = -999 + cx16.r2s = 0 + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { + txt.print("\nyep\n") + } else { + txt.print("\nnope\n") + } + + cx16.r0s = $7fff + cx16.r2s = $7eff + if (cx16.r0s < cx16.r2s) or (envelope_attacks[cx16.r1L]==0) { txt.print("\nyep\n") } else { txt.print("\nnope\n")