From: Alan Cox Date: Thu, 23 Jun 2016 16:47:45 +0000 (+0100) Subject: scc: add draft 6809 and 6801 code gen, fix a bug in the Z80 case X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=64f15e33536a2b1a0c11a128531ea28acfb1a6e5;p=FUZIX.git scc: add draft 6809 and 6801 code gen, fix a bug in the Z80 case --- diff --git a/Applications/SmallC/Makefile b/Applications/SmallC/Makefile index 0151e7c9..d15bf11f 100644 --- a/Applications/SmallC/Makefile +++ b/Applications/SmallC/Makefile @@ -9,13 +9,15 @@ OBJS = initials.rel data.rel error.rel expr.rel function.rel gen.rel io.rel \ OBJ_Z80 = codez80.rel OBJ_8080 = code8080.rel +OBJ_6801 = code6801.rel +OBJ_6809 = code6809.rel OBJ_COPT = copt.rel INC = data.h defs.h prototype.h OBJS_ALL = $(OBJS) $(OBJ_Z80) $(OBJ_8080) -all: scc8080 sccz80 copt +all: scc6801 scc6809 scc8080 sccz80 copt sccz80: $(OBJS) $(OBJ_Z80) $(CC) -o sccz80 --nostdio $(OBJS) $(OBJ_Z80) @@ -23,12 +25,15 @@ sccz80: $(OBJS) $(OBJ_Z80) scc8080: $(OBJS) $(OBJ_8080) $(CC) -o scc8080 --nostdio $(OBJS) $(OBJ_8080) +scc6801: $(OBJS) $(OBJ_6801) + $(CC) -o scc6801 --nostdio $(OBJS) $(OBJ_6801) + +scc6809: $(OBJS) $(OBJ_6809) + $(CC) -o scc6809 --nostdio $(OBJS) $(OBJ_6809) + copt: $(OBJ_COPT) $(CC) -o copt $(OBJ_COPT) -#scc6809: $(OBJS) -# $(CC) -o scc8080 --nostdio $(OBJS) - clean: rm -f $(OBJ) scc8080 *.rel *~ diff --git a/Applications/SmallC/code6801.c b/Applications/SmallC/code6801.c new file mode 100644 index 00000000..1374bbbf --- /dev/null +++ b/Applications/SmallC/code6801.c @@ -0,0 +1,770 @@ +#include +#include "defs.h" +#include "data.h" + +/* + * Some predefinitions: + * + * INTSIZE is the size of an integer in the target machine + * BYTEOFF is the offset of an byte within an integer on the + * target machine. (ie: 8080,pdp11 = 0, 6809 = 1, + * 360 = 3) + * This compiler assumes that an integer is the SAME length as + * a pointer - in fact, the compiler uses INTSIZE for both. + * + * For 6801 we keep the secondary as top of stack as much as possible + */ + +/** + * print all assembler info before any code is generated + */ +void header (void) { + output_string ("; Small C Z80\n;\tCoder (ac0)\n;"); + frontend_version(); + newline (); + output_line ("\t;program area SMALLC_GENERATED is RELOCATABLE"); + output_line ("\t.module SMALLC_GENERATED"); +} + +/** + * prints new line + * @return + */ +void newline (void) { + output_byte (LF); +} + +void initmac(void) { + defmac("MC6801\t1"); + defmac("smallc\t1"); +} + +/** + * Output internal generated label prefix + */ +void output_label_prefix(void) { + output_byte('$'); +} + +/** + * Output a label definition terminator + */ +void output_label_terminator (void) { + output_byte (':'); +} + +/** + * begin a comment line for the assembler + */ +void gen_comment(void) { + output_byte (';'); +} + +/** + * print any assembler stuff needed after all code + */ +void trailer(void) { + output_line (";\t.end"); +} + +/** + * text (code) segment + */ +void code_segment_gtext(void) { + output_line ("\t.text"); +} + +/** + * data segment + */ +void data_segment_gdata(void) { + output_line ("\t.data"); +} + +/** + * Output the variable symbol at scptr as an extrn or a public + * @param scptr + */ +void ppubext(SYMBOL *scptr) { + if (symbol_table[current_symbol_table_idx].storage == STATIC) return; + output_with_tab (scptr->storage == EXTERN ? ".extrn\t" : ".globl\t"); + output_string (scptr->name); + newline(); +} + +/** + * Output the function symbol at scptr as an extrn or a public + * @param scptr + */ +void fpubext(SYMBOL *scptr) { + if (scptr->storage == STATIC) return; + output_with_tab (scptr->offset == FUNCTION ? ".globl\t" : ".extrn\t"); + output_string (scptr->name); + newline (); +} + +/** + * Output a decimal number to the assembler file, with # prefix + * @param num + */ +void output_number(int num) { + output_byte('#'); + output_decimal(num); +} + +/** + * fetch a static memory cell into the primary register + * @param sym + */ +void gen_get_memory(SYMBOL *sym) { + if ((sym->identity != POINTER) && (sym->type == CCHAR)) { + output_with_tab ("ldab "); + output_string(sym->name); + output_line("sex"); + newline (); + } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { + output_with_tab("ldab "); + output_string(sym->name); + newline(); + output_line("clra"); + } else { + output_with_tab ("ldd "); + output_string(sym->name); + newline (); + } +} + +/** + * asm - fetch the address of the specified symbol into the primary register + * @param sym the symbol name + * @return which register pair contains result + */ +int gen_get_locale(SYMBOL *sym) { + if (sym->storage == LSTATIC) { + gen_immediate(); + print_label(sym->offset); + newline(); + return HL_REG; + } else { + output_line("sts _tmp"); + output_line("ldd _tmp"); + output_with_tab("add "); + output_number(sym->offset - stkp); + newline (); + return HL_REG; + } +} + +/** + * asm - store the primary register into the specified static memory cell + * @param 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); + } + newline (); +} + +/** + * store the specified object type in the primary register + * at the address in secondary register (on the top of the stack) + * @param typeobj + */ +void gen_put_indirect(char typeobj) { + gen_pop(); + if (typeobj & CCHAR) { + output_line("stab ,x"); + } else { + output_line("std ,x"); + } +} + +/** + * fetch the specified object type indirect through the primary + * register into the primary register + * @param typeobj object type + */ +void gen_get_indirect(char typeobj, int reg) { + if (typeobj == CCHAR) { + if (reg & DE_REG) { + output_line("ldab ,x"); + output_line("sex"); + } else + gen_call("_ldas_d"); + } else if (typeobj == UCHAR) { + if (reg & DE_REG) { + output_line("ldab ,x"); + output_line("clra"); + } else + gen_call("_ldau_d"); + } else { // int + if (reg & DE_REG) + output_line("ldd ,x"); + else + gen_call("_ldd_d"); + } +} + +/** + * swap the primary and secondary registers + */ +void gen_swap(void) { + gen_call("_swap"); +} + +/** + * print partial instruction to get an immediate value into + * the primary register + */ +void gen_immediate(void) { + output_with_tab ("ldd "); +} + +/** + * push the primary register onto the stack + */ +void gen_push(int reg) { + if (reg & DE_REG) { + output_line ("pshx"); + stkp = stkp - INTSIZE; + } else { + output_line ("psha"); /* Check order */ + output_line ("pshb"); + stkp = stkp - INTSIZE; + } +} + +/** + * pop the top of the stack into the secondary register + */ +void gen_pop(void) { + output_line ("pulx"); + stkp = stkp + INTSIZE; +} + +/** + * swap the primary register and the top of the stack + */ +void gen_swap_stack(void) { + output_line("std _tmp1"); + output_line("ldd ,s"); + output_line("ldx _tmp1"); + output_line("stx ,s"); +} + +/** + * call the specified subroutine name + * @param sname subroutine name + */ +void gen_call(char *sname) { + output_with_tab ("jsr "); + output_string (sname); + newline (); +} + +/** + * declare entry point + */ +void declare_entry_point(char *symbol_name) { + output_string(symbol_name); + output_label_terminator(); + //newline(); +} + +/** + * return from subroutine + */ +void gen_ret(void) { + output_line ("rts"); +} + +/** + * perform subroutine call to value on top of stack + */ +void callstk(void) { + gen_pop(); + output_line("jsr ,x"); +} + +/** + * jump to specified internal label number + * @param label the label + */ +void gen_jump(int label) +{ + output_with_tab ("jump "); + print_label (label); + newline (); +} + +/** + * test the primary register and jump if false to label + * @param label the label + * @param ft if true jnz is generated, jz otherwise + */ +void gen_test_jump(int label, int ft) +{ + output_line ("tstd"); + if (ft) + output_with_tab ("bne "); + else + output_with_tab ("beq "); + print_label (label); + newline (); +} + +/** + * print pseudo-op to define a byte + */ +void gen_def_byte(void) { + output_with_tab (".db "); +} + +/** + * print pseudo-op to define storage + */ +void gen_def_storage(void) { + output_with_tab (".ds "); +} + +/** + * print pseudo-op to define a word + */ +void gen_def_word(void) { + output_with_tab (".dw "); +} + +/** + * modify the stack pointer to the new value indicated + * @param newstkp new value + */ +int gen_modify_stack(int newstkp) { + int k; + + k = newstkp - stkp; + if (k == 0) + return (newstkp); + if (k > 0) { + if (k >= 8) { + while(k >= 2) { + output_line("pulx"); + k -= 2; + } + if (k == 1) + output_line("ins"); + return newstkp; + } else { + output_line("tsx"); + if (k > 255) { + output_line("ldab #255"); + while(k > 255) { + output_line("abx"); + k -= 255; + } + } + if (k) { + output_with_tab("ldab "); + output_number(k); + newline(); + output_line("abx"); + } + output_line("txs"); + return newstkp; + } + } else { + if (k >= -16) { + while (k <= -2) { + output_line("pshx"); + k += 2; + } + if (k == -1) + output_line("des"); + return newstkp; + } + /* TODO - must preserve AA */ + output_line("std _tmp"); + output_line("ldd "); + output_number(newstkp); + output_line("sts _tmp2"); + output_line("addd _tmp2"); + output_line("std _tmp2"); + output_line("lds _tmp2"); + output_line("ldd _tmp"); + } + return newstkp; +} + +/** + * multiply the primary register by INTSIZE + */ +void gen_multiply_by_two(void) { + output_line("aslb"); + output_line("rola"); +} + +/** + * divide the primary register by INTSIZE, never used + */ +void gen_divide_by_two(void) { + output_line("asra"); + output_line("rorb"); +} + +/** + * Case jump instruction + */ +void gen_jump_case(void) { + output_with_tab ("jmp _case"); + newline (); +} + +/** + * add the primary and secondary registers + * if lval2 is int pointer and lval is not, scale lval + * @param lval + * @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(); +} + +/** + * subtract the primary register from the secondary + */ +void gen_sub(void) { + gen_pop(); + gen_call("_sub"); +} + +/** + * multiply the primary and secondary registers (result in primary) + */ +void gen_mult(void) { + gen_pop(); + gen_call("_mul"); +} + +/** + * divide the secondary register by the primary + * (quotient in primary, remainder in secondary) + */ +void gen_div(void) { + gen_pop(); + gen_call("_div"); +} + +/** + * unsigned divide the secondary register by the primary + * (quotient in primary, remainder in secondary) + */ +void gen_udiv(void) { + gen_pop(); + gen_call("_udiv"); +} + +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) + */ +void gen_mod(void) { + gen_pop(); + gen_call("_mod"); +} + +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) + */ +void gen_umod(void) { + gen_pop(); + gen_call("_umod"); +} + +/** + * inclusive 'or' the primary and secondary registers + */ +void gen_or(void) { + output_line("orab ,s"); + output_line("oraa 1,s"); + gen_pop(); +} + +/** + * exclusive 'or' the primary and secondary registers + */ +void gen_xor(void) { + output_line("eorb ,s"); + output_line("eora 1,s"); + gen_pop(); +} + +/** + * 'and' the primary and secondary registers + */ +void gen_and(void) { + output_line("andb ,s"); + output_line("anda 1,s"); + gen_pop(); +} + +/** + * arithmetic shift right the secondary register the number of + * times in the primary register (results in primary register) + */ +void gen_arithm_shift_right(void) { + gen_pop(); + gen_call("_asr"); +} + +/** + * logically shift right the secondary register the number of + * times in the primary register (results in primary register) + */ +void gen_logical_shift_right(void) { + gen_pop(); + gen_call("_asl"); +} + +/** + * arithmetic shift left the secondary register the number of + * times in the primary register (results in primary register) + */ +void gen_arithm_shift_left(void) { + gen_pop (); + gen_call("_lsl"); +} + +/** + * two's complement of primary register + */ +void gen_twos_complement(void) { + gen_call("_neg"); +} + +/** + * logical complement of primary register + */ +void gen_logical_negation(void) { + gen_call("_lneg"); +} + +/** + * one's complement of primary register + */ +void gen_complement(void) { + output_line("coma"); + output_line("comb"); +} + +/** + * Convert primary value into logical value (0 if 0, 1 otherwise) + */ +void gen_convert_primary_reg_value_to_bool(void) { + gen_call("_bool"); +} + +/** + * increment the primary register by 1 if char, INTSIZE if int + */ +void gen_increment_primary_reg(LVALUE *lval) { + switch (lval->ptr_type) { + case STRUCT: + output_with_tab("addd "); + output_number(lval->tagsym->size); + newline(); + break ; + case CINT: + case UINT: + output_line("addd #2"); + break; + default: + output_line("addd #1"); + break; + } +} + +/** + * decrement the primary register by one if char, INTSIZE if int + */ +void gen_decrement_primary_reg(LVALUE *lval) { + switch (lval->ptr_type) { + case CINT: + case UINT: + output_line("subd #2"); + break; + case STRUCT: + output_with_tab("subd "); + output_number(lval->tagsym->size - 1); + newline(); + break ; + default: + output_line("subd #1"); + break; + } +} + +/** + * following are the conditional operators. + * they compare the secondary register against the primary register + * and put a literal 1 in the primary if the condition is true, + * otherwise they clear the primary register + */ + +/** + * equal + */ +void gen_equal(void) { + gen_pop(); + gen_call("_eq"); +} + +/** + * not equal + */ +void gen_not_equal(void) { + gen_pop(); + gen_call("_ne"); +} + +/** + * less than (signed) + */ +void gen_less_than(void) { + gen_pop(); + gen_call("_lt"); +} + +/** + * less than or equal (signed) + */ +void gen_less_or_equal(void) { + gen_pop(); + gen_call("_le"); +} + +/** + * greater than (signed) + */ +void gen_greater_than(void) { + gen_pop(); + gen_call("_gt"); +} + +/** + * greater than or equal (signed) + */ +void gen_greater_or_equal(void) { + gen_pop(); + gen_call("_ge"); +} + +/** + * less than (unsigned) + */ +void gen_unsigned_less_than(void) { + gen_pop(); + gen_call("_ult"); +} + +/** + * less than or equal (unsigned) + */ +void gen_unsigned_less_or_equal(void) { + gen_pop(); + gen_call("_ule"); +} + +/** + * greater than (unsigned) + */ +void gen_usigned_greater_than(void) { + gen_pop(); + gen_call("_ugt"); +} + +/** + * greater than or equal (unsigned) + */ +void gen_unsigned_greater_or_equal(void) { + gen_pop(); + gen_call("_uge"); +} + +char *inclib(void) { +#ifdef cpm + return("B:"); +#endif +#ifdef unix +#ifdef INCDIR + return(INCDIR); +#else + return ""; +#endif +#endif +} + +/** + * Squirrel away argument count in a register that modstk doesn't touch. + * @param d + */ +void gnargs(int d) +{ + output_with_tab ("ldaa "); + output_number(d); + newline (); +} + +/** + * print partial instruction to get an immediate value into + * the secondary register + */ +void gen_immediate2(void) { + output_with_tab ("ldx "); +} + +/** + * add offset to primary register + * @param val the value + */ +void add_offset(int val) { + output_with_tab("addd "); + output_number(val); + newline(); +} + +/** + * multiply the primary register by the length of some variable + * @param type + * @param size + */ +void gen_multiply(int type, int size) { + switch (type) { + case CINT: + case UINT: + output_line("std _tmp"); + output_line("addd _tmp"); + break; + case STRUCT: + output_with_tab("ldx "); + output_number(size); + newline(); + gen_call("_muld"); + break; + default: + break; + } +} diff --git a/Applications/SmallC/code6809.c b/Applications/SmallC/code6809.c index a9c17305..98f5c45b 100644 --- a/Applications/SmallC/code6809.c +++ b/Applications/SmallC/code6809.c @@ -1,9 +1,3 @@ -/* File codeas09.c: 2.2 (84/08/31,10:05:13) */ -/*% cc -O -c % - * - * THIS IS FROM AN OLDER VERSION OF THE COMPILER: WILL NEED PORTING - */ - #include #include "defs.h" #include "data.h" @@ -18,779 +12,711 @@ * This compiler assumes that an integer is the SAME length as * a pointer - in fact, the compiler uses INTSIZE for both. */ -#define INTSIZE 2 -#define BYTEOFF 1 - -void tab(void) -{ - output_byte('\t'); -} - -void ot(char ptr[]) -{ - tab (); - output_string (ptr); - -} - -void ol(char ptr[]) -{ - ot (ptr); - newline(); -} - - - -/* - * print all assembler info before any code is generated - * - */ -void header(void) -{ - output_string("|\tSmall C MC6809\n|\tCoder (2.4,84/11/27)\n|"); - frontend_version(); - newline(); - ol (".globl\tsmul,sdiv,smod,asr,asl,neg,lneg,case"); - ol (".globl\teq,ne,lt,le,gt,ge,ult,ule,ugt,uge,bool"); - -} - - -void initmac(void) { - defmac("mc6809\t1"); - defmac("mitas09\t1"); - defmac("smallc\t1"); - -} - -int galign(int t) -{ - return (t); - -} - -/* - * return size of an integer - */ -int intsize(void) { - return(INTSIZE); - -} -/* - * return offset of ls byte within word - * (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3) +/** + * print all assembler info before any code is generated */ -int byteoff(void) { - return(BYTEOFF); +void header (void) { + output_string ("; Small C Z80\n;\tCoder (ac0)\n;"); + frontend_version(); + newline (); + output_line ("\t;program area SMALLC_GENERATED is RELOCATABLE"); + output_line ("\t.module SMALLC_GENERATED"); } -/* - * Output internal generated label prefix +/** + * prints new line + * @return */ -void olprfix(void) { - output_string("LL"); - +void newline (void) { + output_byte (LF); } -/* - * Output a label definition terminator - */ -void col(void) -{ - output_string ("=.\n"); - +void initmac(void) { + defmac("mc6809\t1"); + defmac("smallc\t1"); } -/* - * begin a comment line for the assembler - * +/** + * Output internal generated label prefix */ -void comment(void) -{ - output_byte ('|'); - +void output_label_prefix(void) { + output_byte('_'); } -/* - * Output a prefix in front of user labels +/** + * Output a label definition terminator */ -void prefix(void) { - output_byte('_'); - +void output_label_terminator (void) { + output_byte (':'); } -/* - * print any assembler stuff needed after all code - * +/** + * begin a comment line for the assembler */ -void trailer(void) -{ - ol (".end"); - +void gen_comment(void) { + output_byte (';'); } -/* - * function prologue +/** + * print any assembler stuff needed after all code */ -void prologue(void) -{ - +void trailer(void) { + output_line (";\t.end"); } -/* - * text (code) segment +/** + * text (code) segment */ - -void gtext(void) -{ - ol (".text"); - +void code_segment_gtext(void) { + output_line ("\t.text"); } -/* - * data segment +/** + * data segment */ -void gdata(void) -{ - ol (".data"); - +void data_segment_gdata(void) { + output_line ("\t.data"); } -/* - * Output the variable symbol at scptr as an extrn or a public +/** + * Output the variable symbol at scptr as an extrn or a public + * @param scptr */ -void ppubext(char *scptr) -{ - if (scptr[STORAGE] == STATIC) - return; - ot (".globl\t"); - prefix (); - output_string (scptr); - nl(); - +void ppubext(SYMBOL *scptr) { + if (symbol_table[current_symbol_table_idx].storage == STATIC) return; + output_with_tab (scptr->storage == EXTERN ? ".extrn\t" : ".globl\t"); + output_string (scptr->name); + newline(); } -/* +/** * Output the function symbol at scptr as an extrn or a public + * @param scptr */ -void fpubext(char *scptr) { - ppubext(scptr); - +void fpubext(SYMBOL *scptr) { + if (scptr->storage == STATIC) return; + output_with_tab (scptr->offset == FUNCTION ? ".globl\t" : ".extrn\t"); + output_string (scptr->name); + newline (); } -/* - * Output a decimal number to the assembler file +/** + * Output a decimal number to the assembler file, with # prefix + * @param num */ -void onum(int num) { - output_decimal(num); /* pdp11 needs a "." here */ - output_byte('.'); +void output_number(int num) { + output_byte('#'); + output_decimal(num); } -/* - * fetch a static memory cell into the primary register +/** + * fetch a static memory cell into the primary register + * @param sym */ - -void getmem(char *sym) -{ - if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) { - ot ("ldb\t"); - prefix (); - output_string (sym + NAME); - newline(); - ot ("sex"); - newline(); - } else { - ot ("ldd\t"); - prefix (); - output_string (sym + NAME); - newline(); +void gen_get_memory(SYMBOL *sym) { + if ((sym->identity != POINTER) && (sym->type == CCHAR)) { + output_with_tab("ldb "); + output_string(sym->name); + newline (); + output_line("sex"); + } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { + output_with_tab("ldb "); + output_string(sym->name); + newline(); + output_line("clr a"); + } else { + output_with_tab ("ldd "); + output_string(sym->name); + newline (); + } +} + +/** + * asm - fetch the address of the specified symbol into the primary register + * @param sym the symbol name + * @return which register pair contains result + */ +int gen_get_locale(SYMBOL *sym) { + if (sym->storage == LSTATIC) { + gen_immediate(); + print_label(sym->offset); + newline(); + return HL_REG; + } else { + output_line("leay "); + output_number(sym->offset - stkp); + output_string("(s)"); + newline (); + output_line("tfr y,d"); + return HL_REG; + } +} + +/** + * asm - store the primary register into the specified static memory cell + * @param sym + */ +void gen_put_memory(SYMBOL *sym) { + if ((sym->identity != POINTER) && (sym->type & CCHAR)) { + output_with_tab ("stb "); + output_string(sym->name); + } else { + output_with_tab("std "); + output_string(sym->name); + } + newline (); +} + +/** + * store the specified object type in the primary register + * at the address in secondary register (on the top of the stack) + * @param typeobj + */ +void gen_put_indirect(char typeobj) { + /* pop ? */ + output_line("tfr d,y"); + if (typeobj & CCHAR) { + output_line("stb ,y"); + } else { + output_line("std ,y"); + } +} + +/** + * fetch the specified object type indirect through the primary + * register into the primary register + * @param typeobj object type + */ +void gen_get_indirect(char typeobj, int reg) { + if (typeobj == CCHAR) { + if (reg & DE_REG) { + gen_swap(); } + output_line("loadbs r1 (r1)"); + } else if (typeobj == UCHAR) { + if (reg & DE_REG) { + gen_swap(); + } + //gen_call("cguchar"); + output_line("loadbu r1 (r1)"); + } else { // int + output_line("load r1 (r1)"); + } } -/* - * fetch the address of the specified symbol into the primary register - * +/** + * swap the primary and secondary registers */ -void getloc(char *sym) -{ - if (sym[STORAGE] == LSTATIC) { - immed(); - printlabel(glint(sym)); - nl(); - } else { - ot ("leay\t"); - onum (glint(sym) - stkp); - output_string ("(s)\n\ttfr\ty,d\n"); - } - +void gen_swap(void) { + output_line("exg d,x"); } -/* - * store the primary register into the specified static memory cell - * +/** + * print partial instruction to get an immediate value into + * the primary register */ -void putmem (char *sym) -{ - if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) { - ot ("stb\t"); - } else - ot ("std\t"); - prefix (); - output_string (sym + NAME); - newline(); - +void gen_immediate(void) { + output_with_tab ("ldd "); } -/* - * store the specified object type in the primary register - * at the address on the top of the stack - * +/** + * push the primary register onto the stack */ -void putstk(char typeobj) -{ - if (typeobj == CCHAR) - ol ("stb\t@(s)++"); - else - ol ("std\t@(s)++"); - stkp = stkp + INTSIZE; - +void gen_push(int reg) { + if (reg & DE_REG) { + output_line ("pshs x"); + stkp = stkp - INTSIZE; + } else { + output_line ("pshs d"); + stkp = stkp - INTSIZE; + } } -/* - * fetch the specified object type indirect through the primary - * register into the primary register - * +/** + * pop the top of the stack into the secondary register */ -void indirect (char typeobj) -{ - ol("tfr\td,y"); - if (typeobj == CCHAR) - ol ("ldb\t(y)\n\tsex"); - else - ol ("ldd\t(y)"); - +void gen_pop(void) { + output_line ("puls x"); + stkp = stkp + INTSIZE; } -/* - * swap the primary and secondary registers - * +/** + * swap the primary register and the top of the stack */ -void swap(void) -{ - ol ("exg\td,x"); - +void gen_swap_stack(void) { + output_line("ldy (s)"); + output_line("std (s)"); + output_line("tfr y,d"); } -/* - * print partial instruction to get an immediate value into - * the primary register - * +/** + * call the specified subroutine name + * @param sname subroutine name */ -void immed(void) -{ - ot ("ldd\t#"); - +void gen_call(char *sname) { + output_with_tab ("jsr "); + output_string (sname); + newline (); } -/* - * push the primary register onto the stack - * +/** + * declare entry point */ -void gpush(void) -{ - ol ("pshs\td"); - stkp = stkp - INTSIZE; - +void declare_entry_point(char *symbol_name) { + output_string(symbol_name); + output_label_terminator(); + //newline(); } -/* - * pop the top of the stack into the secondary register - * +/** + * return from subroutine */ -void gpop(void) -{ - ol ("puls\td"); - stkp = stkp + INTSIZE; - +void gen_ret(void) { + output_line ("rts"); } -/* - * swap the primary register and the top of the stack - * +/** + * perform subroutine call to value on top of stack */ -void swapstk(void) -{ - ol ("ldy\t(s)\nstd\t(s)\n\ttfr\ty,d"); - +void callstk(void) { + output_line ("jsr (x)"); } -/* - * call the specified subroutine name - * +/** + * jump to specified internal label number + * @param label the label */ -void gcall(char *sname) +void gen_jump(int label) { - ot ("jsr\t"); - if (*sname == '^') - output_string (++sname); - else { - prefix (); - output_string (sname); - } - newline(); - + output_with_tab ("lbra "); + print_label (label); + newline (); } -/* - * return from subroutine - * +/** + * test the primary register and jump if false to label + * @param label the label + * @param ft if true jnz is generated, jz otherwise */ -void gret(void) +void gen_test_jump(int label, int ft) { - ol ("rts"); - + output_line ("cmpd #0"); + if (ft) + output_with_tab ("lbne "); + else + output_with_tab ("lbeq "); + print_label (label); + newline (); } -/* - * perform subroutine call to value on top of stack - * +/** + * print pseudo-op to define a byte */ -void callstk(void) -{ - gpop(); - ol("jsr\t(x)"); - +void gen_def_byte(void) { + output_with_tab (".byte "); } -/* - * jump to specified internal label number - * +/** + * print pseudo-op to define storage */ -void jump(int label) -{ - ot ("lbra\t"); - printlabel(label); - nl(); - +void gen_def_storage(void) { + output_with_tab (".blkb "); } -/* - * test the primary register and jump if false to label - * +/** + * print pseudo-op to define a word */ -void testjump (int label, int ft) -{ - ol ("cmpd\t#0"); - if (ft) - ot ("lbne\t"); - else - ot ("lbeq\t"); - printlabel (label); - newline(); - +void gen_def_word(void) { + output_with_tab (".word "); } -/* - * print pseudo-op to define a byte - * +/** + * modify the stack pointer to the new value indicated + * @param newstkp new value */ -void defbyte(void) -{ - ot (".byte\t"); +int gen_modify_stack(int newstkp) { + int k; + k = newstkp - stkp; + if (k == 0) + return (newstkp); + output_with_tab("leas "); + output_decimal(k); + output_string("(s)"); + newline(); + return (newstkp); } -/* - * print pseudo-op to define storage - * +/** + * multiply the primary register by INTSIZE */ -void defstorage(void) -{ - ot (".blkb\t"); - +void gen_multiply_by_two(void) { + output_line("aslb"); + output_line("rola"); } -/* - * print pseudo-op to define a word - * +/** + * divide the primary register by INTSIZE, never used */ - -void defword(void) -{ - ot (".word\t"); - +void gen_divide_by_two(void) { + output_line("asra"); + output_line("rorb"); } -/* - * modify the stack pointer to the new value indicated - * +/** + * Case jump instruction */ -void modstk(int newstkp) -{ - int k; - - k = galign(newstkp - stkp); - if (k == 0) - return (newstkp); - ot ("leas\t"); - onum (k); - output_string ("(s)\n"); - return (newstkp); - +void gen_jump_case(void) { + output_with_tab ("jump cccase"); + newline (); } -/* - * multiply the primary register by INTSIZE +/** + * add the primary and secondary registers + * if lval2 is int pointer and lval is not, scale lval + * @param lval + * @param lval2 */ -void gaslint(void) -{ - ol ("aslb\n\trola"); - +void gen_add(LVALUE *lval, LVALUE *lval2) { + if (dbltest (lval2, lval)) { + output_line("asl 1(s)"); + output_line("rol (s)"); + } + output_line ("addd (s)++"); + stkp += INTSIZE; } -/* - * divide the primary register by INTSIZE +/** + * subtract the primary register from the secondary */ -void gasrint(void) -{ - ol ("asra\n\trorb"); - +void gen_sub(void) { + /* Double check */ + output_line("subd (s)++"); + output_line("coma"); + output_line("comb"); + output_line("addd #1"); + stkp += INTSIZE; } -/* - * Case jump instruction +/** + * multiply the primary and secondary registers (result in primary) */ -void gjcase(void) { - ot ("jmp\tcase"); - newline(); - +void gen_mult(void) { + gen_pop(); + gen_call ("__mul"); } -/* - * add the primary and secondary registers - * if lval2 is int pointer and lval is int, scale lval +/** + * divide the secondary register by the primary + * (quotient in primary, remainder in secondary) */ -void gadd (LVALUE *lval, LVALUE *lval2) -{ - if (dbltest (lval2, lval)) { - ol ("asl\t1(s)\n\trol\t(s)"); - } - ol ("addd\t(s)++"); - stkp = stkp + INTSIZE; - +void gen_div(void) { + gen_pop(); + output_line("__div"); } -/* - * subtract the primary register from the secondary - * +/** + * unsigned divide the secondary register by the primary + * (quotient in primary, remainder in secondary) */ -void gsub(void) -{ - ol ("subd\t(s)++\n\tcoma\n\tcomb\n\taddd\t#1"); - stkp = stkp + INTSIZE; - +void gen_udiv(void) { + gen_pop(); + output_line("__udiv"); } -/* - * multiply the primary and secondary registers - * (result in primary) - * +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) */ -void gmult(void) -{ - gcall ("^smul"); - stkp = stkp + INTSIZE; - +void gen_mod(void) { + gen_pop(); + output_line("__mod"); } -/* - * divide the secondary register by the primary - * (quotient in primary, remainder in secondary) - * +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) */ -void gdiv(void) -{ - gcall ("^sdiv"); - stkp = stkp + INTSIZE; - +void gen_umod(void) { + gen_pop(); + output_line("__umod"); } -/* - * compute the remainder (mod) of the secondary register - * divided by the primary register - * (remainder in primary, quotient in secondary) - * +/** + * inclusive 'or' the primary and secondary registers */ -void gmod(void) -{ - gcall ("^smod"); - stkp = stkp + INTSIZE; - +void gen_or(void) { + output_line("ora (s)+"); + output_line("orb (s)+"); + stkp += INTSIZE; } -/* - * inclusive 'or' the primary and secondary registers - * +/** + * exclusive 'or' the primary and secondary registers */ -void gor(void) -{ - ol ("ora\t(s)+\n\torb\t(s)+"); - stkp = stkp + INTSIZE; - +void gen_xor(void) { + output_line("eora (s)+"); + output_line("eorb (s)+"); + stkp += INTSIZE; } -/* - * exclusive 'or' the primary and secondary registers - * +/** + * 'and' the primary and secondary registers */ -void gxor(void) -{ - ol ("eora\t(s)+\n\teorb\t(s)+"); - stkp = stkp + INTSIZE; - +void gen_and(void) { + output_line("anda (s)+"); + output_line("andb (s)+"); + stkp += INTSIZE; } -/* - * 'and' the primary and secondary registers - * +/** + * arithmetic shift right the secondary register the number of + * times in the primary register (results in primary register) */ -void gand(void) -{ - ol ("anda\t(s)+\n\tandb\t(s)+"); - stkp = stkp + INTSIZE; - +void gen_arithm_shift_right(void) { + gen_call("__asr"); + stkp += INTSIZE; } -/* - * arithmetic shift right the secondary register the number of - * times in the primary register - * (results in primary register) - * +/** + * logically shift right the secondary register the number of + * times in the primary register (results in primary register) */ -void gasr(void) -{ - gcall ("^asr"); - stkp = stkp + INTSIZE; - +void gen_logical_shift_right(void) { + gen_call("__lsr"); + stkp += INTSIZE; } -/* - * arithmetic shift left the secondary register the number of - * times in the primary register - * (results in primary register) - * +/** + * arithmetic shift left the secondary register the number of + * times in the primary register (results in primary register) */ -void gasl(void) -{ - gcall ("^asl"); - stkp = stkp + INTSIZE; - +void gen_arithm_shift_left(void) { + gen_call("__lsl"); + stkp += INTSIZE; } -/* - * two's complement of primary register - * +/** + * two's complement of primary register */ -void gneg(void) -{ - gcall ("^neg"); - +void gen_twos_complement(void) { + gen_call("__neg"); } -/* - * logical complement of primary register - * +/** + * logical complement of primary register */ -void glneg(void) -{ - gcall ("^lneg"); - +void gen_logical_negation(void) { + gen_call("__lneg"); } -/* - * one's complement of primary register - * +/** + * one's complement of primary register */ -void gcom(void) -{ - ol ("coma\n\tcomb"); - +void gen_complement(void) { + output_line("coma"); + output_line("comb"); } -/* - * convert primary register into logical value - * +/** + * Convert primary value into logical value (0 if 0, 1 otherwise) */ -void gbool(void) -{ - gcall ("^bool"); +void gen_convert_primary_reg_value_to_bool(void) { + gen_call("__bool"); } -/* - * increment the primary register by 1 if char, INTSIZE if - * int +/** + * increment the primary register by 1 if char, INTSIZE if int */ -void ginc (int lval[]) -{ - if (lval[2] == CINT) - ol ("addd\t#2"); - else - ol ("addd\t#1"); - +void gen_increment_primary_reg(LVALUE *lval) { + switch (lval->ptr_type) { + case STRUCT: + output_with_tab("addd "); + output_number(lval->tagsym->size); + newline(); + break ; + case CINT: + case UINT: + output_line("addd #2"); + break; + default: + output_line("addd #1"); + break; + } } -/* - * decrement the primary register by one if char, INTSIZE if - * int +/** + * decrement the primary register by one if char, INTSIZE if int */ -void gdec(int lval[]) -{ - if (lval[2] == CINT) - ol ("subd\t#2"); - else - ol ("subd\t#1"); - +void gen_decrement_primary_reg(LVALUE *lval) { + switch (lval->ptr_type) { + case CINT: + case UINT: + output_line("subd #2"); + break; + case STRUCT: + output_with_tab("subd "); + output_number(lval->tagsym->size - 1); + newline(); + break ; + default: + output_line("subd #1"); + break; + } } -/* - * following are the conditional operators. - * they compare the secondary register against the primary register - * and put a literl 1 in the primary if the condition is true, - * otherwise they clear the primary register - * +/** + * following are the conditional operators. + * they compare the secondary register against the primary register + * and put a literal 1 in the primary if the condition is true, + * otherwise they clear the primary register */ -/* - * equal - * +/** + * equal */ -void geq(void) -{ - gcall ("^eq"); - stkp = stkp + INTSIZE; - +void gen_equal(void) { + gen_call("__eq"); + stkp += INTSIZE; } -/* - * not equal - * +/** + * not equal */ -void gne(void) -{ - gcall ("^ne"); - stkp = stkp + INTSIZE; - +void gen_not_equal(void) { + gen_call("__ne"); + stkp += INTSIZE; } -/* - * less than (signed) - * +/** + * less than (signed) */ -void glt(void) -{ - gcall ("^lt"); - stkp = stkp + INTSIZE; +void gen_less_than(void) { + gen_call("__lt"); + stkp += INTSIZE; } -/* - * less than or equal (signed) - * +/** + * less than or equal (signed) */ -void gle(void) -{ - gcall ("^le"); - stkp = stkp + INTSIZE; - +void gen_less_or_equal(void) { + gen_call("__le"); + stkp += INTSIZE; } -/* - * greater than (signed) - * +/** + * greater than (signed) */ -void ggt(void) -{ - gcall ("^gt"); - stkp = stkp + INTSIZE; - +void gen_greater_than(void) { + gen_call("__gt"); + stkp += INTSIZE; } -/* - * greater than or equal (signed) - * +/** + * greater than or equal (signed) */ -void gge(void) -{ - gcall ("^ge"); - stkp = stkp + INTSIZE; - +void gen_greater_or_equal(void) { + gen_call("__ge"); + stkp += INTSIZE; } -/* - * less than (unsigned) - * +/** + * less than (unsigned) */ -void gult(void) -{ - gcall ("^ult"); - stkp = stkp + INTSIZE; - +void gen_unsigned_less_than(void) { + gen_call("__ult"); + stkp += INTSIZE; } -/* - * less than or equal (unsigned) - * +/** + * less than or equal (unsigned) */ -void gule(void) -{ - gcall ("^ule"); - stkp = stkp + INTSIZE; - +void gen_unsigned_less_or_equal(void) { + gen_call("__ule"); + stkp += INTSIZE; } -/* - * greater than (unsigned) - * +/** + * greater than (unsigned) */ -void gugt(void) -{ - gcall ("^ugt"); - stkp = stkp + INTSIZE; - +void gen_usigned_greater_than(void) { + gen_call("__ugt"); + stkp += INTSIZE; } -/* - * greater than or equal (unsigned) - * +/** + * greater than or equal (unsigned) */ -void guge(void) -{ - gcall ("^uge"); - stkp = stkp + INTSIZE; - +void gen_unsigned_greater_or_equal(void) { + gen_call("__uge"); + stkp += INTSIZE; } char *inclib(void) { -#ifdef flex - return("B."); +#ifdef cpm + return("B:"); #endif #ifdef unix +#ifdef INCDIR return(INCDIR); +#else + return ""; #endif -#ifdef cpm - return("B:"); #endif - } -/* Squirrel away argument count in a register that modstk/getloc/stloc - doesn't touch. -*/ - +/** + * Squirrel away argument count in a register that modstk doesn't touch. + * @param d + */ void gnargs(int d) { - ot ("ldu\t#"); - onum(d); - newline(); - + output_with_tab ("ldu "); + output_number(d); + newline (); +} + +/** + * print partial instruction to get an immediate value into + * the secondary register + */ +void gen_immediate2(void) { + output_with_tab ("ldx "); +} + +/** + * add offset to primary register + * @param val the value + */ +void add_offset(int val) { + output_with_tab("addd "); + output_number(val); + newline(); +} + +/** + * multiply the primary register by the length of some variable + * @param type + * @param size + */ +void gen_multiply(int type, int size) { + switch (type) { + case CINT: + case UINT: + gen_multiply_by_two(); + output_line("mul r1 2"); + break; + case STRUCT: + output_with_tab("ldy "); + output_number(size); + newline(); + gen_call("__muli "); + newline(); + break; + default: + break; + } } diff --git a/Applications/SmallC/codez80.c b/Applications/SmallC/codez80.c index 0eb216d4..68a83b71 100644 --- a/Applications/SmallC/codez80.c +++ b/Applications/SmallC/codez80.c @@ -203,7 +203,7 @@ void gen_put_indirect(char typeobj) { gen_pop (); if (typeobj & CCHAR) { //gen_call("ccpchar"); - output_line("ld l,a"); + output_line("ld a,l"); output_line("ld (de),a"); } else { gen_call("ccpint"); diff --git a/Applications/SmallC/foo.c b/Applications/SmallC/foo.c deleted file mode 100644 index 6f189da0..00000000 --- a/Applications/SmallC/foo.c +++ /dev/null @@ -1,2 +0,0 @@ -poop() -