From 017ef8a837077c339993004da9b4ccf5c8ca7b13 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 7 Aug 2023 21:20:02 +0200 Subject: [PATCH] optimization of > and <= in expressions --- .../cpu6502/assignment/AssignmentAsmGen.kt | 162 ++++++++++++++---- docs/source/todo.rst | 2 - examples/test.p8 | 15 +- 3 files changed, 134 insertions(+), 45 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 0f402998e..d3ad814bb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -1150,46 +1150,138 @@ internal class AssignmentAsmGen(private val program: PtProgram, } private fun byteLessEquals(expr: PtBinaryExpression, signed: Boolean) { - // TODO optimize: no need to use a temporary variable if the right expression is a literal number or a variable name (or register name) - asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1") - if(signed) - asmgen.out(""" - sec - sbc P8ZP_SCRATCH_B1 - bvc + - eor #$80 -+ bpl + - lda #0 - beq ++ -+ lda #1 + // note: this is the inverse of byteGreater + when(expr.right) { + is PtNumber -> { + val number = (expr.right as PtNumber).number.toInt() + asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed) + if(signed) + asmgen.out(""" + sec + sbc #$number + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 +""") - else - asmgen.out(""" - cmp P8ZP_SCRATCH_B1 - lda #0 - rol a""") + else + asmgen.out(""" + cmp #$number + lda #0 + rol a + eor #1""") + } + is PtIdentifier -> { + val varname = (expr.right as PtIdentifier).name + asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed) + if(signed) + asmgen.out(""" + sec + sbc $varname + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++""") + else + asmgen.out(""" + cmp $varname + lda #0 + rol a + eor #1""") + } + else -> { + // note: left and right operands get reversed here to reduce code size + asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1") + if(signed) + asmgen.out(""" + sec + sbc P8ZP_SCRATCH_B1 + bvc + + eor #$80 ++ bmi + + lda #1 + bne ++ ++ lda #0 ++""") + else + asmgen.out(""" + cmp P8ZP_SCRATCH_B1 + lda #0 + rol a""") + } + } } private fun byteGreater(expr: PtBinaryExpression, signed: Boolean) { - // TODO optimize: no need to use a temporary variable if the right expression is a literal number or a variable name (or register name) - asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1") - if(signed) - asmgen.out(""" - sec - sbc P8ZP_SCRATCH_B1 - bvc + - eor #$80 -+ bmi + - lda #0 - beq ++ -+ lda #1 + // note: this is the inverse of byteLessEqual + when(expr.right) { + is PtNumber -> { + val number = (expr.right as PtNumber).number.toInt() + asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed) + if(signed) + asmgen.out(""" + sec + sbc #$number + bvc + + eor #$80 ++ bmi + + lda #1 + bne ++ ++ lda #0 +""") - else - asmgen.out(""" - cmp P8ZP_SCRATCH_B1 - lda #0 - rol a - eor #1""") + else + asmgen.out(""" + cmp #$number + lda #0 + rol a""") + } + is PtIdentifier -> { + val varname = (expr.right as PtIdentifier).name + asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed) + if(signed) + asmgen.out(""" + sec + sbc $varname + bvc + + eor #$80 ++ bmi + + lda #1 + bne ++ ++ lda #0 ++""") + else + asmgen.out(""" + cmp $varname + lda #0 + rol a""") + } + else -> { + // note: left and right operands get reversed here to reduce code size + asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1") + if(signed) + asmgen.out(""" + sec + sbc P8ZP_SCRATCH_B1 + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++""") + else + asmgen.out(""" + cmp P8ZP_SCRATCH_B1 + lda #0 + rol a + eor #1""") + } + } } private fun byteGreaterEquals(expr: PtBinaryExpression, signed: Boolean) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3923d9a89..95b4d0e22 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,8 +1,6 @@ TODO ==== -- optimize byteLessEquals() and byteGreater() in AssignmentAsmGen. -- in other codegen for comparisons, try to reduce lda #0/lda #1 by rol a using the carry from the cmp if possible. - investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction diff --git a/examples/test.p8 b/examples/test.p8 index 922066853..dd17ac904 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,26 +5,25 @@ main { sub start() { ubyte a = 2 ubyte var1 = 3 - ubyte var2 = 1 - - if a==2 and a>=1 { + ubyte var2 = 10 + if a==2 and a<=10 { a++ } - if a==var1 and a>=var2 { + if a==var1 and a<=var2 { a++ } txt.print_ub(a) ; 4 byte sa = 2 byte svar1 = 3 - byte svar2 = 1 + byte svar2 = 10 - if sa==2 and sa>=1 { + if sa==2 and sa<=10 { sa++ } - if sa==svar1 and sa>=svar2 { + if sa==svar1 and sa<=svar2 { sa++ } - txt.print_b(sa) ; 4 code 287 + txt.print_b(sa) ; 4 code 28f } }