diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt index c89d9c9ab..68f8fcf8c 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -540,6 +540,13 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } } } + in ComparisonOperators -> { + if(leftDt in NumericDatatypes && rightDt in NumericDatatypes) { + val rightVal = expr.right.constValue(program)?.number?.toInt() + if(rightVal==0) + return translateComparisonWithZero(expr.left, leftDt, expr.operator) + } + } } if((leftDt in ByteDatatypes && rightDt !in ByteDatatypes) @@ -562,6 +569,69 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } } + private fun translateComparisonWithZero(expr: Expression, dt: DataType, operator: String) { + translateExpressionInternal(expr) + when(operator) { + "==" -> { + when(dt) { + DataType.UBYTE, DataType.BYTE -> asmgen.out(" jsr prog8_lib.equalzero_b") + DataType.UWORD, DataType.WORD -> asmgen.out(" jsr prog8_lib.equalzero_w") + DataType.FLOAT -> asmgen.out(" jsr floats.equal_zero") + else -> throw AssemblyError("wrong dt") + } + } + "!=" -> { + when(dt) { + DataType.UBYTE, DataType.BYTE -> asmgen.out(" jsr prog8_lib.notequalzero_b") + DataType.UWORD, DataType.WORD -> asmgen.out(" jsr prog8_lib.notequalzero_w") + DataType.FLOAT -> asmgen.out(" jsr floats.notequal_zero") + else -> throw AssemblyError("wrong dt") + } + } + "<" -> { + if(dt==DataType.UBYTE || dt==DataType.UWORD) + return translateExpressionInternal(NumericLiteralValue.fromBoolean(false, expr.position)) + when(dt) { + DataType.BYTE -> asmgen.out(" jsr prog8_lib.lesszero_b") + DataType.WORD -> asmgen.out(" jsr prog8_lib.lesszero_w") + DataType.FLOAT -> asmgen.out(" jsr floats.less_zero") + else -> throw AssemblyError("wrong dt") + } + } + ">" -> { + when(dt) { + DataType.UBYTE -> asmgen.out(" jsr prog8_lib.greaterzero_ub") + DataType.BYTE -> asmgen.out(" jsr prog8_lib.greaterzero_sb") + DataType.UWORD -> asmgen.out(" jsr prog8_lib.greaterzero_uw") + DataType.WORD -> asmgen.out(" jsr prog8_lib.greaterzero_sw") + DataType.FLOAT -> asmgen.out(" jsr floats.greater_zero") + else -> throw AssemblyError("wrong dt") + } + } + "<=" -> { + when(dt) { + DataType.UBYTE -> asmgen.out(" jsr prog8_lib.equalzero_b") + DataType.BYTE -> asmgen.out(" jsr prog8_lib.lessequalzeros_b") + DataType.UWORD -> asmgen.out(" jsr prog8_lib.equalzero_w") + DataType.WORD -> asmgen.out(" jsr prog8_lib.lessequalzero_sw") + DataType.FLOAT -> asmgen.out(" jsr floats.lessequal_zero") + else -> throw AssemblyError("wrong dt") + } + } + ">=" -> { + if(dt==DataType.UBYTE || dt==DataType.UWORD) + return translateExpressionInternal(NumericLiteralValue.fromBoolean(true, expr.position)) + when(dt) { + DataType.BYTE -> asmgen.out(" jsr prog8_lib.greaterequalzero_sb") + DataType.WORD -> asmgen.out(" jsr prog8_lib.greaterequalzero_sw") + DataType.FLOAT -> asmgen.out(" jsr floats.greaterequal_zero") + else -> throw AssemblyError("wrong dt") + } + } + else -> throw AssemblyError("invalid comparison operator") + } + } + private fun translateSquared(variable: IdentifierReference, dt: DataType) { val asmVar = asmgen.asmVariableName(variable) when(dt) { diff --git a/compiler/res/prog8lib/c64/floats.asm b/compiler/res/prog8lib/c64/floats.asm index 2e1c02182..f76ffa569 100644 --- a/compiler/res/prog8lib/c64/floats.asm +++ b/compiler/res/prog8lib/c64/floats.asm @@ -678,3 +678,54 @@ set_array_float .proc .pend +equal_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + beq _true + bne _false +_true lda #1 + sta P8ESTACK_LO,x + dex + rts +_false lda #0 + sta P8ESTACK_LO,x + dex + rts + .pend + +notequal_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + bne equal_zero._true + beq equal_zero._false + .pend + +greater_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + beq equal_zero._false + bpl equal_zero._true + jmp equal_zero._false + .pend + +less_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + bmi equal_zero._true + jmp equal_zero._false + .pend + +greaterequal_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + bpl equal_zero._true + jmp equal_zero._false + .pend + +lessequal_zero .proc + jsr floats.pop_float_fac1 + jsr floats.SIGN + beq equal_zero._true + bmi equal_zero._true + jmp equal_zero._false + .pend diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index dffc8dd6e..3b87301af 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -4,6 +4,8 @@ ; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 +orig_stackpointer .byte 0 ; stores the Stack pointer register at program start + read_byte_from_address_on_stack .proc ; -- read the byte from the memory address on the top of the stack, return in A (stack remains unchanged) lda P8ESTACK_LO+1,x @@ -683,8 +685,106 @@ shiftright_b .proc .pend -orig_stackpointer .byte 0 ; stores the Stack pointer register at program start +equalzero_b .proc + lda P8ESTACK_LO+1,x + beq _true + bne _false +_true lda #1 + sta P8ESTACK_LO+1,x + rts +_false lda #0 + sta P8ESTACK_LO+1,x + rts + .pend +equalzero_w .proc + lda P8ESTACK_LO+1,x + ora P8ESTACK_HI+1,x + beq equalzero_b._true + bne equalzero_b._false + .pend + +notequalzero_b .proc + lda P8ESTACK_LO+1,x + beq equalzero_b._false + bne equalzero_b._true + .pend + +notequalzero_w .proc + lda P8ESTACK_LO+1,x + ora P8ESTACK_HI+1,x + beq equalzero_b._false + bne equalzero_b._true + .pend + +lesszero_b .proc + lda P8ESTACK_LO+1,x + bmi equalzero_b._true + jmp equalzero_b._false + .pend + +lesszero_w .proc + lda P8ESTACK_HI+1,x + bmi equalzero_b._true + jmp equalzero_b._false + .pend + +greaterzero_ub .proc + lda P8ESTACK_LO+1,x + bne equalzero_b._true + beq equalzero_b._false + .pend + +greaterzero_sb .proc + lda P8ESTACK_LO+1,x + beq equalzero_b._false + bpl equalzero_b._true + bmi equalzero_b._false + .pend + +greaterzero_uw .proc + lda P8ESTACK_LO+1,x + ora P8ESTACK_HI+1,x + bne equalzero_b._true + beq equalzero_b._false + .pend + +greaterzero_sw .proc + lda P8ESTACK_HI+1,x + bmi equalzero_b._false + ora P8ESTACK_LO+1,x + beq equalzero_b._false + bne equalzero_b._true + .pend + +lessequalzero_sb .proc + lda P8ESTACK_LO+1,x + bmi equalzero_b._true + beq equalzero_b._true + bne equalzero_b._false + .pend + +lessequalzero_sw .proc + lda P8ESTACK_HI+1,x + bmi equalzero_b._true + ora P8ESTACK_LO+1,x + beq equalzero_b._true + bne equalzero_b._false + .pend + +greaterequalzero_sb .proc + lda P8ESTACK_LO+1,x + bpl equalzero_b._true + bmi equalzero_b._false + .pend + +greaterequalzero_sw .proc + lda P8ESTACK_HI+1,x + bmi equalzero_b._false + ora P8ESTACK_LO+1,x + beq equalzero_b._true + bne equalzero_b._false + .pend memcopy16_up .proc diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b79dbd272..410912fde 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,10 +3,10 @@ TODO For next compiler release (7.7) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- why is wormfood 40 bytes larger now since 7.6??? -- optimize codegen of pipe operator to avoid needless assigns to temp var +- optimize (u)word comparison against 0 to use MSB only if possible - copying floats around: do it with a subroutine rather than 5 lda/sta pairs . is slower but floats are very slow already anyway and this should take a lot less program size. +- optimize codegen of pipe operator to avoid needless assigns to temp var Need help with diff --git a/examples/test.p8 b/examples/test.p8 index d2260ff2f..e60c9f116 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,11 +5,37 @@ main { sub start() { - float @shared f1 + byte bb = 0 + word ww = 0 + float fl = 0 - f1 = 1.234 |> addfloat1 |> addfloat2 |> addfloat3 ; TODO fix that the value is actually returned - floats.print_f(f1) - txt.nl() + if fl< 0 { + txt.print("wrong fl\n") + } + fl=-1.111 + if 0>fl or fl==2 { + txt.print("good fl\n") + } + + if ww< 0 { + txt.print("wrong ww\n") + } + if bb<0 { + txt.print("wrong bb\n") + } + bb = -1 + ww = -1111 + if 0>ww or ww==2 { + txt.print("good ww\n") + } + if 0>bb or bb==2 { + txt.print("good bb\n") + } +; float @shared f1 +; +; f1 = 1.234 |> addfloat1 |> addfloat2 |> addfloat3 ; TODO fix that the value is actually returned +; floats.print_f(f1) +; txt.nl() ; 1.234 |> addfloat1 ; |> addfloat2 |> addfloat3 |> floats.print_f ; txt.nl() @@ -21,15 +47,15 @@ main { ; |> txt.print_uw ; txt.nl() - test_stack.test() - ; TODO fix that the value is actually returned (398) and that X register is preserved: - uword @shared uw= 9+3 |> assemblything - |> sin8u - |> add_one - |> times_two - txt.print_uw(uw) - txt.nl() - test_stack.test() +; test_stack.test() +; ; TODO fix that the value is actually returned (398) and that X register is preserved: +; uword @shared uw= 9+3 |> assemblything +; |> sin8u +; |> add_one +; |> times_two +; txt.print_uw(uw) +; txt.nl() +; test_stack.test() } sub addfloat1(float fl) -> float {