scc: add draft 6809 and 6801 code gen, fix a bug in the Z80 case
authorAlan Cox <alan@linux.intel.com>
Thu, 23 Jun 2016 16:47:45 +0000 (17:47 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 23 Jun 2016 16:47:45 +0000 (17:47 +0100)
Applications/SmallC/Makefile
Applications/SmallC/code6801.c [new file with mode: 0644]
Applications/SmallC/code6809.c
Applications/SmallC/codez80.c
Applications/SmallC/foo.c [deleted file]

index 0151e7c..d15bf11 100644 (file)
@@ -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 (file)
index 0000000..1374bbb
--- /dev/null
@@ -0,0 +1,770 @@
+#include <stdio.h>
+#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;
+    }
+}
index a9c1730..98f5c45 100644 (file)
@@ -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 <stdio.h>
 #include "defs.h"
 #include "data.h"
  *      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;
+    }
 }
index 0eb216d..68a83b7 100644 (file)
@@ -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 (file)
index 6f189da..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-poop()
-