From d8b8a55078d956b32e8ebc62bd61649e08d0f67d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 26 Jul 2016 18:47:20 +0100 Subject: [PATCH] smallc: Updates - basics for register variables - assorted other improvements to move towards better code generation --- Applications/SmallC/TODO | 34 +++++++ Applications/SmallC/code6801.c | 142 +++++++++++++++++++++++--- Applications/SmallC/code6809.c | 109 ++++++++++++++++++-- Applications/SmallC/code8080.c | 36 +++++-- Applications/SmallC/codegeneric.c | 50 ++++++++- Applications/SmallC/codez80.c | 121 ++++++++++++++++------ Applications/SmallC/defs.h | 2 + Applications/SmallC/lib/strlen.c | 2 +- Applications/SmallC/prototype.h | 2 + Applications/SmallC/rules.6801 | 44 ++++++++ Applications/SmallC/rules.6809 | 109 ++++++++++++++++++++ Applications/SmallC/rules.gen | 162 ++++++++++++++++++++++++++++++ Applications/SmallC/stmt.c | 13 ++- Applications/SmallC/sym.c | 18 ++-- 14 files changed, 774 insertions(+), 70 deletions(-) create mode 100644 Applications/SmallC/rules.6801 create mode 100644 Applications/SmallC/rules.gen diff --git a/Applications/SmallC/TODO b/Applications/SmallC/TODO index 1604b63d..ed06557b 100644 --- a/Applications/SmallC/TODO +++ b/Applications/SmallC/TODO @@ -4,3 +4,37 @@ and maybe even get rid of the literal pool (2.5K saving) - Can we split the preprocessor optionally - Work out what is needed for stack frame based Z80 code + +- Clean up optimizier rules now we have ;end +- Flag void v non void to optimizer (elimination of trailing loads) +- How to do tail load elimination but avoid breaking the way it relies + upon that for returns ? - is the jump $1 reliable for that ? (take care if + we eliminate the jump $1 for a label) + +- Indirection support to multiple output files so we can sort call orders + + +Macro ops for bytecode form + +load r1 (fprel) ; with pre/post inc dec +store r1 (fprel) ; ditto + +And ditto with 'and indirect' or bytes (signed and unsigned) + +ie so we can generate as a 2 byte op + + load r1 [(2+fp)++] + + +Z80 registers + +BC - providing we tweak the varargs bits (int) +IY - pointer +IX - pointer (maybe) + +RST ops ? + +- stack indirections +- complex ops (RSTm aa ll RSTn aa ll hh) + - pre/post inc load/stores with or without indirection + - stack shifts diff --git a/Applications/SmallC/code6801.c b/Applications/SmallC/code6801.c index 54e9890a..2dc5ede6 100644 --- a/Applications/SmallC/code6801.c +++ b/Applications/SmallC/code6801.c @@ -2,6 +2,12 @@ #include "defs.h" #include "data.h" +int nextreg = 0; +int xdirty = 0; +int xsprel = 0; +int xtype = 0; /* 0 = D, 1 = S */ +int regv[8]; + /* * Some predefinitions: * @@ -13,6 +19,9 @@ * a pointer - in fact, the compiler uses INTSIZE for both. * * For 6801 we keep the secondary as top of stack as much as possible + * + * D holds the accumulator values + * X is used for scratch pointer work */ /** @@ -43,6 +52,7 @@ void initmac(void) { * Output internal generated label prefix */ void output_label_prefix(void) { + xdirty = 1; output_byte('$'); } @@ -112,6 +122,53 @@ void output_number(int num) { output_decimal(num); } +static void describe_access(SYMBOL *sym) +{ + if (sym->storage == REGISTER) { + output_string("<_reg"); + output_number(sym->offset); + newline(); + return; + } + if (sym->storage == AUTO || sym->storage == DEFAUTO) { + output_decimal(sym->offset - xsprel); + output_string(",x"); + } else if (sym->storage == LSTATIC) + print_label(sym->offset); + else + output_string(sym->name); + newline(); +} + +static void gen_tsx(int offset) +{ +// printf("GENTSX %d [D%d T%d V%d]\n", offset, xdirty, xtype, xsprel); + /* Having a valid tsx state isn't good enoguh because it may be that + it's out of range of or variable */ + if (xdirty == 0 && xtype == 1) { +// printf("OFFSET %d\n", offset - stkp); + /* Ok we have x holding a value of s but it may be out of range */ + if (offset - xsprel >= 0 && offset - xsprel < 256) + return; + } + output_line("tsx"); + xdirty = 0; + xsprel = stkp; + xtype = 1; + offset -= stkp; + /* Now it gets fun - we might be out of range ? */ + if (offset > 255) { + output_line("pshb"); + output_line("ldab #255"); + while(offset > 255) { + output_line("abx"); + offset -= 256; + xsprel += 256; + } + output_line("pulb"); + } +} + /** * fetch a static memory cell into the primary register * @param sym @@ -119,18 +176,16 @@ void output_number(int num) { void gen_get_memory(SYMBOL *sym) { if ((sym->identity != POINTER) && (sym->type == CCHAR)) { output_with_tab ("ldab "); - output_string(sym->name); + describe_access(sym); output_line("sex"); newline (); } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { output_with_tab("ldab "); - output_string(sym->name); - newline(); + describe_access(sym); output_line("clra"); } else { output_with_tab ("ldd "); - output_string(sym->name); - newline (); + describe_access(sym); } } @@ -161,13 +216,11 @@ int gen_get_locale(SYMBOL *sym) { */ void gen_put_memory(SYMBOL *sym) { if ((sym->identity != POINTER) && (sym->type & CCHAR)) { - output_with_tab("std "); - output_string(sym->name); - } else { output_with_tab("stab "); - output_string(sym->name); + } else { + output_with_tab("std "); } - newline (); + describe_access(sym); } /** @@ -192,6 +245,7 @@ void gen_put_indirect(char typeobj) { void gen_get_indirect(char typeobj, int reg) { if (typeobj == CCHAR) { if (reg & DE_REG) { + /* FIXME DE cases */ output_line("ldab ,x"); output_line("sex"); } else @@ -216,8 +270,10 @@ void gen_get_indirect(char typeobj, int reg) { */ int gen_indirected(SYMBOL *s) { - /* TODO */ - return 1; + if (s->storage == REGISTER || s->storage == LSTATIC) + return 0; + gen_tsx(s->offset); + return 0; } /** @@ -254,6 +310,7 @@ void gen_push(int reg) { */ void gen_pop(void) { output_line ("pulx"); + xdirty = 1; stkp = stkp + INTSIZE; } @@ -265,6 +322,7 @@ void gen_swap_stack(void) { output_line("ldd ,s"); output_line("ldx _tmp1"); output_line("stx ,s"); + xdirty = 1; } /** @@ -288,10 +346,32 @@ void declare_entry_point(char *symbol_name) { void gen_prologue(void) { + xdirty = 1; + nextreg = 0; } void gen_epilogue(void) { + int i; + /* FIXME: usual case we can pop these in this order need to spot the + sp position and optimize accordingly */ + for (i = nextreg - 1; i >= 0; i--) { + if (stkp == regv[i]) { + stkp += 2; + output_line("pulx"); + xdirty = 1; + } else { + output_line("tsx"); + output_with_tab("ldx "); + output_number(stkp - i); + output_string(", x"); + newline(); + xdirty = 1; + } + output_with_tab("stx <_reg"); + output_number(i); + newline(); + } } /** @@ -315,7 +395,7 @@ void callstk(void) { */ void gen_jump(int label) { - output_with_tab ("jump "); + output_with_tab ("jmp "); print_label (label); newline (); } @@ -368,9 +448,10 @@ int gen_modify_stack(int newstkp) { if (k == 0) return (newstkp); if (k > 0) { - if (k >= 8) { + if (k <= 8) { while(k >= 2) { output_line("pulx"); + xdirty = 1; k -= 2; } if (k == 1) @@ -423,6 +504,26 @@ int gen_defer_modify_stack(int newstkp) return gen_modify_stack(newstkp); } +int gen_register(int vp, int size, int typ) +{ + return -1; +/* + Not clear register helps at all on a 6801 + if (size > 2) + return -1; + if (nextreg > 8) + return -1; + stkp = stkp - 2; + regv[nextreg] = stkp; + output_with_tab("ldx <_reg"); + xdirty = 1; + output_number(nextreg); + newline(); + output_line("pshx"); + return nextreg++; +*/ +} + /** * multiply the primary register by INTSIZE @@ -455,13 +556,11 @@ void gen_jump_case(void) { * @param lval2 */ void gen_add(LVALUE *lval, LVALUE *lval2) { - gen_swap(); if (dbltest (lval2, lval)) { output_line("addd ,s"); output_line("addd ,s"); } else output_line ("addd ,s"); - gen_swap(); gen_pop(); } @@ -759,6 +858,7 @@ void gnargs(int d) */ void gen_immediate2(void) { output_with_tab ("ldx "); + xdirty = 1; } /** @@ -784,12 +884,22 @@ void gen_multiply(int type, int size) { output_line("addd _tmp"); break; case STRUCT: + /* Might be smarter to pshx/pulx ? */ output_with_tab("ldx "); output_number(size); newline(); + xdirty = 1; gen_call("_muld"); break; default: break; } } + +/** + * To help the optimizer know when r1/r2 are discardable + */ +void gen_statement_end(void) +{ + output_line(";end"); +} \ No newline at end of file diff --git a/Applications/SmallC/code6809.c b/Applications/SmallC/code6809.c index 596452e9..001763c7 100644 --- a/Applications/SmallC/code6809.c +++ b/Applications/SmallC/code6809.c @@ -2,6 +2,9 @@ #include "defs.h" #include "data.h" +int nextreg = 0; +int regv[8]; + /* * Some predefinitions: * @@ -121,7 +124,15 @@ void output_immediate(int num) { static void describe_access(SYMBOL *sym) { - if (sym->storage == LSTATIC) + if (sym->storage == REGISTER) { + if (sym->offset < 2) + output_byte("uy"[sym->offset]); + else { + output_string("_reg"); + output_number(sym->offset); + } + } + else if (sym->storage == LSTATIC) print_label(sym->offset); else if (sym->storage == AUTO || sym->storage == DEFAUTO) { output_number(sym->offset - stkp); @@ -145,8 +156,16 @@ void gen_get_memory(SYMBOL *sym) { describe_access(sym); output_line("clr a"); } else { - output_with_tab ("ldd "); - describe_access(sym); + /* Annoying special case */ + if (sym->storage == REGISTER && sym->offset < 2) { + output_with_tab("tfr "); + output_byte("uy"[sym->offset]); + output_string(",d"); + newline(); + } else { + output_with_tab ("ldd "); + describe_access(sym); + } } } @@ -176,6 +195,19 @@ int gen_get_locale(SYMBOL *sym) { * @param sym */ void gen_put_memory(SYMBOL *sym) { + int reg = 0; + + /* FIXME: for now we only do 16bit values in reg so we avoid the + tfr b,x problem */ + if (sym->storage == REGISTER && sym->offset < 2) + reg = 1; + + if (reg) { + output_with_tab("tfr d,"); + output_byte("uy"[sym->offset]); + newline(); + return; + } if ((sym->identity != POINTER) && (sym->type & CCHAR)) output_with_tab ("stb "); else @@ -208,6 +240,7 @@ void gen_get_indirect(char typeobj, int reg) { output_line("ldb ,x"); else { /* TODO work out what we can damage here */ + /* Can we avoid using ,u ?? */ output_line("tfr d,u"); output_line("ldb ,u"); } @@ -217,8 +250,9 @@ void gen_get_indirect(char typeobj, int reg) { if (reg & DE_REG) output_line("ldd ,x"); /* Can't happen ?? */ else { - output_line("tfr d,u"); - output_line("ldd ,u"); + output_line("exg d,x"); + output_line("ldx ,x"); + output_line("exg d,x"); } } } @@ -270,9 +304,14 @@ void gen_pop(void) { } /** - * swap the primary register and the top of the stack + * swap the primary register and the top of the stack. Used when we + * call a function as a variable. + * + * FIXME: probably want a gen_call_indirect so targets can do sane things */ void gen_swap_stack(void) { + /* FIXME: if we can get rid of u register stuff we can get two + register variables */ output_line("ldu ,s"); output_line("std ,s"); output_line("tfr u,d"); @@ -299,10 +338,37 @@ void declare_entry_point(char *symbol_name) { void gen_prologue(void) { + nextreg = 0; } void gen_epilogue(void) { + int i; + /* FIXME: usual case we can pop these in this order need to spot the + sp position and optimize accordingly */ + for (i = nextreg - 1; i >= 2; i--) { + if (stkp == regv[i]) { + stkp += 2; + output_line("puls x"); + } else { + output_with_tab("ldx "); + output_number(stkp - i); + output_string(",s"); + newline(); + } + output_with_tab("stx _reg"); + output_number(i); + newline(); + } + /* FIXME: need to adjust the stack if there is cruft in the way */ + if (nextreg > 1) { + output_line("puls y,u"); + stkp + 4; + } + else if (nextreg) { + output_line("puls y"); + stkp += 2; + } } /** @@ -399,6 +465,27 @@ int gen_defer_modify_stack(int newstkp) return newstkp + defer; } +int gen_register(int vp, int size, int typ) +{ + if (size != 2) + return -1; + if (nextreg > 8) + return -1; + stkp = stkp - 2; + regv[nextreg] = stkp; + if (nextreg > 1) { + output_with_tab("ldy _reg"); + output_number(nextreg); + newline(); + } + if (nextreg == 1) + output_line("pshs y"); + else + output_line("pshs u"); + return nextreg++; +} + + /** * multiply the primary register by INTSIZE */ @@ -725,6 +812,8 @@ char *inclib(void) { */ void gnargs(int d) { + /* u is a register variable but it is saved before a call and we just + need to do something clever on entry if using register variables */ output_with_tab ("ldu "); output_immediate(d); newline (); @@ -770,3 +859,11 @@ void gen_multiply(int type, int size) { break; } } + +/** + * To help the optimizer know when r1/r2 are discardable + */ +void gen_statement_end(void) +{ + output_line(";end"); +} diff --git a/Applications/SmallC/code8080.c b/Applications/SmallC/code8080.c index 5aebcf80..76889f4b 100644 --- a/Applications/SmallC/code8080.c +++ b/Applications/SmallC/code8080.c @@ -122,6 +122,15 @@ void output_number(int num) { output_decimal(num); } +static void describe_access(SYMBOL *sym) +{ + if (sym->storage == LSTATIC) + print_label(sym->offset); + else + output_string(sym->name); + newline(); +} + /** * fetch a static memory cell into the primary register * @param sym @@ -129,18 +138,16 @@ void output_number(int num) { void gen_get_memory(SYMBOL *sym) { if ((sym->identity != POINTER) && (sym->type == CCHAR)) { output_with_tab ("lda\t"); - output_string (sym->name); - newline (); + describe_access(sym); gen_call ("ccsxt"); } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { output_with_tab("lda\t"); - output_string(sym->name); - newline(); + describe_access(sym); output_line("mov \tl,a"); output_line("mvi \th,#0"); } else { output_with_tab ("lhld\t"); - output_string (sym->name); + describe_access(sym); newline (); } } @@ -159,6 +166,7 @@ int gen_get_locale(SYMBOL *sym) { } else { if (uflag && !(sym->identity == ARRAY)) {// || //(sym->identity == VARIABLE && sym->type == STRUCT))) { + /* 8085 */ output_with_tab("ldsi\t"); output_number(sym->offset - stkp); newline (); @@ -184,8 +192,7 @@ void gen_put_memory(SYMBOL *sym) { } else { output_with_tab ("shld\t"); } - output_string (sym->name); - newline (); + describe_access(sym); } /** @@ -244,7 +251,8 @@ void gen_get_indirect(char typeobj, int reg) { */ int gen_indirected(SYMBOL *s) { - /* FIXME: TODO - we can avoid indirecting LSTATIC */ + if (s->storage == LSTATIC) + return 0; return 1; } @@ -438,6 +446,11 @@ int gen_defer_modify_stack(int newstkp) return gen_modify_stack(newstkp); } +int gen_register(int vp, int size, int typ) +{ + /* For the moment */ + return -1; +} /** * multiply the primary register by INTSIZE @@ -816,3 +829,10 @@ void gen_multiply(int type, int size) { } } +/** + * To help the optimizer know when r1/r2 are discardable + */ +void gen_statement_end(void) +{ + output_line(";end"); +} diff --git a/Applications/SmallC/codegeneric.c b/Applications/SmallC/codegeneric.c index 29abeee6..5c5c519e 100644 --- a/Applications/SmallC/codegeneric.c +++ b/Applications/SmallC/codegeneric.c @@ -4,6 +4,8 @@ static int args; +static int nextreg; +static int regv[8]; /* * A cheap and cheerful way to see what it's trying to do @@ -85,10 +87,28 @@ void data_segment_gdata(void) { void gen_prologue(void) { + nextreg = 3; } void gen_epilogue(void) { + int i; + /* FIXME: usual case we can pop these in this order need to spot the + sp position and optimize accordingly */ + for (i = nextreg - 1; i >= 3; i--) { + if (stkp == regv[i]) { + stkp += 2; + output_with_tab("pop r"); + output_number(i); + } else { + output_with_tab("load r"); + output_number(i); + output_string(" ("); + output_number(regv[i]); + output_string("+fp)"); + } + newline(); + } } /** @@ -130,6 +150,12 @@ static void output_bracketed(char *p) static void describe_access(SYMBOL *sym) { + if (sym->storage == REGISTER) { + output_string("r"); + output_number(sym->offset); + newline(); + return; + } output_byte('('); if (sym->storage == LSTATIC) { print_label(sym->offset); @@ -378,12 +404,26 @@ int gen_modify_stack(int newstkp) { return (newstkp); } -/* FIXME */ +/* FIXME - interaction with register needs thought */ int gen_defer_modify_stack(int newstkp) { return gen_modify_stack(newstkp); } +int gen_register(int vp, int size, int typ) +{ + if (size != 2) + return -1; + if (nextreg > 6) + return -1; + stkp = stkp - 2; + regv[nextreg] = stkp; + output_with_tab("push r"); + output_number(nextreg); + newline(); + return nextreg++; +} + /** * multiply the primary register by INTSIZE */ @@ -739,3 +779,11 @@ void gen_multiply(int type, int size) { break; } } + +/** + * To help the optimizer know when r1/r2 are discardable + */ +void gen_statement_end(void) +{ + output_line(";end"); +} \ No newline at end of file diff --git a/Applications/SmallC/codez80.c b/Applications/SmallC/codez80.c index 8212c012..82fa3429 100644 --- a/Applications/SmallC/codez80.c +++ b/Applications/SmallC/codez80.c @@ -1,7 +1,11 @@ #include +#include #include "defs.h" #include "data.h" +static int nextreg = 0; +static int regv[8]; + /* * Some predefinitions: * @@ -31,9 +35,6 @@ void header (void) { * @return */ void newline (void) { -#if __CYGWIN__ == 1 - output_byte (CR); -#endif output_byte (LF); } @@ -117,10 +118,9 @@ void output_number(int num) { static void output_number_signed(int num) { - if (num > 0) + if (num >= 0) output_byte('+'); - else - output_decimal(num); + output_decimal(num); } static void output_bracketed(char *p) @@ -130,22 +130,68 @@ static void output_bracketed(char *p) output_byte(')'); } -static void describe_access(SYMBOL *sym) +static void describe_access(SYMBOL *sym, int s) { - if (sym->storage == LSTATIC) { + if (sym->storage == REGISTER) { + if (s == 2) + output_string("bc"); + else + output_string("c"); + } else if (sym->storage == LSTATIC) { output_byte('('); print_label(sym->offset); output_byte(')'); } else if (sym->storage == AUTO || sym->storage == DEFAUTO) { output_string("(ix"); - output_number_signed(sym->offset - stkp); + output_number_signed(sym->offset + 2); output_byte(')'); - } else + } else { + output_byte('('); output_string(sym->name); - newline(); + output_byte(')'); + } } +static void describe_access_hl(SYMBOL *sym, int d) +{ + if (sym->storage == REGISTER) { + if (d) { + output_line("ld h,b"); + output_line("ld l,c"); + } else { + output_line("ld b,h"); + output_line("ld c,l"); + } + return; + } + if (sym->storage != AUTO && sym->storage != DEFAUTO) { + output_with_tab("ld hl,"); + describe_access(sym, 2); + newline(); + return; + } + if (d) { + output_with_tab("ld l,(ix"); + output_number_signed(sym->offset + 2 ); + output_byte(')'); + newline(); + output_with_tab("ld h,(ix"); + output_number_signed(sym->offset + 3); + output_byte(')'); + newline(); + } else { + output_with_tab("ld (ix"); + output_number_signed(sym->offset + 2); + output_string("),l"); + newline(); + output_with_tab("ld (ix"); + output_number_signed(sym->offset + 3); + output_string("),h"); + newline(); + } +} + /** * fetch a static memory cell into the primary register * @param sym @@ -153,19 +199,17 @@ static void describe_access(SYMBOL *sym) void gen_get_memory(SYMBOL *sym) { if ((sym->identity != POINTER) && (sym->type == CCHAR)) { output_with_tab ("ld a,"); - output_bracketed(sym->name); - newline (); + describe_access(sym, 1); + newline(); gen_call ("ccsxt"); } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { output_with_tab("ld a,"); - output_bracketed(sym->name); + describe_access(sym, 1); newline(); output_line("ld l,a"); output_line("ld h,0"); } else { - output_with_tab ("*ld hl,"); - output_bracketed(sym->name); - newline (); + describe_access_hl(sym,1); } } @@ -199,12 +243,10 @@ void gen_put_memory(SYMBOL *sym) { if ((sym->identity != POINTER) && (sym->type & CCHAR)) { output_line ("ld a,l"); output_with_tab ("ld "); - output_bracketed(sym->name); + describe_access(sym, 1); output_string(",a"); } else { - output_with_tab("ld "); - output_bracketed(sym->name); - output_string(",hl"); + describe_access_hl(sym, 0); } newline (); } @@ -257,10 +299,10 @@ void gen_get_indirect(char typeobj, int reg) { */ int gen_indirected(SYMBOL *s) { - if (s->storage == LSTATIC) + if (s->storage == LSTATIC || s->storage == REGISTER) + return 0; + if (abs(s->offset) < 124) return 0; -/* if (abs(s->offset) < 124 && (s->type == CCHAR || s->type == UCHAR)) - return 0; */ return 1; } @@ -328,21 +370,22 @@ void declare_entry_point(char *symbol_name) { void gen_prologue(void) { -#if 0 output_line("push ix"); output_line("ld ix,#0"); output_line("add ix,sp"); stkp = stkp - INTSIZE; -#endif + nextreg = 0; } void gen_epilogue(void) { -#if 0 + if (nextreg) + gen_modify_stack(regv[0]); + output_line("pop bc"); + stkp += 2; output_line("ld sp,ix"); output_line("pop ix"); stkp = 0; -#endif } /** @@ -430,7 +473,7 @@ int gen_modify_stack(int newstkp) { k--; } while (k) { - output_line ("pop bc"); + output_line ("pop af"); k = k - INTSIZE; } return (newstkp); @@ -464,6 +507,18 @@ int gen_defer_modify_stack(int newstkp) return gen_modify_stack(newstkp); } +int gen_register(int vp, int size, int typ) +{ + if (size != 2) + return -1; + if (nextreg > 0) + return -1; + stkp = stkp - 2; + regv[nextreg] = stkp; + output_line("push bc"); + return nextreg++; +} + /** * multiply the primary register by INTSIZE */ @@ -840,3 +895,11 @@ void gen_multiply(int type, int size) { break; } } + +/** + * To help the optimizer know when r1/r2 are discardable + */ +void gen_statement_end(void) +{ + output_line(";end"); +} diff --git a/Applications/SmallC/defs.h b/Applications/SmallC/defs.h index dc28a2cb..7c83941e 100644 --- a/Applications/SmallC/defs.h +++ b/Applications/SmallC/defs.h @@ -89,6 +89,8 @@ struct tag_symbol { #define LSTATIC 5 #define DEFAUTO 6 +#define REGISTER 7 + // "do"/"for"/"while"/"switch" statement stack #define WSTABSZ 20 diff --git a/Applications/SmallC/lib/strlen.c b/Applications/SmallC/lib/strlen.c index e3bd9d48..4c328b07 100644 --- a/Applications/SmallC/lib/strlen.c +++ b/Applications/SmallC/lib/strlen.c @@ -1,7 +1,7 @@ #include /* return length of string, reference CPL p 36 */ strlen(s) char *s;{ - int i; + register int i; i = 0; while (*s++) i++; return (i); diff --git a/Applications/SmallC/prototype.h b/Applications/SmallC/prototype.h index faa24484..b72495ac 100644 --- a/Applications/SmallC/prototype.h +++ b/Applications/SmallC/prototype.h @@ -66,6 +66,8 @@ extern void gen_usigned_greater_than(void); extern void gen_unsigned_greater_or_equal(void); extern void gen_prologue(void); extern void gen_epilogue(void); +extern int gen_register(int vp, int size, int typ); +extern void gen_statement_end(void); extern char *inclib(void); extern void gnargs(int d); extern int assemble(char *s); diff --git a/Applications/SmallC/rules.6801 b/Applications/SmallC/rules.6801 new file mode 100644 index 00000000..a1bb4838 --- /dev/null +++ b/Applications/SmallC/rules.6801 @@ -0,0 +1,44 @@ +# $1 is special - it's the return path and the one case we must not eliminate +# any trailing r1 load so write out the ;end marker if we are merging it +jmp $1 +;end +$1: += +$1: + +jmp $1 +;end += +jmp $1 + +# Normal cases + +jmp %1 +;end +%1: += +;end +%1: + +ldd %1 +psha +pshb +ldd %2 +addd ,s +pulx += +ldd %2 +addd %1 + +# 6801 has no side effects so these are easy + +subd %1 +;end += +;end + + +addd %1 +;end += +;end diff --git a/Applications/SmallC/rules.6809 b/Applications/SmallC/rules.6809 index 2f543e9e..36bb931c 100644 --- a/Applications/SmallC/rules.6809 +++ b/Applications/SmallC/rules.6809 @@ -1,3 +1,17 @@ +# $1 is special - it's the return path and the one case we must not eliminate +# any trailing r1 load so write out the ;end marker if we are merging it +lbra $1 +;end +$1: += +$1: + +lbra $1 +;end += +lbra $1 + +# Normal cases # # Eliminate pointless branches # @@ -23,6 +37,101 @@ lbra %2 lbeq %2 %1: +# +# Silly entry fixup +# +pshs u +pshs y += +pshs u,y + +# +# Register fixups +# + +ldd %1 +std y += +ldy %1 + +ldd %1 +std u +ldu %1 + +tfr u,d +addd #1 +tfr d,u +subd #1 +;end += +leau 1,u +;end + +tfr y,d +addd #1 +tfr d,y +subd #1 +;end += +leay 1,y +;end + +tfr y,d +pshs d +;end += +pshs y +;end + +tfr u,d +pshs d +;end += +pshs u +;end + +tfr y,d +pshs d +ldd %1 += +pshs y +ldd %1 + +tfr u,d +pshs d +ldd %1 += +pshs u +ldd %1 + +tfr y,d +pshs d +tfr %1,d += +pshs y +tfr %1,d + +tfr u,d +pshs d +tfr %1,d += +pshs u +tfr %1,d + +ldd %1 +tfr d,u +;end += +ldu %1 +;end + +ldd %1 +tfr d,y +;end += +ldy %1 +;end + # # Fix up the stack based add and subtraction # generated by scc diff --git a/Applications/SmallC/rules.gen b/Applications/SmallC/rules.gen new file mode 100644 index 00000000..dce5a7f4 --- /dev/null +++ b/Applications/SmallC/rules.gen @@ -0,0 +1,162 @@ +# $1 is special - it's the return path and the one case we must not eliminate +# any trailing r1 load so write out the ;end marker if we are merging it +jump $1 +;end +$1: += +$1: + +jump $1 +;end += +jump $1 + +# Normal cases + +jump %1 +;end +%1: += +;end +%1: + +jumpz r1 %1 +;end +jump %2 +%1: += +jumpnz r1 %2 +;end +%1: + +jumpnz r1 %1 +;end +jump %2 +%1: += +jumpz r1 %2 +;end + +load r1 %1 +add r1 1 +store r1 %1 +sub r1 1 += +load r1 %1++ + +load r1 %1 +add r1 1 +store r1 %1 += +load r1 ++%1 + + +load r1 %1 +sub r1 1 +store r1 %1 +add r1 1 += +load r1 %1-- + +load r1 %1 +sub r1 1 +store r1 %1 += +load r1 --%1 + + +add r1 1 +loadsb r1 (r1) += +loadsb r1 (+r1) + +sub r1 1 +loadsb r1 (r1) += +loadsb r1 (-r1) + +# Fixme do rest of jumps + +test r1 +jumpnz %1 += +jumpnz r1 %1 + +test r1 +jumpz %1 += +jumpz r1 %1 + +add sp %1 +ret += +ret %1 + +load r1 %1 +store r1 r%2 +;end += +load r%2 %1 +;end + +# +# Compress simple register maths +# TODO: non add/sub cases +# + +load r1 r%1 +push r1 +load r1 %2 +popadd r1 r2 +store r1 r%1 +;end += +add r%1 %2 + +load r1 r%1 +push r1 +load r1 %2 +popsub r1 r2 +store r1 r%1 +;end += +add r%1 %2 + +# +# Similar idea for conditionals +# + +load r1 r%1 +push r1 +load r1 %2 +poplt r1 r2 += +lt r%1 %2 + +# +# Side effect only optimisations +# + +load r1 ++r%1 +;end += +inc r1 + +load r1 --r%1 +;end += +dec r1 + + + +load r1 r%1++ +;end += +inc r1 + +load r1 r%1-- +;end += +dec r1 + + diff --git a/Applications/SmallC/stmt.c b/Applications/SmallC/stmt.c index 14ea439e..91262750 100644 --- a/Applications/SmallC/stmt.c +++ b/Applications/SmallC/stmt.c @@ -28,8 +28,10 @@ int statement(int func) { } if (match ("{")) do_compound (NO); - else + else { do_statement (); + gen_statement_end(); + } return (lastst); } @@ -38,7 +40,7 @@ int statement(int func) { */ int statement_declare(void) { if (amatch("register", 8)) - do_local_declares(DEFAUTO); + do_local_declares(REGISTER); else if (amatch("auto", 4)) do_local_declares(DEFAUTO); else if (amatch("static", 6)) @@ -156,8 +158,10 @@ void do_compound(int func) { gen_modify_stack(stkp); decls = NO; } - } else + } else { do_statement (); + gen_statement_end(); + } } ncmp--; } @@ -257,18 +261,21 @@ void dofor(void) { if (!match (";")) { expression (YES); need_semicolon (); + gen_statement_end(); } generate_label (pws->case_test); if (!match (";")) { expression (YES); gen_test_jump (pws->body_tab, TRUE); gen_jump (pws->while_exit); + gen_statement_end(); need_semicolon (); } else pws->case_test = pws->body_tab; generate_label (pws->incr_def); if (!match (")")) { expression (YES); + gen_statement_end(); needbrack (")"); gen_jump (pws->case_test); } else diff --git a/Applications/SmallC/sym.c b/Applications/SmallC/sym.c index a8a13d90..1cf2fc32 100644 --- a/Applications/SmallC/sym.c +++ b/Applications/SmallC/sym.c @@ -250,13 +250,19 @@ void declare_local(int typ, int stclass, int otag) { } } } - /* FIXME: do one gen_modify_stack at the end and - some kind of align method here */ - if (stclass != LSTATIC) { - stkp = gen_defer_modify_stack(stkp - k); - add_local(sname, j, typ, stkp, AUTO); - } else + if (stclass == LSTATIC) { add_local(sname, j, typ, k, LSTATIC); + break; + } + if (stclass == REGISTER) { + int r = gen_register(j, k, typ); + if (r != -1) { + add_local(sname, j, typ, r, REGISTER); + break; + } + } + stkp = gen_defer_modify_stack(stkp - k); + add_local(sname, j, typ, stkp, AUTO); break; } if (!match(",")) -- 2.34.1