From 15ffd001b92bf5b7150e9d0d11cbf6811ef2a58b Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Sun, 6 Oct 2024 12:42:23 -0400 Subject: [PATCH 1/7] Change HuCC to split all comparisons and tests into 2 stages, the first to set the flags for branching, and the second to convert the flag into a boolean int that can be stored or used in math. This allows the second stage I_BOOLEAN i-code to be removed by the peephole if an integer value is not needed/used. At the moment this just saves one CLY instruction for most tests, but it could be more if the test results return the C flag instead of the Z flag as true or false. --- include/hucc/hucc-codegen.asm | 108 +++++---- src/hucc/code.c | 4 + src/hucc/defs.h | 2 + src/hucc/gen.c | 15 +- src/hucc/optimize.c | 400 +++++++++++++++++++++++++--------- 5 files changed, 361 insertions(+), 168 deletions(-) diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index 955b3cf..ce2688f 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -535,7 +535,7 @@ __bra .macro ; ************** ; boolean test, always followed by a __tst.wr or __not.wr -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __cmp.wt .macro jsr \1 @@ -543,7 +543,7 @@ __cmp.wt .macro ; ************** ; boolean test, always followed by a __tst.wr or __not.wr -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __cmp.ut .macro jsr \1 @@ -551,7 +551,7 @@ __cmp.ut .macro ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __equ.wi .macro eor.l #\1 @@ -560,12 +560,11 @@ __equ.wi .macro beq !true+ !false: lda #-1 !true: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __neq.wi .macro eor.l #\1 @@ -573,35 +572,34 @@ __neq.wi .macro cpy.h #\1 beq !false+ !true: lda #1 -!false: cly +!false: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __equ.ui .macro eor.l #\1 beq !true+ !false: lda #-1 !true: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __neq.ui .macro eor.l #\1 beq !false+ lda #1 -!false: cly +!false: .endm ; ************** ; boolean test, optimized into __not.wr if used before a __tst.wr -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.wr .macro sty __temp @@ -609,19 +607,18 @@ __not.wr .macro beq !+ lda #1 !: eor #1 - cly .endm ; ************** ; boolean test, always output immediately before a __bfalse or __btrue -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.wr .macro sty __temp ora __temp beq !+ lda #1 -!: cly +!: .endm ; ************** @@ -640,7 +637,7 @@ __btrue .macro ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.wp .macro ldy #1 @@ -649,12 +646,11 @@ __not.wp .macro beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.wm .macro lda.l \1 @@ -662,12 +658,11 @@ __not.wm .macro beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.ws .macro ; __STACK lda.l <__stack + \1, x @@ -675,12 +670,11 @@ __not.ws .macro ; __STACK beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.war .macro asl a @@ -690,48 +684,44 @@ __not.war .macro beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.up .macro lda [\1] beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.um .macro lda \1 beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.us .macro ; __STACK lda.l <__stack + \1, x beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.uar .macro tay @@ -739,24 +729,22 @@ __not.uar .macro beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __not.uay .macro lda \1, y beq !+ lda #-1 !: inc a - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.wp .macro ldy #1 @@ -764,36 +752,36 @@ __tst.wp .macro ora [\1] beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.wm .macro lda.l \1 ora.h \1 beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.ws .macro ; __STACK lda.l <__stack + \1, x ora.h <__stack + \1, x beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.war .macro asl a @@ -802,68 +790,68 @@ __tst.war .macro ora.h \1, y beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.up .macro lda [\1] beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.um .macro lda \1 beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.us .macro ; __STACK lda.l <__stack + \1, x beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.uar .macro tay lda \1, y beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tst.uay .macro lda \1, y beq !+ lda #1 -!: cly +!: .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __nand.wi .macro .if ((\1 & $FF00) == 0) @@ -884,12 +872,11 @@ __nand.wi .macro !false: lda #1 .endif !: eor #1 - cly .endm ; ************** ; optimized boolean test -; this MUST set the Z flag for the susequent branches! +; this MUST set the Z flag for the subsequent branches! __tand.wi .macro .if ((\1 & $FF00) == 0) @@ -909,7 +896,14 @@ __tand.wi .macro beq !+ !true: lda #1 .endif -!: cly +!: + .endm + +; ************** +; convert boolean test result into a 16-bit integer + +__bool .macro + cly .endm @@ -3042,20 +3036,18 @@ gt_uw: cmp.l <__stack, x ; Subtract memory from Y:A. bra return_false ; ************** -; boolean result, this MUST set the Z flag for the susequent branches! +; boolean result, this MUST set the Z flag for the subsequent branches! return_true: inx inx ; don't push Y:A, they are thrown away - cly lda #1 ; Also set valid Z flag. rts ; ************** -; boolean result, this MUST set the Z flag for the susequent branches! +; boolean result, this MUST set the Z flag for the subsequent branches! return_false: inx inx ; don't push Y:A, they are thrown away - cly lda #0 ; Also set valid Z flag. rts diff --git a/src/hucc/code.c b/src/hucc/code.c index cafd5ee..63899ec 100644 --- a/src/hucc/code.c +++ b/src/hucc/code.c @@ -687,6 +687,10 @@ void gen_code (INS *tmp) nl(); break; + case I_BOOLEAN: + ol("__bool"); + break; + /* i-codes for loading the primary register */ case I_LD_WI: diff --git a/src/hucc/defs.h b/src/hucc/defs.h index 69856df..915e44d 100644 --- a/src/hucc/defs.h +++ b/src/hucc/defs.h @@ -96,6 +96,8 @@ enum ICODE { X_NAND_WI, X_TAND_WI, + I_BOOLEAN, + /* i-codes for loading the primary register */ I_LD_WI, diff --git a/src/hucc/gen.c b/src/hucc/gen.c index ebaa83a..2ff8b3b 100644 --- a/src/hucc/gen.c +++ b/src/hucc/gen.c @@ -233,6 +233,7 @@ void jump (int label) void testjump (int label, int ft) { out_ins(I_TST_WR, 0, 0); + out_ins(I_BOOLEAN, 0, 0); if (ft) out_ins(I_BTRUE, T_LABEL, label); else @@ -455,15 +456,17 @@ void gcom (void) void gbool (void) { out_ins(I_TST_WR, 0, 0); + out_ins(I_BOOLEAN, 0, 0); } /* - * logical complement of primary register + * boolean logical complement of primary register * */ void glneg (void) { out_ins(I_NOT_WR, 0, 0); + out_ins(I_BOOLEAN, 0, 0); } /* @@ -516,6 +519,7 @@ void geq (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"eq_b"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"eq_w"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -529,6 +533,7 @@ void gne (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"ne_b"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"ne_w"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -542,6 +547,7 @@ void glt (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_sb"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_sw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -555,6 +561,7 @@ void gle (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_sb"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_sw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -568,6 +575,7 @@ void ggt (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_sb"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_sw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -581,6 +589,7 @@ void gge (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_sb"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_sw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -594,6 +603,7 @@ void gult (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_ub"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_uw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -607,6 +617,7 @@ void gule (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_ub"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_uw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -620,6 +631,7 @@ void gugt (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_ub"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_uw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -633,6 +645,7 @@ void guge (int is_byte) out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_ub"); else out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_uw"); + out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } diff --git a/src/hucc/optimize.c b/src/hucc/optimize.c index ddef029..1032e9a 100644 --- a/src/hucc/optimize.c +++ b/src/hucc/optimize.c @@ -131,6 +131,8 @@ unsigned char icode_flags[] = { /* X_NAND_WI */ 0, /* X_TAND_WI */ 0, + /* I_BOOLEAN */ 0, + // i-codes for loading the primary register /* I_LD_WI */ 0, @@ -1198,6 +1200,279 @@ void push_ins (INS *ins) } } + /* then optimize conditional tests, part 1 */ + if (q_nb >= 5) { + /* + * LLnn: --> LLnn: + * __bool __bfalse + * __tst.wr + * __bool + * __bfalse + * + * LLnn: --> LLnn: + * __bool __btrue + * __tst.wr + * __bool + * __btrue + * + * Remove redundant __tst.wr in compound conditionals + * that the compiler generates. + * + * Done before removing the 2nd __bool in a later rule + * so that the redundancy is easier to understand. + */ + if + ((p[0]->ins_code == I_BFALSE || + p[0]->ins_code == I_BTRUE) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == I_TST_WR) && + (p[3]->ins_code == I_BOOLEAN) && + (p[4]->ins_code == I_LABEL) + ) { + *p[3] = *p[0]; + nb = 3; + } + + /* + * LLnn: --> LLnn: + * __bool LLqq: + * __tst.wr __bool + * __bool + * LLqq: + * + * Remove redundant __tst.wr in compound conditionals + * that the compiler generates. + * + * Done before reordering the 2nd __bool in a later rule + * so that the redundancy is easier to understand. + */ + else if + ((p[0]->ins_code == I_BFALSE || + p[0]->ins_code == I_BTRUE || + p[0]->ins_code == I_LABEL) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == I_TST_WR) && + (p[3]->ins_code == I_BOOLEAN) && + (p[4]->ins_code == I_LABEL) + ) { + *p[3] = *p[0]; + *p[2] = *p[1]; + nb = 2; + } + + /* flush queue */ + if (nb) { + q_wr -= nb; + q_nb -= nb; + nb = 0; + + if (q_wr < 0) + q_wr += Q_SIZE; + + /* loop */ + goto lv1_loop; + } + } + + /* then optimize conditional tests, part 2 */ + if (q_nb >= 3) { + /* + * __tst.wr --> __not.wr + * __bool + * __not.wr + */ + if + ((p[0]->ins_code == I_NOT_WR) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == I_TST_WR) + ) { + p[2]->ins_code = I_NOT_WR; + nb = 2; + } + + /* + * __not.wr --> __tst.wr + * __bool + * __not.wr + */ + else if + ((p[0]->ins_code == I_NOT_WR) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == I_NOT_WR) + ) { + p[2]->ins_code = I_TST_WR; + nb = 2; + } + + /* + * __cmp.wt --> __cmp.wt + * __bool + * __tst.wr + * + * __equ.wi --> __equ.wi + * __bool + * __tst.wr + * + * __neq.wi --> __neq.wi + * __bool + * __tst.wr + * + * __not.wr --> __not.wr + * __bool + * __tst.wr + * + * __tst.wr --> __tst.wr + * __bool + * __tst.wr + */ + else if + ((p[0]->ins_code == I_TST_WR) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == I_CMP_WT || + p[2]->ins_code == X_EQU_WI || + p[2]->ins_code == X_NEQ_WI || + p[2]->ins_code == I_NOT_WR || + p[2]->ins_code == I_TST_WR) + ) { + nb = 2; + } + + /* + * __equ.wi --> __neq.wi + * __bool + * __not.wr + * + * __neq.wi --> __equ.wi + * __bool + * __not.wr + */ + else if + ((p[0]->ins_code == I_NOT_WR) && + (p[1]->ins_code == I_BOOLEAN) && + (p[2]->ins_code == X_EQU_WI || + p[2]->ins_code == X_NEQ_WI) + ) { + p[2]->ins_code = (p[2]->ins_code == X_EQU_WI) ? X_NEQ_WI : X_EQU_WI; + nb = 2; + } + + /* flush queue */ + if (nb) { + q_wr -= nb; + q_nb -= nb; + nb = 0; + + if (q_wr < 0) + q_wr += Q_SIZE; + + /* loop */ + goto lv1_loop; + } + } + + /* then optimize conditional tests, part 3 */ + if (q_nb >= 2) { + /* + * __bool --> LLnn: + * LLnn: __bool + * + * Delay boolean conversion until the end of a list of labels. + * + * N.B. This optimization should be done before the X_TST_WM optimization! + */ + if + ((p[0]->ins_code == I_LABEL) && + (p[1]->ins_code == I_BOOLEAN) + ) { + *p[1] = *p[0]; + p[0]->ins_code = I_BOOLEAN; + p[0]->ins_type = 0; + p[0]->ins_data = 0; + /* no instructions removed, just loop */ + goto lv1_loop; + } + + /* + * __bool --> __bfalse + * __bfalse + * + * __bool --> __btrue + * __btrue + * + * __bool --> __bool + * __bool + * + * These remove redundant conversions of a flag into a boolean. + * + * N.B. This optimization should be done before the X_TST_WM optimization! + */ + else if + ((p[1]->ins_code == I_BOOLEAN) && + (p[0]->ins_code == I_BFALSE || + p[0]->ins_code == I_BTRUE || + p[0]->ins_code == I_BOOLEAN) + ) { + *p[1] = *p[0]; + nb = 1; + } + + /* + * __bra LLaa --> __bra LLaa + * __bra LLbb + */ + else if + ((p[0]->ins_code == I_BRA) && + (p[1]->ins_code == I_BRA) + ) { + nb = 1; + } + + /* + * LLaa: LLaa .alias LLbb + * __bra LLbb --> __bra LLbb + */ + else if + ((p[0]->ins_code == I_BRA) && + (p[1]->ins_code == I_LABEL) + ) { + int i = 1; + do { + if (p[i]->ins_data != p[0]->ins_data) { + p[i]->ins_code = I_ALIAS; + p[i]->imm_type = T_VALUE; + p[i]->imm_data = p[0]->ins_data; + } + } while (++i < q_nb && i < 10 && p[i]->ins_code == I_LABEL); + } + + /* + * __bra LLaa --> LLaa: + * LLaa: + */ + else if + ((p[0]->ins_code == I_LABEL) && + (p[1]->ins_code == I_BRA) && + (p[1]->ins_type == T_LABEL) && + (p[0]->ins_data == p[1]->ins_data) + ) { + *p[1] = *p[0]; + nb = 1; + } + + /* flush queue */ + if (nb) { + q_wr -= nb; + q_nb -= nb; + nb = 0; + + if (q_wr < 0) + q_wr += Q_SIZE; + + /* loop */ + goto lv1_loop; + } + } + /* 6-instruction patterns */ if (q_nb >= 6) { /* @@ -1733,59 +2008,60 @@ void push_ins (INS *ins) /* * __ld.{w/b/u}p symbol --> __not.{w/u}p symbol * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}p symbol --> __tst.{w/u}p symbol * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}m symbol --> __not.{w/u}m symbol * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}m symbol --> __tst.{w/u}m symbol * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}s symbol --> __not.{w/u}s symbol * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}s symbol --> __tst.{w/u}s symbol * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}ar symbol --> __not.{w/u}ar symbol * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{w/b/u}ar symbol --> __tst.{w/u}ar symbol * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{b/u}ay symbol --> __not.uay symbol * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __ld.{b/u}ay symbol --> __tst.uay symbol * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __and.{w/u}i n --> __tand.wi n * __tst.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * __and.{w/u}i n --> __nand.wi n * __not.wr not(__tst.wr or __not.wr) - * not(__tst.wr or __not.wr) + * not(__bool or __tst.wr or __not.wr) * * N.B. This deliberately tests for the i-code after * the target I_TST_WR or I_NOT_WR in order to delay - * the match until after merging the dupliated tests + * the match until after merging the duplicate tests * that the code-generator often emits. */ else if - ((p[0]->ins_code != I_TST_WR) && + ((p[0]->ins_code != I_BOOLEAN) && + (p[0]->ins_code != I_TST_WR) && (p[0]->ins_code != I_NOT_WR) && (p[1]->ins_code == I_TST_WR || p[1]->ins_code == I_NOT_WR) && @@ -1925,49 +2201,6 @@ void push_ins (INS *ins) /* 2-instruction patterns */ if (q_nb >= 2) { - /* - * __bra LLaa --> __bra LLaa - * __bra LLbb - */ - if - ((p[0]->ins_code == I_BRA) && - (p[1]->ins_code == I_BRA) - ) { - nb = 1; - } - - /* - * LLaa: LLaa .alias LLbb - * __bra LLbb --> __bra LLbb - */ - if - ((p[0]->ins_code == I_BRA) && - (p[1]->ins_code == I_LABEL) - ) { - int i = 1; - do { - if (p[i]->ins_data != p[0]->ins_data) { - p[i]->ins_code = I_ALIAS; - p[i]->imm_type = T_VALUE; - p[i]->imm_data = p[0]->ins_data; - } - } while (++i < q_nb && i < 10 && p[i]->ins_code == I_LABEL); - } - - /* - * __bra LLaa --> LLaa: - * LLaa: - */ - else if - ((p[0]->ins_code == I_LABEL) && - (p[1]->ins_code == I_BRA) && - (p[1]->ins_type == T_LABEL) && - (p[0]->ins_data == p[1]->ins_data) - ) { - *p[1] = *p[0]; - nb = 1; - } - /* * __ld.{b/u}p __ptr --> __ld.{b/u}p __ptr * __switch.wr __switch.ur @@ -1981,7 +2214,7 @@ void push_ins (INS *ins) * __ld.{b/u}ar array --> __ld.{b/u}ar array * __switch.wr __switch.ur */ - else if + if ((p[0]->ins_code == I_SWITCH_WR) && (p[1]->ins_code == I_LD_BP || p[1]->ins_code == I_LD_UP || @@ -2021,57 +2254,6 @@ void push_ins (INS *ins) nb = 1; } - /* - * __tst.wr --> __not.wr - * __not.wr - */ - else if - ((p[0]->ins_code == I_NOT_WR) && - (p[1]->ins_code == I_TST_WR) - ) { - p[1]->ins_code = I_NOT_WR; - nb = 1; - } - - /* - * __not.wr --> __tst.wr - * __not.wr - */ - else if - ((p[0]->ins_code == I_NOT_WR) && - (p[1]->ins_code == I_NOT_WR) - ) { - p[1]->ins_code = I_TST_WR; - nb = 1; - } - - /* - * __cmp.wt --> __cmp.wt - * __tst.wr - * - * __not.wr --> __not.wr - * __tst.wr - * - * __tst.wr --> __tst.wr - * __tst.wr - * - * This removes redundant tests in compound conditionals ... - * - * LLnn: --> LLnn: - * __tst.wr - */ - else if - ((p[0]->ins_code == I_TST_WR) && - (p[1]->ins_code == I_CMP_WT || - p[1]->ins_code == X_EQU_WI || - p[1]->ins_code == X_NEQ_WI || - p[1]->ins_code == I_NOT_WR || - p[1]->ins_code == I_TST_WR || - p[1]->ins_code == I_LABEL) - ) { - nb = 1; - } - /* * __modsp i --> __modsp (i + j) * __modsp j From 2a85906c39556abf43d6f88562c2b5f0ed4ebff4 Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Sun, 6 Oct 2024 12:56:44 -0400 Subject: [PATCH 2/7] Update stack-local symbol output to the use the new C-style /* */ comments for the local name rather than the `;` style. Seperate the /* */ comment a bit further away from the compiler-generated name so that it is a bit easier to read. --- src/hucc/io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hucc/io.c b/src/hucc/io.c index c50475e..d9707c0 100644 --- a/src/hucc/io.c +++ b/src/hucc/io.c @@ -466,7 +466,7 @@ void outsymbol (SYMBOL *ptr) outstr(ptr->name); } if (ptr->linked) { - outstr(" /* "); + outstr(" /* "); outstr(ptr->linked->name); outstr(" */"); } @@ -641,7 +641,8 @@ void outstr (const char *ptr) void outlocal (SYMBOL *ptr) { if (ptr) { - outstr(" ; "); + outstr(" /* "); outstr(ptr->name); + outstr(" */"); } } From dff7ec20e93b334ee58e1a51d8229464b36a5445 Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Tue, 8 Oct 2024 13:23:57 -0400 Subject: [PATCH 3/7] Add SGX_PARALLAX flag setting to core-config.inc and hucc-config.inc and correct the VPC initialization comments in vdc.asm --- include/hucc/core-config.inc | 30 ++++++++++++++++++++++++++++-- include/hucc/hucc-config.inc | 30 ++++++++++++++++++++++++++++-- include/hucc/vdc.asm | 35 +++++++++++++++++------------------ 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/include/hucc/core-config.inc b/include/hucc/core-config.inc index 4841e0c..cf57592 100644 --- a/include/hucc/core-config.inc +++ b/include/hucc/core-config.inc @@ -120,15 +120,41 @@ SUPPORT_TED2 = 0 ; (0 or 1) .endif ; -; Support development for the SuperGrafx? +; Support development for the SuperGRAFX? ; -; This enables SuperGrafx support in certain library functions. +; This enables SuperGRAFX support in certain library functions. ; .ifndef SUPPORT_SGX SUPPORT_SGX = 0 ; (0 or 1) .endif +; +; Choose SuperGRAFX VPC initialization mode. +; +; SGX_PARALLAX=0 (useful when VDC #1 is a fullscreen HUD) +; +; FRONT +; SP1 = VDC #1 (pce) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG2 = VDC #2 (sgx) background pixels +; BACK +; +; SGX_PARALLAX=1 +; +; FRONT +; SP1 = VDC #1 (pce) sprite pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; BG2 = VDC #2 (sgx) background pixels +; BACK +; + + .ifndef SGX_PARALLAX +SGX_PARALLAX = 1 ; The most common default. + .endif + ; ; Support development for the ArcadeCard? ; diff --git a/include/hucc/hucc-config.inc b/include/hucc/hucc-config.inc index dab1f2b..1416637 100644 --- a/include/hucc/hucc-config.inc +++ b/include/hucc/hucc-config.inc @@ -100,9 +100,9 @@ SUPPORT_TED2 = 0 ; (0 or 1) .endif ; -; Support development for the SuperGrafx? +; Support development for the SuperGRAFX? ; -; This enables SuperGrafx support in certain library functions. +; This enables SuperGRAFX support in certain library functions. ; .ifndef SUPPORT_SGX @@ -113,6 +113,32 @@ SUPPORT_SGX = 0 ; (0 or 1) .endif .endif +; +; Choose SuperGRAFX VPC initialization mode. +; +; SGX_PARALLAX=0 (useful when VDC #1 is a fullscreen HUD) +; +; FRONT +; SP1 = VDC #1 (pce) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG2 = VDC #2 (sgx) background pixels +; BACK +; +; SGX_PARALLAX=1 +; +; FRONT +; SP1 = VDC #1 (pce) sprite pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; BG2 = VDC #2 (sgx) background pixels +; BACK +; + + .ifndef SGX_PARALLAX +SGX_PARALLAX = 1 ; The most common default. + .endif + ; ; Support development for the ArcadeCard? ; diff --git a/include/hucc/vdc.asm b/include/hucc/vdc.asm index 798d3af..24fbc1b 100644 --- a/include/hucc/vdc.asm +++ b/include/hucc/vdc.asm @@ -337,6 +337,11 @@ set_mode_vdc .proc ; ; HuC6202 VIDEO PRIORITY CONTROLLER (huge thanks to Charles MacDonald!) ; +; The VPC has no access to sprite priority data, it can only sort pixels +; based upon which VDC and whether they are "sprite" or "background". +; +; This can sometimes lead to unexpected results with low-priority sprites. +; ; VPC registers $0008 and $0009 make up four 4-bit values that define the ; enabled layers and priority setting for the four possible window areas. ; @@ -355,34 +360,28 @@ set_mode_vdc .proc ; Priority Setting 0b00xx: (useful when VDC #1 is a fullscreen HUD) ; ; FRONT -; SP1'= VDC #1 high priority sprites -; BG1 = VDC #1 background -; SP1 = VDC #1 low priority sprites -; SP2'= VDC #2 high priority sprites -; BG2 = VDC #2 background -; SP2 = VDC #2 low priority sprites +; SP1 = VDC #1 (pce) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG2 = VDC #2 (sgx) background pixels ; BACK ; ; Priority Setting 0b01xx: (useful for parallax backgrounds) ; ; FRONT -; SP1'= VDC #1 high priority sprites -; SP2'= VDC #2 high priority sprites -; BG1 = VDC #1 background -; SP1 = VDC #1 low priority sprites -; BG2 = VDC #2 background -; SP2 = VDC #2 low priority sprites +; SP1 = VDC #1 (pce) sprite pixels +; SP2 = VDC #2 (sgx) sprite pixels +; BG1 = VDC #1 (pce) background pixels +; BG2 = VDC #2 (sgx) background pixels ; BACK ; ; Priority Setting 0b10xx: (only useful for special effects) ; ; FRONT -; BG1 = VDC #1 background (with holes for sprites) -; SP2'= VDC #2 high priority sprites -; BG2 = VDC #2 background -; SP2 = VDC #2 low priority sprites -; SP1'= VDC #1 high priority sprites -; SP1 = VDC #1 low priority sprites +; BG1 = VDC #1 (pce) background pixels (transparent where sprites) +; BG2 = VDC #2 (sgx) background pixels +; SP1 = VDC #1 (pce) sprite pixels +; SP2 = VDC #2 (sgx) sprite pixels ; BACK .if SUPPORT_SGX From d532a1fee519d45d99377c05c38838bbbb30666c Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Wed, 9 Oct 2024 12:49:47 -0400 Subject: [PATCH 4/7] Change how HuCC generates the code for C comparisons. Uli's attempt to generate byte comparisons has been completely removed from the code-generation section of the compiler because the SmallC expression code does not propagate operand size information. Remove the last of the T_LIB usage of embedded comparison name strings, and use integer enums instead which make it easier to optimize comparison-ops. Teach the peephole optimizer how to convert the compare-with-integer operations into a new i-code that generates faster inline code. Further optimize unsigned char compare-with-integer operations when they can be detected. --- include/hucc/hucc-codegen.asm | 404 +++++++++++++++++++++++----------- src/hucc/code.c | 62 +++--- src/hucc/code.h | 1 + src/hucc/defs.h | 33 ++- src/hucc/expr.c | 30 +-- src/hucc/gen.c | 71 ++---- src/hucc/gen.h | 20 +- src/hucc/optimize.c | 147 ++++++++----- 8 files changed, 470 insertions(+), 298 deletions(-) diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index ce2688f..c497850 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -552,8 +552,9 @@ __cmp.ut .macro ; ************** ; optimized boolean test ; this MUST set the Z flag for the subsequent branches! +; A is true (1) if Y:A == integer-value, else false (0) -__equ.wi .macro +__equ_w.wi .macro eor.l #\1 bne !false+ cpy.h #\1 @@ -565,8 +566,9 @@ __equ.wi .macro ; ************** ; optimized boolean test ; this MUST set the Z flag for the subsequent branches! +; A is true (1) if Y:A != integer-value, else false (0) -__neq.wi .macro +__neq_w.wi .macro eor.l #\1 bne !true+ cpy.h #\1 @@ -575,12 +577,137 @@ __neq.wi .macro !false: .endm +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A < integer-value, else false (0) + +__slt_w.wi .macro + cmp.l #\1 ; Subtract integer from Y:A. + tya + sbc.h #\1 + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A < integer (signed). + cla ; +ve if Y:A >= integer (signed). + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A <= integer-value, else false (0) + +__sle_w.wi .macro + clc ; Subtract integer+1 from Y:A. + sbc.l #\1 + tya + sbc.h #\1 + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A <= integer (signed). + cla ; +ve if Y:A > integer (signed). + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A > integer-value, else false (0) + +__sgt_w.wi .macro + clc ; Subtract integer+1 from Y:A. + sbc.l #\1 + tya + sbc.h #\1 + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A > integer (signed). + cla ; -ve if Y:A <= integer (signed). + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A >= integer-value, else false (0) + +__sge_w.wi .macro + cmp.l #\1 ; Subtract integer from Y:A. + tya + sbc.h #\1 + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A >= integer (signed). + cla ; -ve if Y:A < integer (signed). + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A < integer-value, else false (0) + +__ult_w.wi .macro + cmp.l #\1 ; Subtract integer from Y:A. + tya + sbc.h #\1 + cla ; CC if Y:A < integer. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A <= integer-value, else false (0) + +__ule_w.wi .macro + clc ; Subtract integer+1 from Y:A. + sbc.l #\1 + tya + sbc.h #\1 + cla ; CC if Y:A <= integer. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A > integer-value, else false (0) + +__ugt_w.wi .macro + clc ; Subtract integer+1 from Y:A. + sbc.l #\1 + tya + sbc.h #\1 + cla ; CS if Y:A > integer. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if Y:A >= integer-value, else false (0) + +__uge_w.wi .macro + cmp.l #\1 ; Subtract integer from Y:A. + tya + sbc.h #\1 + cla ; CS if Y:A >= integer. + rol a + .endm + ; ************** ; optimized boolean test ; this MUST set the Z flag for the subsequent branches! +; A is true (1) if A == integer-value, else false (0) -__equ.ui .macro - eor.l #\1 +__equ_b.uiq .macro + eor #\1 beq !true+ !false: lda #-1 !true: inc a @@ -589,14 +716,125 @@ __equ.ui .macro ; ************** ; optimized boolean test ; this MUST set the Z flag for the subsequent branches! +; A is true (1) if A != integer-value, else false (0) -__neq.ui .macro - eor.l #\1 +__neq_b.uiq .macro + eor #\1 beq !false+ lda #1 !false: .endm +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A < integer-value, else false (0) + +__slt_b.biq .macro + sec ; Subtract integer from A. + sbc #\1 + bvc !+ + eor #$80 +!: asl a ; -ve if A < integer (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A <= integer-value, else false (0) + +__sle_b.biq .macro + clc ; Subtract integer+1 from A. + sbc #\1 + bvc !+ + eor #$80 +!: asl a ; -ve if A <= integer (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A > integer-value, else false (0) + +__sgt_b.biq .macro + clc ; Subtract integer+1 from A. + sbc.l #\1 + bvc !+ + eor #$80 +!: asl a ; +ve if A > integer (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A >= integer-value, else false (0) + +__sge_b.biq .macro + sec ; Subtract integer from A. + sbc #\1 + bvc !+ + eor #$80 +!: asl a ; +ve if A >= integer (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A < integer-value, else false (0) + +__ult_b.uiq .macro + cmp #\1 ; Subtract integer from A. + cla ; CC if A < integer. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A <= integer-value, else false (0) + +__ule_b.uiq .macro + clc ; Subtract integer+1 from A. + sbc #\1 + cla ; CC if A <= integer. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A > integer-value, else false (0) + +__ugt_b.uiq .macro + clc ; Subtract integer+1 from A. + sbc #\1 + cla ; CS if A > integer. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; this MUST set the Z flag for the susequent branches! +; A is true (1) if A >= integer-value, else false (0) + +__uge_b.uiq .macro + cmp #\1 ; Subtract integer from A. + cla ; CS if A >= integer. + rol a + .endm + ; ************** ; boolean test, optimized into __not.wr if used before a __tst.wr ; this MUST set the Z flag for the subsequent branches! @@ -2930,9 +3168,9 @@ __ldd_s_b .macro ; __STACK ; *************************************************************************** ; ************** -; Y:A is true if stacked-value == Y:A, else false +; A is true (1) if stacked-value == Y:A, else false (0) -eq_w: cmp.l <__stack, x +equ_w: cmp.l <__stack, x bne return_false say cmp.h <__stack, x @@ -2941,9 +3179,9 @@ eq_w: cmp.l <__stack, x bra return_true ; ************** -; Y:A is true if stacked-value != Y:A, else false +; A is true (1) if stacked-value != Y:A, else false (0) -ne_w: cmp.l <__stack, x +neq_w: cmp.l <__stack, x bne return_true say cmp.h <__stack, x @@ -2952,9 +3190,9 @@ ne_w: cmp.l <__stack, x bra return_false ; ************** -; Y:A is true if stacked-value < Y:A, else false +; A is true (1) if stacked-value < Y:A, else false (0) -lt_sw: clc ; Subtract memory+1 from Y:A. +slt_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x tya sbc.h <__stack, x @@ -2964,43 +3202,43 @@ lt_sw: clc ; Subtract memory+1 from Y:A. bra return_false ; -ve if Y:A <= memory (signed). ; ************** -; Y:A is true if stacked-value >= Y:A, else false +; A is true (1) if stacked-value <= Y:A, else false (0) -ge_sw: clc ; Subtract memory+1 from Y:A. - sbc.l <__stack, x +sle_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya sbc.h <__stack, x bvc !+ eor #$80 -!: bmi return_true ; -ve if Y:A <= memory (signed). - bra return_false ; +ve if Y:A > memory (signed). +!: bpl return_true ; +ve if Y:A >= memory (signed). + bra return_false ; -ve if Y:A < memory (signed). ; ************** -; Y:A is true if stacked-value <= Y:A, else false +; A is true (1) if stacked-value > Y:A, else false (0) -le_sw: cmp.l <__stack, x ; Subtract memory from Y:A. +sgt_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya sbc.h <__stack, x bvc !+ eor #$80 -!: bpl return_true ; +ve if Y:A >= memory (signed). - bra return_false ; -ve if Y:A < memory (signed). +!: bmi return_true ; -ve if Y:A < memory (signed). + bra return_false ; +ve if Y:A >= memory (signed). ; ************** -; Y:A is true if stacked-value > Y:A, else false +; A is true (1) if stacked-value >= Y:A, else false (0) -gt_sw: cmp.l <__stack, x ; Subtract memory from Y:A. +sge_w: clc ; Subtract memory+1 from Y:A. + sbc.l <__stack, x tya sbc.h <__stack, x bvc !+ eor #$80 -!: bmi return_true ; -ve if Y:A < memory (signed). - bra return_false ; +ve if Y:A >= memory (signed). +!: bmi return_true ; -ve if Y:A <= memory (signed). + bra return_false ; +ve if Y:A > memory (signed). ; ************** -; Y:A is true if stacked-value < Y:A, else false +; A is true (1) if stacked-value < Y:A, else false (0) -lt_uw: clc ; Subtract memory+1 from Y:A. +ult_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x tya sbc.h <__stack, x @@ -3008,31 +3246,31 @@ lt_uw: clc ; Subtract memory+1 from Y:A. bra return_false ; ************** -; Y:A is true if stacked-value >= Y:A, else false +; A is true (1) if stacked-value <= Y:A, else false (0) -ge_uw: clc ; Subtract memory+1 from Y:A. - sbc.l <__stack, x +ule_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya sbc.h <__stack, x - bcc return_true ; CC if Y:A <= memory. + bcs return_true ; CS if Y:A >= memory. bra return_false ; ************** -; Y:A is true if stacked-value <= Y:A, else false +; A is true (1) if stacked-value > Y:A, else false (0) -le_uw: cmp.l <__stack, x ; Subtract memory from Y:A. +ugt_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya sbc.h <__stack, x - bcs return_true ; CS if Y:A >= memory. + bcc return_true ; CC if Y:A < memory. bra return_false ; ************** -; Y:A is true if stacked-value > Y:A, else false +; A is true (1) if stacked-value >= Y:A, else false (0) -gt_uw: cmp.l <__stack, x ; Subtract memory from Y:A. +uge_w: clc ; Subtract memory+1 from Y:A. + sbc.l <__stack, x tya sbc.h <__stack, x - bcc return_true ; CC if Y:A < memory. + bcc return_true ; CC if Y:A <= memory. bra return_false ; ************** @@ -3053,98 +3291,6 @@ return_false: inx -; *************************************************************************** -; *************************************************************************** -; subroutines for comparison tests with signed and unsigned bytes -; *************************************************************************** -; *************************************************************************** - -; ************** -; Y:A is true if stacked-value == Y:A, else false - -eq_b: cmp <__stack, x - bne return_false - bra return_true - -; ************** -; Y:A is true if stacked-value != Y:A, else false - -ne_b: cmp <__stack, x - bne return_true - bra return_false - -; ************** -; Y:A is true if stacked-value < Y:A, else false - -lt_sb: clc ; Subtract memory+1 from A. - sbc.l <__stack, x - bvc !+ - eor #$80 -!: bpl return_true ; +ve if A > memory (signed). - bra return_false ; -ve if A <= memory (signed). - -; ************** -; Y:A is true if stacked-value >= Y:A, else false - -ge_sb: clc ; Subtract memory+1 from A. - sbc.l <__stack, x - bvc !+ - eor #$80 -!: bmi return_true ; -ve if A <= memory (signed). - bra return_false ; +ve if A > memory (signed). - -; ************** -; Y:A is true if stacked-value <= Y:A, else false - -le_sb: sec ; Subtract memory from A. - sbc.l <__stack, x ; Cannot use a "cmp" as it - bvc !+ ; does not set the V flag! - eor #$80 -!: bpl return_true ; +ve if A >= memory (signed). - bra return_false ; -ve if A < memory (signed). - -; ************** -; Y:A is true if stacked-value > Y:A, else false - -gt_sb: sec ; Subtract memory from A. - sbc.l <__stack, x ; Cannot use a "cmp" as it - bvc !+ ; does not set the V flag! - eor #$80 -!: bmi return_true ; -ve if A < memory (signed). - bra return_false ; +ve if A >= memory (signed). - -; ************** -; Y:A is true if stacked-value < Y:A, else false - -lt_ub: clc ; Subtract memory+1 from A. - sbc.l <__stack, x - bcs return_true ; CS if A > memory. - bra return_false - -; ************** -; Y:A is true if stacked-value >= Y:A, else false - -ge_ub: clc ; Subtract memory+1 from A. - sbc.l <__stack, x - bcc return_true ; CC if A <= memory. - bra return_false - -; ************** -; Y:A is true if stacked-value <= Y:A, else false - -le_ub: cmp.l <__stack, x ; Subtract memory from A. - bcs return_true ; CS if Y:A >= memory. - bra return_false - -; ************** -; Y:A is true if stacked-value > Y:A, else false - -gt_ub: cmp.l <__stack, x ; Subtract memory from A. - bcc return_true ; CC if A < memory. - bra return_false - - - ; *************************************************************************** ; *************************************************************************** ; subroutines for logical and arithmetic shifts by a constant amount diff --git a/src/hucc/code.c b/src/hucc/code.c index 63899ec..0fa8662 100644 --- a/src/hucc/code.c +++ b/src/hucc/code.c @@ -24,6 +24,20 @@ int segment; /* externs */ extern int arg_stack_flag; +/* convert comparison operation to a string */ +const char * compare2str [] = { + "equ", // CMP_EQU + "neq", // CMP_NEQ + "slt", // CMP_SLT + "sle", // CMP_SLE + "sgt", // CMP_SGT + "sge", // CMP_SGE + "ult", // CMP_ULT + "ule", // CMP_ULE + "ugt", // CMP_UGT + "uge" // CMP_UGE +}; + /* * print all assembler info before any code is generated * @@ -157,6 +171,17 @@ void out_ins_sym (int code, int type, intptr_t data, SYMBOL *sym) gen_ins(&tmp); } +void out_ins_cmp (int code, int type) +{ + INS tmp; + + memset(&tmp, 0, sizeof(INS)); + + tmp.ins_code = code; + tmp.cmp_type = type; + gen_ins(&tmp); +} + void gen_ins (INS *tmp) { if (optimize) @@ -507,40 +532,23 @@ void gen_code (INS *tmp) case I_CMP_WT: ot("__cmp.wt\t"); - - switch (type) { - case T_SYMBOL: - outsymbol((SYMBOL *)data); - break; - case T_LIB: - outstr((const char *)data); - break; - } - nl(); - break; - - case I_CMP_UT: - ot("__cmp.ut\t"); - - switch (type) { - case T_SYMBOL: - outsymbol((SYMBOL *)data); - break; - case T_LIB: - outstr((const char *)data); - break; - } + outstr(compare2str[tmp->cmp_type]); + outstr("_w"); nl(); break; - case X_EQU_WI: - ot("__equ.wi\t"); + case X_CMP_WI: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_w.wi\t"); out_type(type, data); nl(); break; - case X_NEQ_WI: - ot("__neq.wi\t"); + case X_CMP_UIQ: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_b.uiq\t"); out_type(type, data); nl(); break; diff --git a/src/hucc/code.h b/src/hucc/code.h index c95fba2..5f62b6b 100644 --- a/src/hucc/code.h +++ b/src/hucc/code.h @@ -21,6 +21,7 @@ void defword (void); void out_ins (int code, int type, intptr_t data); void out_ins_ex (int code, int type, intptr_t data, int imm_type, intptr_t imm_data); void out_ins_sym (int code, int type, intptr_t data, SYMBOL *sym); +void out_ins_cmp (int code, int type); void gen_ins (INS *tmp); void gen_code (INS *tmp); diff --git a/src/hucc/defs.h b/src/hucc/defs.h index 915e44d..4d29e08 100644 --- a/src/hucc/defs.h +++ b/src/hucc/defs.h @@ -66,9 +66,8 @@ enum ICODE { I_BRA, I_DEF, I_CMP_WT, - I_CMP_UT, - X_EQU_WI, - X_NEQ_WI, + X_CMP_WI, + X_CMP_UIQ, I_NOT_WR, I_TST_WR, I_BFALSE, @@ -325,6 +324,22 @@ enum ICODE { X_LDD_S_B }; +/* + * boolean comparison operations + */ +enum ICOMPARE { + CMP_EQU, + CMP_NEQ, + CMP_SLT, + CMP_SLE, + CMP_SGT, + CMP_SGE, + CMP_ULT, + CMP_ULE, + CMP_UGT, + CMP_UGE +}; + /* * INTSIZE is the size of an integer in the target machine * BYTEOFF is the offset of an byte within an integer on the @@ -345,12 +360,11 @@ enum ICODE { #define T_PTR 4 #define T_STACK 5 #define T_STRING 6 -#define T_LIB 7 -#define T_SIZE 8 -#define T_BANK 9 -#define T_VRAM 10 -#define T_PAL 11 -#define T_LITERAL 12 +#define T_SIZE 7 +#define T_BANK 8 +#define T_VRAM 9 +#define T_PAL 10 +#define T_LITERAL 11 #define FOREVER for (;;) #define FALSE 0 @@ -539,6 +553,7 @@ struct macro { typedef struct { enum ICODE ins_code; + enum ICOMPARE cmp_type; int ins_type; intptr_t ins_data; int imm_type; diff --git a/src/hucc/expr.c b/src/hucc/expr.c index 36b4b38..957a885 100644 --- a/src/hucc/expr.c +++ b/src/hucc/expr.c @@ -86,16 +86,6 @@ static int is_ptrptr (LVALUE *lval) return (s && (s->ptr_order > 1 || (s->identity == ARRAY && s->ptr_order > 0))); } -static int is_byte (LVALUE *lval) -{ -#if 0 // Byte comparisons are broken, disable them for now. - if (lval->symbol && !lval->ptr_type && - (lval->symbol->sym_type == CCHAR || lval->symbol->sym_type == CUCHAR)) - return (1); -#endif - return (0); -} - static void gen_scale_right (LVALUE *lval, LVALUE *lval2) { if (dbltest(lval, lval2)) { @@ -398,13 +388,13 @@ int heir5 (LVALUE *lval, int comma) gpush(); if (heir6(lval2, comma)) rvalue(lval2); - geq(is_byte(lval) && is_byte(lval2)); + geq(); } else if (match("!=")) { gpush(); if (heir6(lval2, comma)) rvalue(lval2); - gne(is_byte(lval) && is_byte(lval2)); + gne(); } else return (0); @@ -443,10 +433,10 @@ int heir6 (LVALUE *lval, int comma) is_unsigned(lval) || is_unsigned(lval2) ) { - gule(is_byte(lval) && is_byte(lval2)); + gule(); continue; } - gle(is_byte(lval) && is_byte(lval2)); + gle(); } else if (match(">=")) { gpush(); @@ -456,10 +446,10 @@ int heir6 (LVALUE *lval, int comma) is_unsigned(lval) || is_unsigned(lval2) ) { - guge(is_byte(lval) && is_byte(lval2)); + guge(); continue; } - gge(is_byte(lval) && is_byte(lval2)); + gge(); } else if ((sstreq("<")) && !sstreq("<<")) { @@ -471,10 +461,10 @@ int heir6 (LVALUE *lval, int comma) is_unsigned(lval) || is_unsigned(lval2) ) { - gult(is_byte(lval) && is_byte(lval2)); + gult(); continue; } - glt(is_byte(lval) && is_byte(lval2)); + glt(); } else if ((sstreq(">")) && !sstreq(">>")) { @@ -486,10 +476,10 @@ int heir6 (LVALUE *lval, int comma) is_unsigned(lval) || is_unsigned(lval2) ) { - gugt(is_byte(lval) && is_byte(lval2)); + gugt(); continue; } - ggt(is_byte(lval) && is_byte(lval2)); + ggt(); } else return (0); diff --git a/src/hucc/gen.c b/src/hucc/gen.c index 2ff8b3b..184de91 100644 --- a/src/hucc/gen.c +++ b/src/hucc/gen.c @@ -513,12 +513,10 @@ void gdec (LVALUE *lval) * equal * */ -void geq (int is_byte) + +void geq (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"eq_b"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"eq_w"); + out_ins_cmp(I_CMP_WT, CMP_EQU); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -527,12 +525,9 @@ void geq (int is_byte) * not equal * */ -void gne (int is_byte) +void gne (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ne_b"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ne_w"); + out_ins_cmp(I_CMP_WT, CMP_NEQ); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -541,12 +536,9 @@ void gne (int is_byte) * less than (signed) * */ -void glt (int is_byte) +void glt (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_sb"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_sw"); + out_ins_cmp(I_CMP_WT, CMP_SLT); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -555,12 +547,9 @@ void glt (int is_byte) * less than or equal (signed) * */ -void gle (int is_byte) +void gle (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_sb"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_sw"); + out_ins_cmp(I_CMP_WT, CMP_SLE); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -569,12 +558,9 @@ void gle (int is_byte) * greater than (signed) * */ -void ggt (int is_byte) +void ggt (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_sb"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_sw"); + out_ins_cmp(I_CMP_WT, CMP_SGT); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -583,12 +569,9 @@ void ggt (int is_byte) * greater than or equal (signed) * */ -void gge (int is_byte) +void gge (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_sb"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_sw"); + out_ins_cmp(I_CMP_WT, CMP_SGE); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -597,12 +580,9 @@ void gge (int is_byte) * less than (unsigned) * */ -void gult (int is_byte) +void gult (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_ub"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"lt_uw"); + out_ins_cmp(I_CMP_WT, CMP_ULT); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -611,12 +591,9 @@ void gult (int is_byte) * less than or equal (unsigned) * */ -void gule (int is_byte) +void gule (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_ub"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"le_uw"); + out_ins_cmp(I_CMP_WT, CMP_ULE); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -625,12 +602,9 @@ void gule (int is_byte) * greater than (unsigned) * */ -void gugt (int is_byte) +void gugt (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_ub"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"gt_uw"); + out_ins_cmp(I_CMP_WT, CMP_UGT); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } @@ -639,12 +613,9 @@ void gugt (int is_byte) * greater than or equal (unsigned) * */ -void guge (int is_byte) +void guge (void) { - if (is_byte) - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_ub"); - else - out_ins(I_CMP_WT, T_LIB, (intptr_t)"ge_uw"); + out_ins_cmp(I_CMP_WT, CMP_UGE); out_ins(I_BOOLEAN, 0, 0); stkp = stkp + INTSIZE; } diff --git a/src/hucc/gen.h b/src/hucc/gen.h index f487efb..ff2e195 100644 --- a/src/hucc/gen.h +++ b/src/hucc/gen.h @@ -39,16 +39,16 @@ void gbool (void); void glneg (void); void ginc (LVALUE *lval); void gdec (LVALUE *lval); -void geq (int is_byte); -void gne (int is_byte); -void glt (int is_byte); -void gle (int is_byte); -void ggt (int is_byte); -void gge (int is_byte); -void gult (int is_byte); -void gule (int is_byte); -void gugt (int is_byte); -void guge (int is_byte); +void geq (void); +void gne (void); +void glt (void); +void gle (void); +void ggt (void); +void gge (void); +void gult (void); +void gule (void); +void gugt (void); +void guge (void); void gcast (int type); void gsei (void); void gcli (void); diff --git a/src/hucc/optimize.c b/src/hucc/optimize.c index 1032e9a..4138281 100644 --- a/src/hucc/optimize.c +++ b/src/hucc/optimize.c @@ -101,9 +101,8 @@ unsigned char icode_flags[] = { /* I_BRA */ 0, /* I_DEF */ 0, /* I_CMP_WT */ 0, - /* I_CMP_UT */ 0, - /* X_EQU_WI */ 0, - /* X_NEQ_WI */ 0, + /* X_CMP_WI */ 0, + /* X_CMP_UIQ */ 0, /* I_NOT_WR */ 0, /* I_TST_WR */ 0, /* I_BFALSE */ 0, @@ -360,6 +359,35 @@ unsigned char icode_flags[] = { /* X_LDD_S_B */ IS_SPREL }; +/* invert comparison operation */ +int compare2not [] = { + CMP_NEQ, // CMP_EQU + CMP_EQU, // CMP_NEQ + CMP_SGE, // CMP_SLT + CMP_SGT, // CMP_SLE + CMP_SLE, // CMP_SGT + CMP_SLT, // CMP_SGE + CMP_UGE, // CMP_ULT + CMP_UGT, // CMP_ULE + CMP_ULE, // CMP_UGT + CMP_ULT // CMP_UGE +}; + +/* optimize comparison between unsigned chars */ +/* C promotes an unsigned char to a signed int for comparison */ +int compare2uchar [] = { + CMP_EQU, // CMP_EQU + CMP_NEQ, // CMP_NEQ + CMP_ULT, // CMP_SLT + CMP_ULE, // CMP_SLE + CMP_UGT, // CMP_SGT + CMP_UGE, // CMP_SGE + CMP_ULT, // CMP_ULT + CMP_ULE, // CMP_ULE + CMP_UGT, // CMP_UGT + CMP_UGE // CMP_UGE +}; + /* defines */ #define Q_SIZE 16 @@ -1309,11 +1337,11 @@ void push_ins (INS *ins) * __bool * __tst.wr * - * __equ.wi --> __equ.wi + * __cmp.wi --> __cmp.wi * __bool * __tst.wr * - * __neq.wi --> __neq.wi + * __cmp.uiq --> __cmp.uiq * __bool * __tst.wr * @@ -1329,8 +1357,8 @@ void push_ins (INS *ins) ((p[0]->ins_code == I_TST_WR) && (p[1]->ins_code == I_BOOLEAN) && (p[2]->ins_code == I_CMP_WT || - p[2]->ins_code == X_EQU_WI || - p[2]->ins_code == X_NEQ_WI || + p[2]->ins_code == X_CMP_WI || + p[2]->ins_code == X_CMP_UIQ || p[2]->ins_code == I_NOT_WR || p[2]->ins_code == I_TST_WR) ) { @@ -1338,21 +1366,23 @@ void push_ins (INS *ins) } /* - * __equ.wi --> __neq.wi + * __cmp.wi --> __cmp.wi * __bool * __not.wr * - * __neq.wi --> __equ.wi + * __cmp.uiq --> __cmp.uiq * __bool * __not.wr + * + * N.B. This inverts the test condition of the __cmp.wi! */ else if ((p[0]->ins_code == I_NOT_WR) && (p[1]->ins_code == I_BOOLEAN) && - (p[2]->ins_code == X_EQU_WI || - p[2]->ins_code == X_NEQ_WI) + (p[2]->ins_code == X_CMP_WI || + p[2]->ins_code == X_CMP_UIQ) ) { - p[2]->ins_code = (p[2]->ins_code == X_EQU_WI) ? X_NEQ_WI : X_EQU_WI; + p[2]->cmp_type = compare2not[p[2]->cmp_type]; nb = 2; } @@ -1831,58 +1861,46 @@ void push_ins (INS *ins) } /* - * __push.wr --> __equ.wi i - * __ld.wi i - * __cmp.wt eq_w - * - * __push.wr --> __neq.wi i - * __ld.wi i - * __cmp.wt ne_w - * * __push.wr --> __not.wr * __ld.wi 0 - * __cmp.wt eq_w + * __cmp.wt equ_w * * __push.wr --> __tst.wr * __ld.wi 0 - * __cmp.wt ne_w + * __cmp.wt neq_w */ else if ((p[0]->ins_code == I_CMP_WT) && + (p[0]->cmp_type == CMP_EQU || + p[0]->cmp_type == CMP_NEQ) && (p[1]->ins_code == I_LD_WI) && - (p[2]->ins_code == I_PUSH_WR) && - - (p[1]->ins_type == T_VALUE || p[1]->ins_type == T_SYMBOL) && - (strcmp((char *)p[0]->ins_data, "eq_w") == 0 || - strcmp((char *)p[0]->ins_data, "eq_b") == 0 || - strcmp((char *)p[0]->ins_data, "ne_w") == 0 || - strcmp((char *)p[0]->ins_data, "ne_b") == 0) + (p[1]->ins_type == T_VALUE) && + (p[1]->ins_data == 0) && + (p[2]->ins_code == I_PUSH_WR) ) { /* replace code */ - if (p[1]->ins_data == 0) { - if (strcmp((char *)p[0]->ins_data, "eq_w") == 0) - p[2]->ins_code = I_NOT_WR; - else if (strcmp((char *)p[0]->ins_data, "eq_b") == 0) - p[2]->ins_code = I_NOT_WR; - else if (strcmp((char *)p[0]->ins_data, "ne_w") == 0) - p[2]->ins_code = I_TST_WR; - else if (strcmp((char *)p[0]->ins_data, "ne_b") == 0) - p[2]->ins_code = I_TST_WR; - p[2]->ins_type = 0; - p[2]->ins_data = 0; - } else { - if (strcmp((char *)p[0]->ins_data, "eq_w") == 0) - p[2]->ins_code = X_EQU_WI; - else if (strcmp((char *)p[0]->ins_data, "eq_b") == 0) - p[2]->ins_code = X_EQU_WI; - else if (strcmp((char *)p[0]->ins_data, "ne_w") == 0) - p[2]->ins_code = X_NEQ_WI; - else if (strcmp((char *)p[0]->ins_data, "ne_b") == 0) - p[2]->ins_code = X_NEQ_WI; - p[2]->ins_type = p[1]->ins_type; - p[2]->ins_data = p[1]->ins_data; - } + p[2]->ins_code = (p[0]->cmp_type == CMP_EQU) ? I_NOT_WR : I_TST_WR; + p[2]->ins_type = 0; + p[2]->ins_data = 0; + nb = 2; + } + /* + * __push.wr --> __cmp.wi type, i + * __ld.wi i + * __cmp.wt type + */ + else if + ((p[0]->ins_code == I_CMP_WT) && + (p[1]->ins_code == I_LD_WI) && +// (p[1]->ins_type == T_VALUE || +// p[1]->ins_type == T_SYMBOL) && + (p[2]->ins_code == I_PUSH_WR) + ) { + /* replace code */ + *p[2] = *p[1]; + p[2]->ins_code = X_CMP_WI; + p[2]->cmp_type = p[0]->cmp_type; nb = 2; } @@ -2764,6 +2782,30 @@ void push_ins (INS *ins) goto lv1_loop; } + /* + * __ld.u{p/m/s/ar/ay} symbol --> __ld.u{p/m/s/ar/ay} symbol + * __cmp_w.wi j __cmp_b.uiq j + * + * __and.uiq i --> __and.uiq i + * __cmp_w.wi j __cmp_b.uiq j + * + * C promotes an unsigned char to a signed int so this + * must be done in the peephole, not the compiler. + */ + else if + ((p[0]->ins_code == X_CMP_WI) && + (p[0]->ins_type == T_VALUE) && + (p[0]->ins_data >= 0) && + (p[0]->ins_data <= 255) && + (is_ubyte(p[1])) + ) { + /* replace code */ + p[0]->ins_code = X_CMP_UIQ; + p[0]->cmp_type = compare2uchar[p[0]->cmp_type]; + /* no instructions removed, just loop */ + goto lv1_loop; + } + /* flush queue */ if (nb) { q_wr -= nb; @@ -2914,7 +2956,6 @@ void push_ins (INS *ins) case I_POP_WR: case I_CMP_WT: - case I_CMP_UT: case I_ST_WPT: case I_ST_UPT: case I_ADD_WT: From 05c2b1c99788d756f96ce2fd461e2c0cf140d18d Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Wed, 9 Oct 2024 13:20:54 -0400 Subject: [PATCH 5/7] Tidy up the comments for the comparison macros in hucc-codegen.asm --- include/hucc/hucc-codegen.asm | 70 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index c497850..04bb739 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -541,18 +541,10 @@ __cmp.wt .macro jsr \1 .endm -; ************** -; boolean test, always followed by a __tst.wr or __not.wr -; this MUST set the Z flag for the subsequent branches! - -__cmp.ut .macro - jsr \1 - .endm - ; ************** ; optimized boolean test -; this MUST set the Z flag for the subsequent branches! ; A is true (1) if Y:A == integer-value, else false (0) +; this MUST set the Z flag for the subsequent branches! __equ_w.wi .macro eor.l #\1 @@ -565,8 +557,8 @@ __equ_w.wi .macro ; ************** ; optimized boolean test -; this MUST set the Z flag for the subsequent branches! ; A is true (1) if Y:A != integer-value, else false (0) +; this MUST set the Z flag for the subsequent branches! __neq_w.wi .macro eor.l #\1 @@ -579,8 +571,8 @@ __neq_w.wi .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A < integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __slt_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. @@ -595,8 +587,8 @@ __slt_w.wi .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A <= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sle_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -612,8 +604,8 @@ __sle_w.wi .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A > integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sgt_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -630,8 +622,8 @@ __sgt_w.wi .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A >= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sge_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. @@ -647,8 +639,8 @@ __sge_w.wi .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A < integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ult_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. @@ -661,8 +653,8 @@ __ult_w.wi .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A <= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ule_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -676,8 +668,8 @@ __ule_w.wi .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A > integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ugt_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -690,8 +682,8 @@ __ugt_w.wi .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if Y:A >= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __uge_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. @@ -703,8 +695,8 @@ __uge_w.wi .macro ; ************** ; optimized boolean test -; this MUST set the Z flag for the subsequent branches! ; A is true (1) if A == integer-value, else false (0) +; this MUST set the Z flag for the subsequent branches! __equ_b.uiq .macro eor #\1 @@ -715,8 +707,8 @@ __equ_b.uiq .macro ; ************** ; optimized boolean test -; this MUST set the Z flag for the subsequent branches! ; A is true (1) if A != integer-value, else false (0) +; this MUST set the Z flag for the subsequent branches! __neq_b.uiq .macro eor #\1 @@ -727,8 +719,8 @@ __neq_b.uiq .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A < integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __slt_b.biq .macro sec ; Subtract integer from A. @@ -742,8 +734,8 @@ __slt_b.biq .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A <= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sle_b.biq .macro clc ; Subtract integer+1 from A. @@ -757,8 +749,8 @@ __sle_b.biq .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A > integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sgt_b.biq .macro clc ; Subtract integer+1 from A. @@ -773,8 +765,8 @@ __sgt_b.biq .macro ; ************** ; optimized boolean test (signed word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A >= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __sge_b.biq .macro sec ; Subtract integer from A. @@ -789,8 +781,8 @@ __sge_b.biq .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A < integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ult_b.uiq .macro cmp #\1 ; Subtract integer from A. @@ -801,8 +793,8 @@ __ult_b.uiq .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A <= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ule_b.uiq .macro clc ; Subtract integer+1 from A. @@ -814,8 +806,8 @@ __ule_b.uiq .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A > integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __ugt_b.uiq .macro clc ; Subtract integer+1 from A. @@ -826,8 +818,8 @@ __ugt_b.uiq .macro ; ************** ; optimized boolean test (unsigned word) -; this MUST set the Z flag for the susequent branches! ; A is true (1) if A >= integer-value, else false (0) +; this MUST set the Z flag for the susequent branches! __uge_b.uiq .macro cmp #\1 ; Subtract integer from A. @@ -837,6 +829,7 @@ __uge_b.uiq .macro ; ************** ; boolean test, optimized into __not.wr if used before a __tst.wr +; A is true (1) if Y:A == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.wr .macro @@ -849,6 +842,7 @@ __not.wr .macro ; ************** ; boolean test, always output immediately before a __bfalse or __btrue +; A is true (1) if Y:A != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.wr .macro @@ -875,6 +869,7 @@ __btrue .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.wp .macro @@ -888,6 +883,7 @@ __not.wp .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.wm .macro @@ -900,6 +896,7 @@ __not.wm .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.ws .macro ; __STACK @@ -912,6 +909,7 @@ __not.ws .macro ; __STACK ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.war .macro @@ -926,6 +924,7 @@ __not.war .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.up .macro @@ -937,6 +936,7 @@ __not.up .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.um .macro @@ -948,6 +948,7 @@ __not.um .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.us .macro ; __STACK @@ -959,6 +960,7 @@ __not.us .macro ; __STACK ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.uar .macro @@ -971,6 +973,7 @@ __not.uar .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __not.uay .macro @@ -982,6 +985,7 @@ __not.uay .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.wp .macro @@ -995,6 +999,7 @@ __tst.wp .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.wm .macro @@ -1007,6 +1012,7 @@ __tst.wm .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.ws .macro ; __STACK @@ -1019,6 +1025,7 @@ __tst.ws .macro ; __STACK ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.war .macro @@ -1033,6 +1040,7 @@ __tst.war .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.up .macro @@ -1044,6 +1052,7 @@ __tst.up .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.um .macro @@ -1055,6 +1064,7 @@ __tst.um .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.us .macro ; __STACK @@ -1066,6 +1076,7 @@ __tst.us .macro ; __STACK ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.uar .macro @@ -1078,6 +1089,7 @@ __tst.uar .macro ; ************** ; optimized boolean test +; A is true (1) if memory-value != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tst.uay .macro @@ -1089,6 +1101,7 @@ __tst.uay .macro ; ************** ; optimized boolean test +; A is true (1) if (Y:A & integer) == 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __nand.wi .macro @@ -1114,6 +1127,7 @@ __nand.wi .macro ; ************** ; optimized boolean test +; A is true (1) if (Y:A & integer) != 0, else false (0) ; this MUST set the Z flag for the subsequent branches! __tand.wi .macro From 8823fd2181039a7afc8415b5ab2c12e5fe8055c1 Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Fri, 11 Oct 2024 13:15:22 -0400 Subject: [PATCH 6/7] Teach HuCC's peephole optimizer how to convert both the compare-with-memory and compare-with-stack operations into new i-codes that generate faster inline code. --- include/hucc/hucc-codegen.asm | 626 ++++++++++++++++++++++++++++++++-- src/hucc/code.c | 65 +++- src/hucc/defs.h | 15 +- src/hucc/optimize.c | 111 +++++- 4 files changed, 763 insertions(+), 54 deletions(-) diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index 04bb739..1529605 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -533,6 +533,20 @@ __bra .macro bra \1 .endm +; ************** +; always preceeded by a __tst.wr before peephole optimization + +__bfalse .macro + beq \1 + .endm + +; ************** +; always preceeded by a __tst.wr before peephole optimization + +__btrue .macro + bne \1 + .endm + ; ************** ; boolean test, always followed by a __tst.wr or __not.wr ; this MUST set the Z flag for the subsequent branches! @@ -580,8 +594,8 @@ __slt_w.wi .macro sbc.h #\1 bvc !+ eor #$80 -!: asl a ; -ve if Y:A < integer (signed). - cla ; +ve if Y:A >= integer (signed). +!: asl a ; -ve if Y:A < integer (signed). + cla rol a .endm @@ -598,7 +612,7 @@ __sle_w.wi .macro bvc !+ eor #$80 !: asl a ; -ve if Y:A <= integer (signed). - cla ; +ve if Y:A > integer (signed). + cla rol a .endm @@ -614,8 +628,8 @@ __sgt_w.wi .macro sbc.h #\1 bvc !+ eor #$80 -!: asl a ; +ve if Y:A > integer (signed). - cla ; -ve if Y:A <= integer (signed). +!: asl a ; +ve if Y:A > integer (signed). + cla rol a eor #1 .endm @@ -632,7 +646,7 @@ __sge_w.wi .macro bvc !+ eor #$80 !: asl a ; +ve if Y:A >= integer (signed). - cla ; -ve if Y:A < integer (signed). + cla rol a eor #1 .endm @@ -828,43 +842,590 @@ __uge_b.uiq .macro .endm ; ************** -; boolean test, optimized into __not.wr if used before a __tst.wr -; A is true (1) if Y:A == 0, else false (0) +; optimized boolean test +; A is true (1) if Y:A == memory-value, else false (0) ; this MUST set the Z flag for the subsequent branches! -__not.wr .macro - sty __temp - ora __temp - beq !+ +__equ_w.wm .macro + eor.l \1 + bne !false+ + cpy.h \1 + beq !true+ +!false: lda #-1 +!true: inc a + .endm + +; ************** +; optimized boolean test +; A is true (1) if Y:A != memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__neq_w.wm .macro + eor.l \1 + bne !true+ + cpy.h \1 + beq !false+ +!true: lda #1 +!false: + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__slt_w.wm .macro + cmp.l \1 ; Subtract memory from Y:A. + tya + sbc.h \1 + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A < memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sle_w.wm .macro + clc ; Subtract memory+1 from Y:A. + sbc.l \1 + tya + sbc.h \1 + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A <= memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sgt_w.wm .macro + clc ; Subtract memory+1 from Y:A. + sbc.l \1 + tya + sbc.h \1 + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A > memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sge_w.wm .macro + cmp.l \1 ; Subtract memory from Y:A. + tya + sbc.h \1 + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A >= memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ult_w.wm .macro + cmp.l \1 ; Subtract memory from Y:A. + tya + sbc.h \1 + cla ; CC if Y:A < memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ule_w.wm .macro + clc ; Subtract memory+1 from Y:A. + sbc.l \1 + tya + sbc.h \1 + cla ; CC if Y:A <= memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ugt_w.wm .macro + clc ; Subtract memory+1 from Y:A. + sbc.l \1 + tya + sbc.h \1 + cla ; CS if Y:A > memory. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__uge_w.wm .macro + cmp.l \1 ; Subtract memory from Y:A. + tya + sbc.h \1 + cla ; CS if Y:A >= memory. + rol a + .endm + +; ************** +; optimized boolean test +; A is true (1) if A == memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__equ_b.umq .macro + eor \1 + beq !true+ +!false: lda #-1 +!true: inc a + .endm + +; ************** +; optimized boolean test +; A is true (1) if A != memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__neq_b.umq .macro + eor \1 + beq !false+ lda #1 -!: eor #1 +!false: .endm ; ************** -; boolean test, always output immediately before a __bfalse or __btrue -; A is true (1) if Y:A != 0, else false (0) +; optimized boolean test (signed word) +; A is true (1) if A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__slt_b.bmq .macro + sec ; Subtract memory from A. + sbc \1 + bvc !+ + eor #$80 +!: asl a ; -ve if A < memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sle_b.bmq .macro + clc ; Subtract memory+1 from A. + sbc \1 + bvc !+ + eor #$80 +!: asl a ; -ve if A <= memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sgt_b.bmq .macro + clc ; Subtract memory+1 from A. + sbc.l \1 + bvc !+ + eor #$80 +!: asl a ; +ve if A > memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sge_b.bmq .macro + sec ; Subtract memory from A. + sbc \1 + bvc !+ + eor #$80 +!: asl a ; +ve if A >= memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ult_b.umq .macro + cmp \1 ; Subtract memory from A. + cla ; CC if A < memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ule_b.umq .macro + clc ; Subtract memory+1 from A. + sbc \1 + cla ; CC if A <= memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ugt_b.umq .macro + clc ; Subtract memory+1 from A. + sbc \1 + cla ; CS if A > memory. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__uge_b.umq .macro + cmp \1 ; Subtract memory from A. + cla ; CS if A >= memory. + rol a + .endm + +; ************** +; optimized boolean test +; A is true (1) if Y:A == memory-value, else false (0) ; this MUST set the Z flag for the subsequent branches! -__tst.wr .macro - sty __temp - ora __temp - beq !+ +__equ_w.ws .macro ; __STACK + eor.l <__stack + \1, x + bne !false+ + tya + eor.h <__stack + \1, x + beq !true+ +!false: lda #-1 +!true: inc a + .endm + +; ************** +; optimized boolean test +; A is true (1) if Y:A != memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__neq_w.ws .macro ; __STACK + eor.l <__stack + \1, x + bne !true+ + tya + eor.h <__stack + \1, x + beq !false+ +!true: lda #1 +!false: + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__slt_w.ws .macro ; __STACK + cmp.l <__stack + \1, x; Subtract memory from Y:A. + tya + sbc.h <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A < memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sle_w.ws .macro ; __STACK + clc ; Subtract memory+1 from Y:A. + sbc.l <__stack + \1, x + tya + sbc.h <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; -ve if Y:A <= memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sgt_w.ws .macro ; __STACK + clc ; Subtract memory+1 from Y:A. + sbc.l <__stack + \1, x + tya + sbc.h <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A > memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sge_w.ws .macro ; __STACK + cmp.l <__stack + \1, x; Subtract memory from Y:A. + tya + sbc.h <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; +ve if Y:A >= memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ult_w.ws .macro ; __STACK + cmp.l <__stack + \1, x; Subtract memory from Y:A. + tya + sbc.h <__stack + \1, x + cla ; CC if Y:A < memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ule_w.ws .macro ; __STACK + clc ; Subtract memory+1 from Y:A. + sbc.l <__stack + \1, x + tya + sbc.h <__stack + \1, x + cla ; CC if Y:A <= memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ugt_w.ws .macro ; __STACK + clc ; Subtract memory+1 from Y:A. + sbc.l <__stack + \1, x + tya + sbc.h <__stack + \1, x + cla ; CS if Y:A > memory. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__uge_w.ws .macro ; __STACK + cmp.l <__stack + \1, x; Subtract memory from Y:A. + tya + sbc.h <__stack + \1, x + cla ; CS if Y:A >= memory. + rol a + .endm + +; ************** +; optimized boolean test +; A is true (1) if A == memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__equ_b.usq .macro ; __STACK + eor <__stack + \1, x + beq !true+ +!false: lda #-1 +!true: inc a + .endm + +; ************** +; optimized boolean test +; A is true (1) if A != memory-value, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__neq_b.usq .macro ; __STACK + eor <__stack + \1, x + beq !false+ lda #1 -!: +!false: .endm ; ************** -; always preceeded by a __tst.wr before peephole optimization +; optimized boolean test (signed word) +; A is true (1) if A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! -__bfalse .macro - beq \1 +__slt_b.bsq .macro ; __STACK + sec ; Subtract memory from A. + sbc <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; -ve if A < memory (signed). + cla + rol a .endm ; ************** -; always preceeded by a __tst.wr before peephole optimization +; optimized boolean test (signed word) +; A is true (1) if A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! -__btrue .macro - bne \1 +__sle_b.bsq .macro ; __STACK + clc ; Subtract memory+1 from A. + sbc <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; -ve if A <= memory (signed). + cla + rol a + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sgt_b.bsq .macro ; __STACK + clc ; Subtract memory+1 from A. + sbc.l <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; +ve if A > memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (signed word) +; A is true (1) if A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__sge_b.bsq .macro ; __STACK + sec ; Subtract memory from A. + sbc <__stack + \1, x + bvc !+ + eor #$80 +!: asl a ; +ve if A >= memory (signed). + cla + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A < memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ult_b.usq .macro ; __STACK + cmp <__stack + \1, x; Subtract memory from A. + cla ; CC if A < memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A <= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ule_b.usq .macro ; __STACK + clc ; Subtract memory+1 from A. + sbc <__stack + \1, x + cla ; CC if A <= memory. + rol a + eor #1 + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A > memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__ugt_b.usq .macro ; __STACK + clc ; Subtract memory+1 from A. + sbc <__stack + \1, x + cla ; CS if A > memory. + rol a + .endm + +; ************** +; optimized boolean test (unsigned word) +; A is true (1) if A >= memory-value, else false (0) +; this MUST set the Z flag for the susequent branches! + +__uge_b.usq .macro ; __STACK + cmp <__stack + \1, x; Subtract memory from A. + cla ; CS if A >= memory. + rol a + .endm + +; ************** +; boolean test, optimized into __not.wr if used before a __tst.wr +; A is true (1) if Y:A == 0, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__not.wr .macro + sty __temp + ora __temp + beq !+ + lda #1 +!: eor #1 .endm ; ************** @@ -983,6 +1544,19 @@ __not.uay .macro !: inc a .endm +; ************** +; boolean test, always output immediately before a __bfalse or __btrue +; A is true (1) if Y:A != 0, else false (0) +; this MUST set the Z flag for the subsequent branches! + +__tst.wr .macro + sty __temp + ora __temp + beq !+ + lda #1 +!: + .endm + ; ************** ; optimized boolean test ; A is true (1) if memory-value != 0, else false (0) diff --git a/src/hucc/code.c b/src/hucc/code.c index 0fa8662..3415ae0 100644 --- a/src/hucc/code.c +++ b/src/hucc/code.c @@ -523,6 +523,20 @@ void gen_code (INS *tmp) nl(); break; + case I_BFALSE: + ot("__bfalse\t"); + outlabel((int)data); + nl(); + nl(); + break; + + case I_BTRUE: + ot("__btrue\t\t"); + outlabel((int)data); + nl(); + nl(); + break; + case I_DEF: outstr((const char *)data); outstr(" .equ "); @@ -545,36 +559,52 @@ void gen_code (INS *tmp) nl(); break; - case X_CMP_UIQ: + case X_CMP_WM: ot("__"); outstr(compare2str[tmp->cmp_type]); - outstr("_b.uiq\t"); + outstr("_w.wm\t"); out_type(type, data); nl(); break; - case I_TST_WR: - ol("__tst.wr"); + case X_CMP_WS: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_w.ws\t"); + outdec((int)data); + outlocal(tmp->sym); + nl(); break; - case I_NOT_WR: - ol("__not.wr"); + case X_CMP_UIQ: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_b.uiq\t"); + out_type(type, data); + nl(); break; - case I_BFALSE: - ot("__bfalse\t"); - outlabel((int)data); - nl(); + case X_CMP_UMQ: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_b.umq\t"); + out_type(type, data); nl(); break; - case I_BTRUE: - ot("__btrue\t\t"); - outlabel((int)data); - nl(); + case X_CMP_USQ: + ot("__"); + outstr(compare2str[tmp->cmp_type]); + outstr("_b.usq\t"); + outdec((int)data); + outlocal(tmp->sym); nl(); break; + case I_NOT_WR: + ol("__not.wr"); + break; + case X_NOT_WP: ot("__not.wp\t"); out_addr(type, data); @@ -614,6 +644,7 @@ void gen_code (INS *tmp) case X_NOT_US: ot("__not.us\t"); outdec((int)data); + outlocal(tmp->sym); nl(); break; @@ -629,6 +660,10 @@ void gen_code (INS *tmp) nl(); break; + case I_TST_WR: + ol("__tst.wr"); + break; + case X_TST_WP: ot("__tst.wp\t"); out_addr(type, data); @@ -644,6 +679,7 @@ void gen_code (INS *tmp) case X_TST_WS: ot("__tst.ws\t"); outdec((int)data); + outlocal(tmp->sym); nl(); break; @@ -668,6 +704,7 @@ void gen_code (INS *tmp) case X_TST_US: ot("__tst.us\t"); outdec((int)data); + outlocal(tmp->sym); nl(); break; diff --git a/src/hucc/defs.h b/src/hucc/defs.h index 4d29e08..ef2f186 100644 --- a/src/hucc/defs.h +++ b/src/hucc/defs.h @@ -64,15 +64,20 @@ enum ICODE { I_LABEL, I_ALIAS, I_BRA, + I_BFALSE, + I_BTRUE, I_DEF, + I_CMP_WT, X_CMP_WI, + X_CMP_WM, + X_CMP_WS, + X_CMP_UIQ, - I_NOT_WR, - I_TST_WR, - I_BFALSE, - I_BTRUE, + X_CMP_UMQ, + X_CMP_USQ, + I_NOT_WR, X_NOT_WP, X_NOT_WM, X_NOT_WS, @@ -82,6 +87,8 @@ enum ICODE { X_NOT_US, X_NOT_UAR, X_NOT_UAY, + + I_TST_WR, X_TST_WP, X_TST_WM, X_TST_WS, diff --git a/src/hucc/optimize.c b/src/hucc/optimize.c index 4138281..7bf634e 100644 --- a/src/hucc/optimize.c +++ b/src/hucc/optimize.c @@ -99,15 +99,20 @@ unsigned char icode_flags[] = { /* I_LABEL */ 0, /* I_ALIAS */ 0, /* I_BRA */ 0, + /* I_BFALSE */ 0, + /* I_BTRUE */ 0, /* I_DEF */ 0, + /* I_CMP_WT */ 0, /* X_CMP_WI */ 0, - /* X_CMP_UIQ */ 0, - /* I_NOT_WR */ 0, - /* I_TST_WR */ 0, - /* I_BFALSE */ 0, - /* I_BTRUE */ 0, + /* X_CMP_WM */ 0, + /* X_CMP_WS */ IS_SPREL, + /* X_CMP_UIQ */ IS_UBYTE, + /* X_CMP_UMQ */ IS_UBYTE, + /* X_CMP_USQ */ IS_SPREL + IS_UBYTE, + + /* I_NOT_WR */ 0, /* X_NOT_WP */ 0, /* X_NOT_WM */ 0, /* X_NOT_WS */ IS_SPREL, @@ -117,6 +122,8 @@ unsigned char icode_flags[] = { /* X_NOT_US */ IS_SPREL, /* X_NOT_UAR */ 0, /* X_NOT_UAY */ 0, + + /* I_TST_WR */ 0, /* X_TST_WP */ 0, /* X_TST_WM */ 0, /* X_TST_WS */ IS_SPREL, @@ -1341,10 +1348,26 @@ void push_ins (INS *ins) * __bool * __tst.wr * + * __cmp.wm --> __cmp.wm + * __bool + * __tst.wr + * + * __cmp.ws --> __cmp.ws + * __bool + * __tst.wr + * * __cmp.uiq --> __cmp.uiq * __bool * __tst.wr * + * __cmp.umq --> __cmp.umq + * __bool + * __tst.wr + * + * __cmp.usq --> __cmp.usq + * __bool + * __tst.wr + * * __not.wr --> __not.wr * __bool * __tst.wr @@ -1358,7 +1381,11 @@ void push_ins (INS *ins) (p[1]->ins_code == I_BOOLEAN) && (p[2]->ins_code == I_CMP_WT || p[2]->ins_code == X_CMP_WI || + p[2]->ins_code == X_CMP_WM || + p[2]->ins_code == X_CMP_WS || p[2]->ins_code == X_CMP_UIQ || + p[2]->ins_code == X_CMP_UMQ || + p[2]->ins_code == X_CMP_USQ || p[2]->ins_code == I_NOT_WR || p[2]->ins_code == I_TST_WR) ) { @@ -1370,17 +1397,37 @@ void push_ins (INS *ins) * __bool * __not.wr * + * __cmp.wm --> __cmp.wm + * __bool + * __not.wr + * + * __cmp.ws --> __cmp.ws + * __bool + * __not.wr + * * __cmp.uiq --> __cmp.uiq * __bool * __not.wr * + * __cmp.umq --> __cmp.umq + * __bool + * __not.wr + * + * __cmp.usq --> __cmp.usq + * __bool + * __not.wr + * * N.B. This inverts the test condition of the __cmp.wi! */ else if ((p[0]->ins_code == I_NOT_WR) && (p[1]->ins_code == I_BOOLEAN) && (p[2]->ins_code == X_CMP_WI || - p[2]->ins_code == X_CMP_UIQ) + p[2]->ins_code == X_CMP_WM || + p[2]->ins_code == X_CMP_WS || + p[2]->ins_code == X_CMP_UIQ || + p[2]->ins_code == X_CMP_UMQ || + p[2]->ins_code == X_CMP_USQ) ) { p[2]->cmp_type = compare2not[p[2]->cmp_type]; nb = 2; @@ -1680,6 +1727,35 @@ void push_ins (INS *ins) } #endif + /* + * is_ubyte() --> is_ubyte() + * __push.wr __cmp.umq type, symbol + * __ld.um symbol + * __cmp.wt type + * + * is_ubyte() --> is_ubyte() + * __push.wr __cmp.usq type, (n - 2) + * __ld.us n + * __cmp.wt type + */ + else if + ((p[0]->ins_code == I_CMP_WT) && + (p[1]->ins_code == I_LD_UM || + p[1]->ins_code == X_LD_US) && + (p[2]->ins_code == I_PUSH_WR) && + (is_ubyte(p[3])) + ) { + /* replace code */ + *p[2] = *p[1]; + switch (p[1]->ins_code) { + case I_LD_UM: p[2]->ins_code = X_CMP_UMQ; break; + case X_LD_US: p[2]->ins_code = X_CMP_USQ; p[2]->ins_data -= 2; break; + default: break; + } + p[2]->cmp_type = compare2uchar[p[0]->cmp_type]; + nb = 2; + } + /* flush queue */ if (nb) { q_wr -= nb; @@ -1868,6 +1944,8 @@ void push_ins (INS *ins) * __push.wr --> __tst.wr * __ld.wi 0 * __cmp.wt neq_w + * + * Check for this before converting to X_CMP_WI! */ else if ((p[0]->ins_code == I_CMP_WT) && @@ -1889,17 +1967,30 @@ void push_ins (INS *ins) * __push.wr --> __cmp.wi type, i * __ld.wi i * __cmp.wt type + * + * __push.wr --> __cmp.wm type, symbol + * __ld.wm symbol + * __cmp.wt type + * + * __push.wr --> __cmp.ws type, (n - 2) + * __ld.ws n + * __cmp.wt type */ else if ((p[0]->ins_code == I_CMP_WT) && - (p[1]->ins_code == I_LD_WI) && -// (p[1]->ins_type == T_VALUE || -// p[1]->ins_type == T_SYMBOL) && + (p[1]->ins_code == I_LD_WI || + p[1]->ins_code == I_LD_WM || + p[1]->ins_code == X_LD_WS) && (p[2]->ins_code == I_PUSH_WR) ) { /* replace code */ *p[2] = *p[1]; - p[2]->ins_code = X_CMP_WI; + switch (p[1]->ins_code) { + case I_LD_WI: p[2]->ins_code = X_CMP_WI; break; + case I_LD_WM: p[2]->ins_code = X_CMP_WM; break; + case X_LD_WS: p[2]->ins_code = X_CMP_WS; p[2]->ins_data -= 2; break; + default: break; + } p[2]->cmp_type = p[0]->cmp_type; nb = 2; } From ad9ce4bc0745189ba723057107533d6039e605bb Mon Sep 17 00:00:00 2001 From: John Brandwood Date: Sat, 12 Oct 2024 11:55:34 -0400 Subject: [PATCH 7/7] Change HuCC's comparisons to set the C flag for true instead of setting A and the Z flag. This makes most of the common comparison operations a little quicker with the cost that the rare boolean conversion step is slower and larger when it isn't removed by the peephole optimizer. The most common boolean is "var = !var", and this can be optimized separately in the future. --- include/hucc/hucc-codegen.asm | 988 ++++++++++++++++------------------ 1 file changed, 473 insertions(+), 515 deletions(-) diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index 1529605..fe877df 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -537,18 +537,18 @@ __bra .macro ; always preceeded by a __tst.wr before peephole optimization __bfalse .macro - beq \1 + bcc \1 .endm ; ************** ; always preceeded by a __tst.wr before peephole optimization __btrue .macro - bne \1 + bcs \1 .endm ; ************** -; boolean test, always followed by a __tst.wr or __not.wr +; boolean test, always followed by a __tst.wr or __not.wr before peephole optimization ; this MUST set the Z flag for the subsequent branches! __cmp.wt .macro @@ -557,52 +557,52 @@ __cmp.wt .macro ; ************** ; optimized boolean test -; A is true (1) if Y:A == integer-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A == integer-value, else false (0) +; this MUST set the C flag for the subsequent branches! __equ_w.wi .macro - eor.l #\1 + cmp.l #\1 bne !false+ cpy.h #\1 - beq !true+ -!false: lda #-1 -!true: inc a + beq !+ +!false: clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if Y:A != integer-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A != integer-value, else false (0) +; this MUST set the C flag for the subsequent branches! __neq_w.wi .macro + sec eor.l #\1 - bne !true+ - cpy.h #\1 - beq !false+ -!true: lda #1 -!false: + bne !+ + tya + eor.h #\1 + bne !+ + clc +!: .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A < integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __slt_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. tya sbc.h #\1 bvc !+ - eor #$80 -!: asl a ; -ve if Y:A < integer (signed). - cla - rol a + eor #$80 ; -ve if Y:A < integer (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A <= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sle_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -610,16 +610,14 @@ __sle_w.wi .macro tya sbc.h #\1 bvc !+ - eor #$80 -!: asl a ; -ve if Y:A <= integer (signed). - cla - rol a + eor #$80 ; -ve if Y:A <= integer (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A > integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sgt_w.wi .macro clc ; Subtract integer+1 from Y:A. @@ -627,268 +625,250 @@ __sgt_w.wi .macro tya sbc.h #\1 bvc !+ - eor #$80 -!: asl a ; +ve if Y:A > integer (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A > integer (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A >= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sge_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. tya sbc.h #\1 bvc !+ - eor #$80 -!: asl a ; +ve if Y:A >= integer (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A >= integer (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A < integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ult_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. tya - sbc.h #\1 - cla ; CC if Y:A < integer. + sbc.h #\1 ; CC if Y:A < integer. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A <= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ule_w.wi .macro clc ; Subtract integer+1 from Y:A. sbc.l #\1 tya - sbc.h #\1 - cla ; CC if Y:A <= integer. + sbc.h #\1 ; CC if Y:A <= integer. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A > integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ugt_w.wi .macro clc ; Subtract integer+1 from Y:A. sbc.l #\1 tya - sbc.h #\1 - cla ; CS if Y:A > integer. - rol a + sbc.h #\1 ; CS if Y:A > integer. .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A >= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __uge_w.wi .macro cmp.l #\1 ; Subtract integer from Y:A. tya - sbc.h #\1 - cla ; CS if Y:A >= integer. - rol a + sbc.h #\1 ; CS if Y:A >= integer. .endm ; ************** ; optimized boolean test -; A is true (1) if A == integer-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A == integer-value, else false (0) +; this MUST set the C flag for the subsequent branches! __equ_b.uiq .macro - eor #\1 - beq !true+ -!false: lda #-1 -!true: inc a + cmp #\1 + beq !+ + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if A != integer-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A != integer-value, else false (0) +; this MUST set the C flag for the subsequent branches! __neq_b.uiq .macro + sec eor #\1 - beq !false+ - lda #1 -!false: + bne !+ + clc +!: .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A < integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A < integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __slt_b.biq .macro sec ; Subtract integer from A. sbc #\1 bvc !+ - eor #$80 -!: asl a ; -ve if A < integer (signed). - cla - rol a + eor #$80 ; -ve if A < integer (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A <= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A <= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sle_b.biq .macro clc ; Subtract integer+1 from A. sbc #\1 bvc !+ - eor #$80 -!: asl a ; -ve if A <= integer (signed). - cla - rol a + eor #$80 ; -ve if A <= integer (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A > integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A > integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sgt_b.biq .macro clc ; Subtract integer+1 from A. sbc.l #\1 bvc !+ - eor #$80 -!: asl a ; +ve if A > integer (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A > integer (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A >= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A >= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __sge_b.biq .macro sec ; Subtract integer from A. sbc #\1 bvc !+ - eor #$80 -!: asl a ; +ve if A >= integer (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A >= integer (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A < integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A < integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ult_b.uiq .macro cmp #\1 ; Subtract integer from A. - cla ; CC if A < integer. + ror a ; CC if A < integer. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A <= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A <= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ule_b.uiq .macro clc ; Subtract integer+1 from A. sbc #\1 - cla ; CC if A <= integer. + ror a ; CC if A <= integer. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A > integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A > integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __ugt_b.uiq .macro clc ; Subtract integer+1 from A. - sbc #\1 - cla ; CS if A > integer. - rol a + sbc #\1 ; CS if A > integer. .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A >= integer-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A >= integer-value, else false (0) +; this MUST set the C flag for the susequent branches! __uge_b.uiq .macro cmp #\1 ; Subtract integer from A. - cla ; CS if A >= integer. - rol a + ; CS if A >= integer. .endm ; ************** ; optimized boolean test -; A is true (1) if Y:A == memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A == memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! __equ_w.wm .macro - eor.l \1 + cmp.l \1 bne !false+ cpy.h \1 - beq !true+ -!false: lda #-1 -!true: inc a + beq !+ +!false: clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if Y:A != memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A != memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! __neq_w.wm .macro + sec eor.l \1 - bne !true+ - cpy.h \1 - beq !false+ -!true: lda #1 -!false: + bne !+ + tya + eor.h \1 + bne !+ + clc +!: .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __slt_w.wm .macro cmp.l \1 ; Subtract memory from Y:A. tya sbc.h \1 bvc !+ - eor #$80 -!: asl a ; -ve if Y:A < memory (signed). - cla - rol a + eor #$80 ; -ve if Y:A < memory (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sle_w.wm .macro clc ; Subtract memory+1 from Y:A. @@ -896,16 +876,14 @@ __sle_w.wm .macro tya sbc.h \1 bvc !+ - eor #$80 -!: asl a ; -ve if Y:A <= memory (signed). - cla - rol a + eor #$80 ; -ve if Y:A <= memory (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sgt_w.wm .macro clc ; Subtract memory+1 from Y:A. @@ -913,772 +891,754 @@ __sgt_w.wm .macro tya sbc.h \1 bvc !+ - eor #$80 -!: asl a ; +ve if Y:A > memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A > memory (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sge_w.wm .macro cmp.l \1 ; Subtract memory from Y:A. tya sbc.h \1 bvc !+ - eor #$80 -!: asl a ; +ve if Y:A >= memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A >= memory (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ult_w.wm .macro cmp.l \1 ; Subtract memory from Y:A. tya - sbc.h \1 - cla ; CC if Y:A < memory. + sbc.h \1 ; CC if Y:A < memory. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ule_w.wm .macro clc ; Subtract memory+1 from Y:A. sbc.l \1 tya - sbc.h \1 - cla ; CC if Y:A <= memory. + sbc.h \1 ; CC if Y:A <= memory. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ugt_w.wm .macro clc ; Subtract memory+1 from Y:A. sbc.l \1 tya - sbc.h \1 - cla ; CS if Y:A > memory. - rol a + sbc.h \1 ; CS if Y:A > memory. .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __uge_w.wm .macro cmp.l \1 ; Subtract memory from Y:A. tya - sbc.h \1 - cla ; CS if Y:A >= memory. - rol a + sbc.h \1 ; CS if Y:A >= memory. .endm ; ************** ; optimized boolean test -; A is true (1) if A == memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A == memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! __equ_b.umq .macro - eor \1 - beq !true+ -!false: lda #-1 -!true: inc a + cmp \1 + beq !+ + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if A != memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A != memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! __neq_b.umq .macro + sec eor \1 - beq !false+ - lda #1 -!false: + bne !+ + clc +!: .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __slt_b.bmq .macro sec ; Subtract memory from A. sbc \1 bvc !+ - eor #$80 -!: asl a ; -ve if A < memory (signed). - cla - rol a + eor #$80 ; -ve if A < memory (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sle_b.bmq .macro clc ; Subtract memory+1 from A. sbc \1 bvc !+ - eor #$80 -!: asl a ; -ve if A <= memory (signed). - cla - rol a + eor #$80 ; -ve if A <= memory (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sgt_b.bmq .macro clc ; Subtract memory+1 from A. sbc.l \1 bvc !+ - eor #$80 -!: asl a ; +ve if A > memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A > memory (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __sge_b.bmq .macro sec ; Subtract memory from A. sbc \1 bvc !+ - eor #$80 -!: asl a ; +ve if A >= memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A >= memory (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ult_b.umq .macro cmp \1 ; Subtract memory from A. - cla ; CC if A < memory. + ror a ; CC if A < memory. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ule_b.umq .macro clc ; Subtract memory+1 from A. sbc \1 - cla ; CC if A <= memory. + ror a ; CC if A <= memory. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __ugt_b.umq .macro clc ; Subtract memory+1 from A. - sbc \1 - cla ; CS if A > memory. - rol a + sbc \1 ; CS if A > memory. .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! __uge_b.umq .macro cmp \1 ; Subtract memory from A. - cla ; CS if A >= memory. - rol a + ; CS if A >= memory. .endm ; ************** ; optimized boolean test -; A is true (1) if Y:A == memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A == memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! -__equ_w.ws .macro ; __STACK - eor.l <__stack + \1, x +__equ_w.ws .macro + cmp.l <__stack + \1, x bne !false+ tya - eor.h <__stack + \1, x - beq !true+ -!false: lda #-1 -!true: inc a + cmp.h <__stack + \1, x + beq !+ +!false: clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if Y:A != memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A != memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! -__neq_w.ws .macro ; __STACK +__neq_w.ws .macro + sec eor.l <__stack + \1, x - bne !true+ + bne !+ tya eor.h <__stack + \1, x - beq !false+ -!true: lda #1 -!false: + bne !+ + clc +!: .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__slt_w.ws .macro ; __STACK +__slt_w.ws .macro cmp.l <__stack + \1, x; Subtract memory from Y:A. tya sbc.h <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; -ve if Y:A < memory (signed). - cla - rol a + eor #$80 ; -ve if Y:A < memory (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sle_w.ws .macro ; __STACK +__sle_w.ws .macro clc ; Subtract memory+1 from Y:A. sbc.l <__stack + \1, x tya sbc.h <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; -ve if Y:A <= memory (signed). - cla - rol a + eor #$80 ; -ve if Y:A <= memory (signed). +!: asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sgt_w.ws .macro ; __STACK +__sgt_w.ws .macro clc ; Subtract memory+1 from Y:A. sbc.l <__stack + \1, x tya sbc.h <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; +ve if Y:A > memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A > memory (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (signed word) -; A is true (1) if Y:A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sge_w.ws .macro ; __STACK +__sge_w.ws .macro cmp.l <__stack + \1, x; Subtract memory from Y:A. tya sbc.h <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; +ve if Y:A >= memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if Y:A >= memory (signed). +!: eor #$80 + asl a .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ult_w.ws .macro ; __STACK +__ult_w.ws .macro cmp.l <__stack + \1, x; Subtract memory from Y:A. tya - sbc.h <__stack + \1, x - cla ; CC if Y:A < memory. + sbc.h <__stack + \1, x; CC if Y:A < memory. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ule_w.ws .macro ; __STACK +__ule_w.ws .macro clc ; Subtract memory+1 from Y:A. sbc.l <__stack + \1, x tya - sbc.h <__stack + \1, x - cla ; CC if Y:A <= memory. + sbc.h <__stack + \1, x; CC if Y:A <= memory. + ror a + eor #$80 rol a - eor #1 .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ugt_w.ws .macro ; __STACK +__ugt_w.ws .macro clc ; Subtract memory+1 from Y:A. sbc.l <__stack + \1, x tya - sbc.h <__stack + \1, x - cla ; CS if Y:A > memory. - rol a + sbc.h <__stack + \1, x; CS if Y:A > memory. .endm ; ************** ; optimized boolean test (unsigned word) -; A is true (1) if Y:A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; C is true (1) if Y:A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__uge_w.ws .macro ; __STACK +__uge_w.ws .macro cmp.l <__stack + \1, x; Subtract memory from Y:A. tya - sbc.h <__stack + \1, x - cla ; CS if Y:A >= memory. - rol a + sbc.h <__stack + \1, x; CS if Y:A >= memory. .endm ; ************** ; optimized boolean test -; A is true (1) if A == memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A == memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! -__equ_b.usq .macro ; __STACK - eor <__stack + \1, x - beq !true+ -!false: lda #-1 -!true: inc a +__equ_b.usq .macro + cmp <__stack + \1, x + beq !+ + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if A != memory-value, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if A != memory-value, else false (0) +; this MUST set the C flag for the subsequent branches! -__neq_b.usq .macro ; __STACK +__neq_b.usq .macro + sec eor <__stack + \1, x - beq !false+ - lda #1 -!false: + bne !+ + clc +!: .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__slt_b.bsq .macro ; __STACK +__slt_b.bsq .macro sec ; Subtract memory from A. sbc <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; -ve if A < memory (signed). - cla - rol a + eor #$80 ; -ve if A < memory (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sle_b.bsq .macro ; __STACK +__sle_b.bsq .macro clc ; Subtract memory+1 from A. sbc <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; -ve if A <= memory (signed). - cla - rol a + eor #$80 ; -ve if A <= memory (signed). +!: asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sgt_b.bsq .macro ; __STACK +__sgt_b.bsq .macro clc ; Subtract memory+1 from A. sbc.l <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; +ve if A > memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A > memory (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (signed word) -; A is true (1) if A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (signed byte) +; C is true (1) if A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__sge_b.bsq .macro ; __STACK +__sge_b.bsq .macro sec ; Subtract memory from A. sbc <__stack + \1, x bvc !+ - eor #$80 -!: asl a ; +ve if A >= memory (signed). - cla - rol a - eor #1 + eor #$80 ; +ve if A >= memory (signed). +!: eor #$80 + asl a .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A < memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A < memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ult_b.usq .macro ; __STACK +__ult_b.usq .macro cmp <__stack + \1, x; Subtract memory from A. - cla ; CC if A < memory. + ror a ; CC if A < memory. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A <= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A <= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ule_b.usq .macro ; __STACK +__ule_b.usq .macro clc ; Subtract memory+1 from A. sbc <__stack + \1, x - cla ; CC if A <= memory. + ror a ; CC if A <= memory. + eor #$80 rol a - eor #1 .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A > memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A > memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__ugt_b.usq .macro ; __STACK +__ugt_b.usq .macro clc ; Subtract memory+1 from A. - sbc <__stack + \1, x - cla ; CS if A > memory. - rol a + sbc <__stack + \1, x; CS if A > memory. .endm ; ************** -; optimized boolean test (unsigned word) -; A is true (1) if A >= memory-value, else false (0) -; this MUST set the Z flag for the susequent branches! +; optimized boolean test (unsigned byte) +; C is true (1) if A >= memory-value, else false (0) +; this MUST set the C flag for the susequent branches! -__uge_b.usq .macro ; __STACK +__uge_b.usq .macro cmp <__stack + \1, x; Subtract memory from A. - cla ; CS if A >= memory. - rol a + ; CS if A >= memory. .endm ; ************** ; boolean test, optimized into __not.wr if used before a __tst.wr -; A is true (1) if Y:A == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.wr .macro sty __temp ora __temp + sec beq !+ - lda #1 -!: eor #1 + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.wp .macro ldy #1 lda [\1], y ora [\1] + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.wm .macro lda.l \1 ora.h \1 + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.ws .macro ; __STACK lda.l <__stack + \1, x ora.h <__stack + \1, x + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.war .macro asl a tay lda.l \1, y ora.h \1, y + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.up .macro lda [\1] + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.um .macro lda \1 + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.us .macro ; __STACK lda.l <__stack + \1, x + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.uar .macro tay lda \1, y + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __not.uay .macro lda \1, y + sec beq !+ - lda #-1 -!: inc a + clc +!: .endm ; ************** ; boolean test, always output immediately before a __bfalse or __btrue -; A is true (1) if Y:A != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if Y:A != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.wr .macro sty __temp ora __temp - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.wp .macro ldy #1 lda [\1], y ora [\1] - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.wm .macro lda.l \1 ora.h \1 - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.ws .macro ; __STACK lda.l <__stack + \1, x ora.h <__stack + \1, x - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.war .macro asl a tay lda.l \1, y ora.h \1, y - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.up .macro lda [\1] - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.um .macro lda \1 - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.us .macro ; __STACK lda.l <__stack + \1, x - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.uar .macro tay lda \1, y - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if memory-value != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if memory-value != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tst.uay .macro lda \1, y - beq !+ - lda #1 + sec + bne !+ + clc !: .endm ; ************** ; optimized boolean test -; A is true (1) if (Y:A & integer) == 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if (Y:A & integer) == 0, else false (0) +; this MUST set the C flag for the subsequent branches! __nand.wi .macro + clc .if ((\1 & $FF00) == 0) and #\1 .else @@ -1687,24 +1647,23 @@ __nand.wi .macro and.h #\1 .else and.l #\1 - bne !false+ + bne !+ tya and.h #\1 .endif .endif - .if (\1 != 1) - beq !+ -!false: lda #1 - .endif -!: eor #1 + bne !+ + sec +!: .endm ; ************** ; optimized boolean test -; A is true (1) if (Y:A & integer) != 0, else false (0) -; this MUST set the Z flag for the subsequent branches! +; C is true (1) if (Y:A & integer) != 0, else false (0) +; this MUST set the C flag for the subsequent branches! __tand.wi .macro + sec .if ((\1 & $FF00) == 0) and #\1 .else @@ -1713,23 +1672,24 @@ __tand.wi .macro and.h #\1 .else and.l #\1 - bne !true+ + bne !+ tya and.h #\1 .endif .endif - .if (\1 != 1) - beq !+ -!true: lda #1 - .endif + bne !+ + clc !: .endm ; ************** -; convert boolean test result into a 16-bit integer +; convert boolean test result C flag into a 16-bit Y:A integer __bool .macro + cla + rol a cly + cmp #1 ; Only needed for unoptimized code. .endm @@ -3098,7 +3058,7 @@ __sub.wt .macro ; __STACK ; ************** __sub.wi .macro - .if ((\?1 == ARG_ABS) && (\1 >= 0) && (\1 < 256)) + .if ((\?1 == ARG_ABS) && ((\1) >= 0) && ((\1) < 256)) sec sbc.l #\1 bcs !+ @@ -3756,29 +3716,43 @@ __ldd_s_b .macro ; __STACK ; *************************************************************************** ; ************** -; A is true (1) if stacked-value == Y:A, else false (0) +; C is true (1) if stacked-value == Y:A, else false (0) equ_w: cmp.l <__stack, x bne return_false - say + tya cmp.h <__stack, x - say bne return_false - bra return_true +; bra return_true ; ************** -; A is true (1) if stacked-value != Y:A, else false (0) +; boolean result, this MUST set the C flag for the subsequent branches! + +return_true: inx + inx + sec + rts + +; ************** +; C is true (1) if stacked-value != Y:A, else false (0) neq_w: cmp.l <__stack, x bne return_true - say + tya cmp.h <__stack, x - say bne return_true - bra return_false +; bra return_false + +; ************** +; boolean result, this MUST set the C flagy for the subsequent branches! + +return_false: inx + inx + clc + rts ; ************** -; A is true (1) if stacked-value < Y:A, else false (0) +; C is true (1) if stacked-value < Y:A, else false (0) slt_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x @@ -3790,7 +3764,7 @@ slt_w: clc ; Subtract memory+1 from Y:A. bra return_false ; -ve if Y:A <= memory (signed). ; ************** -; A is true (1) if stacked-value <= Y:A, else false (0) +; C is true (1) if stacked-value <= Y:A, else false (0) sle_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya @@ -3801,7 +3775,7 @@ sle_w: cmp.l <__stack, x ; Subtract memory from Y:A. bra return_false ; -ve if Y:A < memory (signed). ; ************** -; A is true (1) if stacked-value > Y:A, else false (0) +; C is true (1) if stacked-value > Y:A, else false (0) sgt_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya @@ -3812,7 +3786,7 @@ sgt_w: cmp.l <__stack, x ; Subtract memory from Y:A. bra return_false ; +ve if Y:A >= memory (signed). ; ************** -; A is true (1) if stacked-value >= Y:A, else false (0) +; C is true (1) if stacked-value >= Y:A, else false (0) sge_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x @@ -3824,7 +3798,7 @@ sge_w: clc ; Subtract memory+1 from Y:A. bra return_false ; +ve if Y:A > memory (signed). ; ************** -; A is true (1) if stacked-value < Y:A, else false (0) +; C is true (1) if stacked-value < Y:A, else false (0) ult_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x @@ -3834,7 +3808,7 @@ ult_w: clc ; Subtract memory+1 from Y:A. bra return_false ; ************** -; A is true (1) if stacked-value <= Y:A, else false (0) +; C is true (1) if stacked-value <= Y:A, else false (0) ule_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya @@ -3843,7 +3817,7 @@ ule_w: cmp.l <__stack, x ; Subtract memory from Y:A. bra return_false ; ************** -; A is true (1) if stacked-value > Y:A, else false (0) +; C is true (1) if stacked-value > Y:A, else false (0) ugt_w: cmp.l <__stack, x ; Subtract memory from Y:A. tya @@ -3852,7 +3826,7 @@ ugt_w: cmp.l <__stack, x ; Subtract memory from Y:A. bra return_false ; ************** -; A is true (1) if stacked-value >= Y:A, else false (0) +; C is true (1) if stacked-value >= Y:A, else false (0) uge_w: clc ; Subtract memory+1 from Y:A. sbc.l <__stack, x @@ -3861,22 +3835,6 @@ uge_w: clc ; Subtract memory+1 from Y:A. bcc return_true ; CC if Y:A <= memory. bra return_false -; ************** -; boolean result, this MUST set the Z flag for the subsequent branches! - -return_true: inx - inx ; don't push Y:A, they are thrown away - lda #1 ; Also set valid Z flag. - rts - -; ************** -; boolean result, this MUST set the Z flag for the subsequent branches! - -return_false: inx - inx ; don't push Y:A, they are thrown away - lda #0 ; Also set valid Z flag. - rts - ; ***************************************************************************