From 88488dd171468835e7eac22bd2dab67f39d4f819 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 23 Jun 2016 13:12:35 +0100 Subject: [PATCH] cc: initial Z80 support --- Applications/SmallC/6809/ccstart.u | 25 + Applications/SmallC/6809/crunas09.u | 85 +++ Applications/SmallC/6809/exit.u | 3 + Applications/SmallC/6809/faults.u | 10 + Applications/SmallC/6809/io.u | 28 + Applications/SmallC/6809/mrabs.u | 26 + Applications/SmallC/6809/prabs.u | 27 + Applications/SmallC/6809/sdiv.u | 55 ++ Applications/SmallC/6809/shift.u | 32 ++ Applications/SmallC/6809/smod.u | 54 ++ Applications/SmallC/6809/sumul.u | 32 ++ Applications/SmallC/8080/arglist.c | 2 +- Applications/SmallC/Makefile | 19 +- Applications/SmallC/code6809.c | 7 - Applications/SmallC/code8080.c | 6 - Applications/SmallC/codez80.c | 796 ++++++++++++++++++++++++++++ Applications/SmallC/defs.h | 4 +- Applications/SmallC/lib/Makefile | 34 ++ Applications/SmallC/lib/lorder8080 | 12 + Applications/SmallC/preproc.c | 4 + 20 files changed, 1238 insertions(+), 23 deletions(-) create mode 100644 Applications/SmallC/6809/ccstart.u create mode 100644 Applications/SmallC/6809/crunas09.u create mode 100644 Applications/SmallC/6809/exit.u create mode 100644 Applications/SmallC/6809/faults.u create mode 100644 Applications/SmallC/6809/io.u create mode 100644 Applications/SmallC/6809/mrabs.u create mode 100644 Applications/SmallC/6809/prabs.u create mode 100644 Applications/SmallC/6809/sdiv.u create mode 100644 Applications/SmallC/6809/shift.u create mode 100644 Applications/SmallC/6809/smod.u create mode 100644 Applications/SmallC/6809/sumul.u create mode 100644 Applications/SmallC/codez80.c create mode 100644 Applications/SmallC/lib/Makefile create mode 100644 Applications/SmallC/lib/lorder8080 diff --git a/Applications/SmallC/6809/ccstart.u b/Applications/SmallC/6809/ccstart.u new file mode 100644 index 00000000..ffeb176e --- /dev/null +++ b/Applications/SmallC/6809/ccstart.u @@ -0,0 +1,25 @@ +| Run-time start off for ccv1 on the Physics 6809 +.globl _edata +.globl _main +| Initialize stack + lds #/1000 + ldx #_edata | clear all of memory +l2: clr (x)+ + cmpx #/0fff + bne l2 +| Circumvent EPROM bug + ldx #/ff3b + ldb #6 +l1: pshs x + decb + bne l1 +| clear everything so that start conds are +| always same + clra + clrb + tfr a,dp + tfr d,x + tfr d,y + tfr d,u + jsr _main + jmp /fc00 diff --git a/Applications/SmallC/6809/crunas09.u b/Applications/SmallC/6809/crunas09.u new file mode 100644 index 00000000..4b20f81e --- /dev/null +++ b/Applications/SmallC/6809/crunas09.u @@ -0,0 +1,85 @@ +| csa09 Small C v1 comparison support +| All are dyadic except for lneg. +.globl eq +.globl ne +.globl lt +.globl le +.globl gt +.globl ge +.globl ult +.globl ule +.globl ugt +.globl uge +.globl lneg +.globl bool +.globl _eend,_edata,_etext +.globl _Xstktop,_brkend + +eq: cmpd 2(s) + lbeq true + lbra false + +ne: cmpd 2(s) + lbne true + lbra false + +lt: cmpd 2(s) + bgt true + bra false + +le: cmpd 2(s) + bge true + bra false + +gt: cmpd 2(s) + blt true + bra false + +ge: cmpd 2(s) + ble true + bra false + +ult: cmpd 2(s) + bhi true + bra false + +ule: cmpd 2(s) + bhs true + bra false + +ugt: cmpd 2(s) + blo true + bra false + +uge: cmpd 2(s) + bls true + bra false + +lneg: cmpd #0 + beq ltrue + ldd #0 + rts +ltrue: ldd #1 + rts + +bool: bsr lneg + bra lneg + +true: ldd #1 + ldx (s) + leas 4(s) + jmp (x) + +false: clra + clrb + ldx (s) + leas 4(s) + jmp (x) +_Xstktop: tfr s,d + rts +_etext = . + .bss +_eend = . + .data +_brkend: .wval _eend +_edata = . diff --git a/Applications/SmallC/6809/exit.u b/Applications/SmallC/6809/exit.u new file mode 100644 index 00000000..423fd67b --- /dev/null +++ b/Applications/SmallC/6809/exit.u @@ -0,0 +1,3 @@ +| Small C v1 exit routine (physics computer) +.globl _exit +_exit: jmp /fc00 diff --git a/Applications/SmallC/6809/faults.u b/Applications/SmallC/6809/faults.u new file mode 100644 index 00000000..6e7db80d --- /dev/null +++ b/Applications/SmallC/6809/faults.u @@ -0,0 +1,10 @@ +| MC6809 Concurrent Euclid fault codes +ASSERTFAIL = 0 +RANGECHECK = 1 +CASERANGE = 2 +| fault codes for runtime routines +OUTOFSPACE = 20 +.globl ASSERTFAIL +.globl RANGECHECK +.globl CASERANGE +.globl OUTOFSPACE diff --git a/Applications/SmallC/6809/io.u b/Applications/SmallC/6809/io.u new file mode 100644 index 00000000..1f3a63f3 --- /dev/null +++ b/Applications/SmallC/6809/io.u @@ -0,0 +1,28 @@ +| Small C v1 io (putchar) for physics machine +.globl _putchar +_putchar=. + lda /9000 + bita #2 + beq _putchar + lda 3(s) + sta /9001 + cmpa #10. + bne out + ldd #13. + pshs d + lbsr _putchar + leas 2(s) +out: rts + +.globl _getchar +_getchar=. + lda /9000 + bita #1 + beq _getchar + ldb /9001 + clra + andb #/7F + cmpb #04 + bne noteot + ldd #-1 +noteot: rts diff --git a/Applications/SmallC/6809/mrabs.u b/Applications/SmallC/6809/mrabs.u new file mode 100644 index 00000000..97f06624 --- /dev/null +++ b/Applications/SmallC/6809/mrabs.u @@ -0,0 +1,26 @@ +| mrabs. converts both args to unsigned, and +| remembers result sign as the sign of the left +| argument. (for signed modulo) +| result d contains right, sign is non-zero +| if result (from mod) should be negative. +| +| +.globl mrabs + left=8. + right=4. + sign=3. +mrabs: clr sign(s) + ldd left(s) + bge tryr + nega + negb + sbca #0 + std left(s) + inc sign(s) +tryr: ldd right(s) + bge done + nega + negb + sbca #0 + std right(s) +done: rts diff --git a/Applications/SmallC/6809/prabs.u b/Applications/SmallC/6809/prabs.u new file mode 100644 index 00000000..40b6dc85 --- /dev/null +++ b/Applications/SmallC/6809/prabs.u @@ -0,0 +1,27 @@ +| prabs. converts both args to unsigned, and +| remembers result sign as sign a eor sign b +| used only by divide support +| result d contains right, sign is non-zero +| if result (from divide) should be negative. +| +| +.globl prabs + left=8. + right=4. + sign=3. +prabs: clr sign(s) + ldd left(s) + bge tryr + nega + negb + sbca #0 + std left(s) + inc sign(s) +tryr: ldd right(s) + bge done + nega + negb + sbca #0 + dec sign(s) + std right(s) +done: rts diff --git a/Applications/SmallC/6809/sdiv.u b/Applications/SmallC/6809/sdiv.u new file mode 100644 index 00000000..3b177707 --- /dev/null +++ b/Applications/SmallC/6809/sdiv.u @@ -0,0 +1,55 @@ +| signed divide +| calling: (left / right) +| push left +| ldd right +| jsr sdiv +| result in d, arg popped. +| + left=6 + right=2 + sign=1 + count=0 + return=4 + CARRY=1 +.globl sdiv,div,ASSERTFAIL +.globl prabs +sdiv: leas -4(s) + std right(s) + bne nozero + swi2 + .byte ASSERTFAIL +nozero: jsr prabs +div: clr count(s) | prescale divisor + inc count(s) +mscl: inc count(s) + aslb + rola + bpl mscl + std right(s) + ldd left(s) + clr left(s) + clr left+1 (s) +div1: subd right(s) | check subtract + bcc div2 + addd right(s) + andcc #~CARRY + bra div3 +div2: orcc #CARRY +div3: rol left+1 (s) | roll in carry + rol left(s) + lsr right(s) + ror right+1 (s) + dec count(s) + bne div1 + ldd left(s) + tst sign(s) | sign fiddle + beq nochg + nega + negb + sbca #0 +nochg: std right(s) | move return addr + ldd return(s) + std left(s) + ldd right(s) + leas 6(s) + rts diff --git a/Applications/SmallC/6809/shift.u b/Applications/SmallC/6809/shift.u new file mode 100644 index 00000000..0ced5ec6 --- /dev/null +++ b/Applications/SmallC/6809/shift.u @@ -0,0 +1,32 @@ +| Shift support for Small C v1 sa09 +.globl asr +asr: tstb + bge okr + negb + bra asl +okr: incb + pshs b + ldd 3(s) +asrl: dec (s) + beq return + asra + rorb + bra asrl + +.globl asl +asl: tstb + bge okl + negb + bra asr +okl: incb + pshs b + ldd 3(s) +asll: dec (s) + beq return + aslb + rola + bra asll + +return: ldx 1(s) + leas 5(s) + jmp (x) diff --git a/Applications/SmallC/6809/smod.u b/Applications/SmallC/6809/smod.u new file mode 100644 index 00000000..737cb900 --- /dev/null +++ b/Applications/SmallC/6809/smod.u @@ -0,0 +1,54 @@ +| signed mod +| calling: (left / right) +| push left +| ldd right +| jsr smod +| result in d, arg popped. +| + left=6 + right=2 + sign=1 + count=0 + return=4 + CARRY=1 +.globl smod,mod,ASSERTFAIL +.globl mrabs +smod: leas -4(s) + std right(s) + bne nozero + swi2 + .byte ASSERTFAIL +nozero: jsr mrabs +mod: clr count(s) | prescale divisor + inc count(s) +mscl: inc count(s) + aslb + rola + bpl mscl + std right(s) + ldd left(s) + clr left(s) + clr left+1 (s) +mod1: subd right(s) | check subtract + bcc mod2 + addd right(s) + andcc #~CARRY + bra mod3 +mod2: orcc #CARRY +mod3: rol left+1 (s) | roll in carry + rol left(s) + lsr right(s) + ror right+1 (s) + dec count(s) + bne mod1 + tst sign(s) | sign fiddle + beq nochg + nega + negb + sbca #0 +nochg: std right(s) | move return addr + ldd return(s) + std left(s) + ldd right(s) + leas 6(s) + rts diff --git a/Applications/SmallC/6809/sumul.u b/Applications/SmallC/6809/sumul.u new file mode 100644 index 00000000..806c9ca8 --- /dev/null +++ b/Applications/SmallC/6809/sumul.u @@ -0,0 +1,32 @@ +| signed/unsigned multiply +| calling (left * right) +| push left +| ldd right +| jsr [u|s]mul (same entry point) +| result in d, stack is popped +.globl smul,umul +smul=. +umul: pshs d + lda 2+2 (s) + mul | left msb * right lsb + pshs b | save high order + ldb -1+3 (s) | right lsb + lda 3+3 (s) | left lsb + mul + pshs d + lda 3+5 (s) | left lsb + ldb -2+5 (s) | right msb + beq small | is zero? + mul | no, gotta do it too + tfr b,a + clrb + addd (s)++ | partial prod + bra big +small: puls d | aha! don't need third mul +big: adda (s)+ + pshs d + ldd 4(s) | rearrange return address + std 6(s) + puls d + leas 4(s) + rts diff --git a/Applications/SmallC/8080/arglist.c b/Applications/SmallC/8080/arglist.c index f747b465..a0ac3021 100644 --- a/Applications/SmallC/8080/arglist.c +++ b/Applications/SmallC/8080/arglist.c @@ -10,7 +10,7 @@ int Xargv[30]; Xarglist(ap) char *ap; { char qc; Xargc = 0; - ap[(*ap)+1 ] = '\0'; + ap[(*ap)+1] = '\0'; ap++; while (isspace(*ap)) ap++; Xargv[Xargc++] = "arg0"; diff --git a/Applications/SmallC/Makefile b/Applications/SmallC/Makefile index 29b30e7b..83c1160f 100644 --- a/Applications/SmallC/Makefile +++ b/Applications/SmallC/Makefile @@ -1,19 +1,26 @@ .SUFFIXES: .c .rel CC = fcc -CFLAGS = -DTINY -DM8080 +CFLAGS = -DTINY COPT = -O2 OBJS = initials.rel data.rel error.rel expr.rel function.rel gen.rel io.rel lex.rel main.rel preproc.rel \ - primary.rel stmt.rel sym.rel while.rel code6809.rel code8080.rel struct.rel + primary.rel stmt.rel sym.rel while.rel struct.rel + +OBJ_Z80 = codez80.rel +OBJ_8080 = code8080.rel INC = data.h defs.h prototype.h -all: scc8080 +OBJS_ALL = $(OBJS) $(OBJ_Z80) $(OBJ_8080) +all: scc8080 sccz80 + +sccz80: $(OBJS) $(OBJ_Z80) + $(CC) -o sccz80 --nostdio $(OBJS) $(OBJ_Z80) -scc8080: $(OBJS) - $(CC) -o scc8080 --nostdio $(OBJS) +scc8080: $(OBJS) $(OBJ_8080) + $(CC) -o scc8080 --nostdio $(OBJS) $(OBJ_8080) #scc6809: $(OBJS) # $(CC) -o scc8080 --nostdio $(OBJS) @@ -24,4 +31,4 @@ clean: .c.rel: $(CC) $(COPT) $(CFLAGS) -c $< -o $@ -$(OBJS) : $(INC) +$(OBJS_ALL) : $(INC) diff --git a/Applications/SmallC/code6809.c b/Applications/SmallC/code6809.c index b4762f70..a9c17305 100644 --- a/Applications/SmallC/code6809.c +++ b/Applications/SmallC/code6809.c @@ -8,11 +8,6 @@ #include "defs.h" #include "data.h" -#ifdef M6809 - -/* Define ASNM and LDNM to the names of the assembler and linker - respectively */ - /* * Some predefinitions: * @@ -799,5 +794,3 @@ void gnargs(int d) newline(); } - -#endif diff --git a/Applications/SmallC/code8080.c b/Applications/SmallC/code8080.c index 847ff5cd..8cac7025 100644 --- a/Applications/SmallC/code8080.c +++ b/Applications/SmallC/code8080.c @@ -7,11 +7,6 @@ #include "defs.h" #include "data.h" -#ifdef M8080 - -/* Define ASNM and LDNM to the names of the assembler and linker - respectively */ - /* * Some predefinitions: * @@ -795,4 +790,3 @@ void gen_multiply(int type, int size) { } } -#endif diff --git a/Applications/SmallC/codez80.c b/Applications/SmallC/codez80.c new file mode 100644 index 00000000..0eb216d4 --- /dev/null +++ b/Applications/SmallC/codez80.c @@ -0,0 +1,796 @@ +#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. + */ + +/** + * 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"); + output_line ("\t.list (err, loc, bin, eqt, cyc, lin, src, lst, md)"); + output_line ("\t.nlist (pag)"); +} + +/** + * prints new line + * @return + */ +void newline (void) { +#if __CYGWIN__ == 1 + output_byte (CR); +#endif + output_byte (LF); +} + +void initmac(void) { + defmac("cpm\t1"); + defmac("Z80\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.area SMALLC_GENERATED (REL,CON,CSEG)"); +} + +/** + * data segment + */ +void data_segment_gdata(void) { + output_line ("\t.area SMALLC_GENERATED_DATA (REL,CON,DSEG)"); +} + +/** + * 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); +} + +static void output_bracketed(char *p) +{ + output_byte('('); + output_string(p); + output_byte(')'); +} + +/** + * 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 ("ld a,"); + output_bracketed(sym->name); + newline (); + gen_call ("ccsxt"); + } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { + output_with_tab("ld a,"); + output_bracketed(sym->name); + newline(); + output_line("ld l,a"); + output_line("ld h,0"); + } else { + output_with_tab ("ld hl,"); + output_bracketed(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(); + output_byte('('); + print_label(sym->offset); + output_byte(')'); + newline(); + return HL_REG; + } else { + if (uflag && !(sym->identity == ARRAY)) {// || + //(sym->identity == VARIABLE && sym->type == STRUCT))) { + output_with_tab("ldsi\t"); + output_number(sym->offset - stkp); + newline (); + return DE_REG; + } else { + gen_immediate(); + output_number(sym->offset - stkp); + newline (); + output_line ("add hl, sp"); + 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_line ("ld a,l"); + output_with_tab ("ld "); + output_bracketed(sym->name); + output_string(",a"); + } else { + output_with_tab("ld "); + output_bracketed(sym->name); + output_string(",hl"); + } + 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) { + //gen_call("ccpchar"); + output_line("ld l,a"); + output_line("ld (de),a"); + } else { + gen_call("ccpint"); + } +} + +/** + * 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(); + } + gen_call("ccgchar"); + } else if (typeobj == UCHAR) { + if (reg & DE_REG) { + gen_swap(); + } + //gen_call("cguchar"); + output_line("ld l,(hl)"); + output_line("ld h,0"); + } else { // int + if (uflag) { + if (reg & HL_REG) { + gen_swap(); + } + output_line("lhlx"); + } else { + output_line("ld a,(hl)"); + output_line("inc hl"); + output_line("ld h,(hl)"); + output_line("ld l,a"); + } + } +} + +/** + * swap the primary and secondary registers + */ +void gen_swap(void) { + output_line("ex de,hl"); +} + +/** + * print partial instruction to get an immediate value into + * the primary register + */ +void gen_immediate(void) { + output_with_tab ("ld hl,"); +} + +/** + * push the primary register onto the stack + */ +void gen_push(int reg) { + if (reg & DE_REG) { + output_line ("push de"); + stkp = stkp - INTSIZE; + } else { + output_line ("push hl"); + stkp = stkp - INTSIZE; + } +} + +/** + * pop the top of the stack into the secondary register + */ +void gen_pop(void) { + output_line ("pop de"); + stkp = stkp + INTSIZE; +} + +/** + * swap the primary register and the top of the stack + */ +void gen_swap_stack(void) { + output_line ("ex (sp),hl"); +} + +/** + * call the specified subroutine name + * @param sname subroutine name + */ +void gen_call(char *sname) { + output_with_tab ("call "); + 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 ("ret"); +} + +/** + * perform subroutine call to value on top of stack + */ +void callstk(void) { + gen_immediate (); + output_string ("#.+5"); + newline (); + gen_swap_stack (); + output_line ("jp (hl)"); + stkp = stkp + INTSIZE; +} + +/** + * jump to specified internal label number + * @param label the label + */ +void gen_jump(int label) +{ + output_with_tab ("jp "); + 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 ("ld a,h"); + output_line ("or l"); + if (ft) + output_with_tab ("jp nz,"); + else + output_with_tab ("jp z,"); + 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 < 7) { + if (k & 1) { + output_line ("inc sp"); + k--; + } + while (k) { + output_line ("pop bc"); + k = k - INTSIZE; + } + return (newstkp); + } + } else { + if (k > -7) { + if (k & 1) { + output_line ("dec sp"); + k++; + } + while (k) { + output_line ("pop bc"); + k = k + INTSIZE; + } + return (newstkp); + } + } + gen_swap (); + gen_immediate (); + output_number (k); + newline (); + output_line ("dec sp"); + output_line ("ld sp, hl"); + gen_swap (); + return (newstkp); +} + +/** + * multiply the primary register by INTSIZE + */ +void gen_multiply_by_two(void) { + output_line ("add hl,hl"); +} + +/** + * divide the primary register by INTSIZE, never used + */ +void gen_divide_by_two(void) { + gen_push(HL_REG); /* push primary in prep for gasr */ + gen_immediate (); + output_number (1); + newline (); + gen_arithm_shift_right (); /* divide by two */ +} + +/** + * Case jump instruction + */ +void gen_jump_case(void) { + output_with_tab ("jp cccase"); + 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_pop (); + if (dbltest (lval2, lval)) { + gen_swap (); + gen_multiply_by_two(); + gen_swap (); + } + output_line ("add hl,de"); +} + +/** + * subtract the primary register from the secondary + */ +void gen_sub(void) { + gen_pop (); + gen_call ("ccsub"); +} + +/** + * multiply the primary and secondary registers (result in primary) + */ +void gen_mult(void) { + gen_pop(); + gen_call ("ccmul"); +} + +/** + * divide the secondary register by the primary + * (quotient in primary, remainder in secondary) + */ +void gen_div(void) { + gen_pop(); + gen_call ("ccdiv"); +} + +/** + * unsigned divide the secondary register by the primary + * (quotient in primary, remainder in secondary) + */ +void gen_udiv(void) { + gen_pop(); + gen_call ("ccudiv"); +} + +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) + */ +void gen_mod(void) { + gen_div (); + gen_swap (); +} + +/** + * compute the remainder (mod) of the secondary register + * divided by the primary register + * (remainder in primary, quotient in secondary) + */ +void gen_umod(void) { + gen_udiv (); + gen_swap (); +} + +/** + * inclusive 'or' the primary and secondary registers + */ +void gen_or(void) { + gen_pop(); + gen_call ("ccor"); +} + +/** + * exclusive 'or' the primary and secondary registers + */ +void gen_xor(void) { + gen_pop(); + gen_call ("ccxor"); +} + +/** + * 'and' the primary and secondary registers + */ +void gen_and(void) { + gen_pop(); + gen_call ("ccand"); +} + +/** + * 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 ("ccasr"); +} + +/** + * 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 ("cclsr"); +} + +/** + * 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 ("ccasl"); +} + +/** + * two's complement of primary register + */ +void gen_twos_complement(void) { + gen_call ("ccneg"); +} + +/** + * logical complement of primary register + */ +void gen_logical_negation(void) { + gen_call ("cclneg"); +} + +/** + * one's complement of primary register + */ +void gen_complement(void) { + gen_call ("cccom"); +} + +/** + * Convert primary value into logical value (0 if 0, 1 otherwise) + */ +void gen_convert_primary_reg_value_to_bool(void) { + gen_call ("ccbool"); +} + +/** + * increment the primary register by 1 if char, INTSIZE if int + */ +void gen_increment_primary_reg(LVALUE *lval) { + switch (lval->ptr_type) { + case STRUCT: + gen_immediate2(); + output_number(lval->tagsym->size); + newline(); + output_line("add hl,de"); + break ; + case CINT: + case UINT: + output_line("inc hl"); + default: + output_line("inc hl"); + break; + } +} + +/** + * decrement the primary register by one if char, INTSIZE if int + */ +void gen_decrement_primary_reg(LVALUE *lval) { + output_line("dec hl"); + switch (lval->ptr_type) { + case CINT: + case UINT: + output_line("dec hl"); + break; + case STRUCT: + gen_immediate2(); + output_number(lval->tagsym->size - 1); + newline(); + // two's complement + output_line("ld a,d"); + output_line("cpl"); + output_line("ld d,a"); + output_line("ld a,e"); + output_line("cpl"); + output_line("ld e,a"); + output_line("inc de"); + // substract + output_line("add hl,de"); + break ; + default: + 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 ("cceq"); +} + +/** + * not equal + */ +void gen_not_equal(void) { + gen_pop(); + gen_call ("ccne"); +} + +/** + * less than (signed) + */ +void gen_less_than(void) { + gen_pop(); + gen_call ("cclt"); +} + +/** + * less than or equal (signed) + */ +void gen_less_or_equal(void) { + gen_pop(); + gen_call ("ccle"); +} + +/** + * greater than (signed) + */ +void gen_greater_than(void) { + gen_pop(); + gen_call ("ccgt"); +} + +/** + * greater than or equal (signed) + */ +void gen_greater_or_equal(void) { + gen_pop(); + gen_call ("ccge"); +} + +/** + * less than (unsigned) + */ +void gen_unsigned_less_than(void) { + gen_pop(); + gen_call ("ccult"); +} + +/** + * less than or equal (unsigned) + */ +void gen_unsigned_less_or_equal(void) { + gen_pop(); + gen_call ("ccule"); +} + +/** + * greater than (unsigned) + */ +void gen_usigned_greater_than(void) { + gen_pop(); + gen_call ("ccugt"); +} + +/** + * greater than or equal (unsigned) + */ +void gen_unsigned_greater_or_equal(void) { + gen_pop(); + gen_call ("ccuge"); +} + +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 ("ld a,"); + output_number(d); + newline (); +} + +/** + * print partial instruction to get an immediate value into + * the secondary register + */ +void gen_immediate2(void) { + output_with_tab ("ld de,"); +} + +/** + * add offset to primary register + * @param val the value + */ +void add_offset(int val) { + gen_immediate2(); + output_number(val); + newline(); + output_line ("add hl,de"); +} + +/** + * 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(); + break; + case STRUCT: + gen_immediate2(); + output_number(size); + newline(); + gen_call("ccmul"); + break ; + default: + break; + } +} diff --git a/Applications/SmallC/defs.h b/Applications/SmallC/defs.h index c6fbc22e..bef33a98 100644 --- a/Applications/SmallC/defs.h +++ b/Applications/SmallC/defs.h @@ -2,10 +2,8 @@ * File defs.h: 2.1 (83/03/21,02:07:20) */ -// Intel 8080 architecture defs -#if defined(M6809) || defined(M8080) +// Intel 8080 / Z80 architecture defs #define INTSIZE 2 -#endif // miscellaneous #define FOREVER for(;;) diff --git a/Applications/SmallC/lib/Makefile b/Applications/SmallC/lib/Makefile new file mode 100644 index 00000000..37c767ac --- /dev/null +++ b/Applications/SmallC/lib/Makefile @@ -0,0 +1,34 @@ +.SUFFIXES: .o .obj .c .asm + +.c.o: + ../src/sccvax $*.c + as -o $*.o $*.s + rm $*.s +ASSEMS =\ + abs.asm atoi.asm binary.asm\ + charclass.asm fgets.asm fputs.asm\ + getchar.asm gets.asm index.asm\ + itoa.asm printn.asm putchar.asm\ + puts.asm reverse.asm shell.asm\ + strcat.asm strcmp.asm strcpy.asm\ + strlen.asm rand.asm \ + strncat.asm strncmp.asm strncpy.asm + +OBJ =\ + abs.o atoi.o binary.o\ + charclass.o fgets.o fputs.o\ + getchar.o gets.o index.o\ + itoa.o printn.o putchar.o\ + puts.o reverse.o shell.o\ + strcat.o strcmp.o strcpy.o\ + strlen.o rand.o \ + strncat.o strncmp.o strncpy.o +.c.asm: + ../src/scc8080 $*.c + mv $*.s $*.asm + +all: $(ASSEMS) + +vaxlibc.a: $(OBJ) + ar ur vaxlibc.a $(OBJ) + ranlib vaxlibc.a diff --git a/Applications/SmallC/lib/lorder8080 b/Applications/SmallC/lib/lorder8080 new file mode 100644 index 00000000..e36c5853 --- /dev/null +++ b/Applications/SmallC/lib/lorder8080 @@ -0,0 +1,12 @@ +grep public $* | sed 's/: public// +/?/d +s?\([^ ]*\)[ ]*\(.*\)?\2 \1? +s/\.asm//'> /tmp/symdef$$ +grep extrn $* | sed 's/: extrn// +s/\.asm// +s?\([^ ]*\)[ ]*\(.*\)?\2 \1? +/?/d' > /tmp/symref$$ +sort /tmp/symdef$$ -o /tmp/symdef$$ +sort /tmp/symref$$ -o /tmp/symref$$ +join /tmp/symref$$ /tmp/symdef$$ | sed 's/[^ ]* *//' +rm /tmp/symdef$$ /tmp/symref$$ diff --git a/Applications/SmallC/preproc.c b/Applications/SmallC/preproc.c index a00ec388..a18875d6 100644 --- a/Applications/SmallC/preproc.c +++ b/Applications/SmallC/preproc.c @@ -34,8 +34,12 @@ int fix_include_name (void) { *(--ibp) = 0; fp = -1; if (c1 == '<' || ((fp = open(buf, O_RDONLY)) != -1)) { +#ifndef __linux__ strcpy(buf2, DEFLIB); strlcat(buf2, buf, sizeof(buf2)); +#else + snprintf(buf2, sizeof(buf2), "%s%s", DEFLIB, buf); +#endif fp = open(buf2, O_RDONLY); } return (fp); -- 2.34.1