Skip to content
This repository was archived by the owner on Dec 23, 2025. It is now read-only.
This repository was archived by the owner on Dec 23, 2025. It is now read-only.

be-codegen-6800.c Optimizes addition and subtraction with signed/unsigned char. #167

@zu2

Description

@zu2

Currently, addition with signed/unsigned char pushes the augend onto the stack, sign-extends the addend, and then calls a helper function.

This patch provides shorter code.

--- ../Fuzix-Compiler-Kit/be-codegen-6800.c	2024-11-18 09:16:57
+++ be-codegen-6800.c	2024-11-18 21:02:24
@@ -514,6 +514,20 @@
 			invalidate_d();
 			add_d_const(v);
 			return 1;
+		}
+		if (s == 2 && r->op == T_CAST && (r->type&~UNSIGNED) == CSHORT && is_simple(r->right)) {
+			if (r->right->type == UCHAR) {
+				op8_on_node(r->right, "add", 0);
+				puts("\tadca #0");
+				return 1;
+			}else if (r->right->type == CCHAR) {
+				unsigned l = ++label;
+				write_uni_op(r->right, "tst", 0);
+				printf("\tbpl X%u\n\tdeca\nX%u:\n",l,l);
+				op8_on_node(r->right, "add", 0);
+				puts("\tadca #0");
+				return 1;
+			}
 		}
 		return write_opd(r, "add", "adc", 0);
 	case T_MINUS:
@@ -527,6 +541,20 @@
 			if (s == 1) {
 				add_b_const(-r->value);
 				b_val -= r->value;
+				return 1;
+			}
+		}
+		if (s == 2 && r->op == T_CAST && (r->type&~UNSIGNED) == CSHORT && is_simple(r->right)) {
+			if (r->right->type == UCHAR) {
+				op8_on_node(r->right, "sub", 0);
+				puts("\tsbca #0");
+				return 1;
+			}else if (r->right->type == CCHAR) {
+				unsigned l = ++label;
+				write_uni_op(r->right, "tst", 0);
+				printf("\tbpl X%u\n\tinca\nX%u:\n",l,l);
+				op8_on_node(r->right, "sub", 0);
+				puts("\tsbca #0");
 				return 1;
 			}
 		}

the patch pass this test program.

#include	"cprintf.c"

int
main(int argc,char **argv)
{
	signed char c1, c2;
	int	i1,i2;

	for(i1=-128; i1<=127; i1++){
		for(i2=-128; i2<=127; i2++){
			c1 = i1;
			c2 = i2;
			if(c1+c2 != i1+i2){
				cprintf("%d+%d=%d (!=%d)\n",i1,i2,c1+c2,i1+i2);
				return 1;
			}
			if(c1-c2 != i1-i2){
				cprintf("%d+%d=%d (!=%d)\n",i1,i2,c1-c2,i1-i2);
				return 2;
			}
		}
	}

	return 0;
}

before

        ldb 0,x
        clra
        asrb
        rolb
        sbca #0
        pshb
        psha
        ldb 1,x
        clra
        asrb
        rolb
        sbca #0
        jsr __plus

after.

        ldb 0,x
        clra
        asrb
        rolb
        sbca #0
        tst 1,x
        bpl X1
        deca
X1:
        addb 1,x
        adca #0

This patch does not shorten the form *p - *q as memcmp uses. I am looking for a way to do this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions