asz80: write symbols out
authorAlan Cox <alan@linux.intel.com>
Fri, 27 Oct 2017 21:50:14 +0000 (22:50 +0100)
committerAlan Cox <alan@linux.intel.com>
Fri, 27 Oct 2017 21:50:14 +0000 (22:50 +0100)
Also fix the .export handling and some oddments related to it.

We now should be writing out correct relocations and symbol tables. The one
thing we have yet to do is to properly number the external symbols so that
we can output them in that order and tie it nicely to the relocations so that
ld doesn't have to work overtime.

Applications/MWC/cmd/asz80/as.h
Applications/MWC/cmd/asz80/as0.c
Applications/MWC/cmd/asz80/as1.c
Applications/MWC/cmd/asz80/as2.c
Applications/MWC/cmd/asz80/as3.c
Applications/MWC/cmd/asz80/as4.c

index bfd9d0e..a025eb5 100644 (file)
@@ -139,6 +139,8 @@ typedef     struct  ADDR    {
        int     a_type;                 /* Type */
        VALUE   a_value;                /* Index offset, etc */
        int     a_segment;              /* Segment relative to */
+       struct SYM *a_sym;              /* Symbol tied to this address */
+                                       /* NULL indicates simple own segment */
 }      ADDR;
 
 /*
@@ -150,6 +152,7 @@ typedef     struct  SYM     {
        int     s_type;                 /* Type */
        VALUE   s_value;                /* Value */
        int     s_segment;              /* Segment this symbol is relative to */
+       uint16_t s_number;              /* Symbol number 1..n */
 }      SYM;
 
 /*
@@ -175,6 +178,7 @@ extern      int     lflag;
 extern jmp_buf env;
 extern VALUE   dot[NSEGMENT];
 extern  int    segment;
+extern int     debug_write;
 
 extern void asmline(void);
 extern void asmld(void);
index 59d1aa0..355350c 100644 (file)
@@ -24,6 +24,7 @@ SYM   *uhash[NHASH];
 int    pass;
 int    line;
 jmp_buf        env;
+int    debug_write = 1 ;
 
 
 /*
@@ -90,7 +91,7 @@ int main(int argc, char *argv[])
                fprintf(stderr, "%s: cannot open\n", ifn);
                exit(BAD);
        }
-       mkname(fn, ifn, "hex");
+       mkname(fn, ifn, "o");
        if ((ofp=fopen(fn, "w")) == NULL) {
                fprintf(stderr, "%s: cannot create\n", fn);
                exit(BAD);
index 360732f..a9f54d2 100644 (file)
@@ -98,10 +98,12 @@ loop:
                if ((sp->s_type&TMMODE) != TNEW
                &&  (sp->s_type&TMASG) == 0)
                        err('m');
-               sp->s_type &= ~TMMODE;
+               sp->s_type &= ~(TMMODE|TPUBLIC);
                sp->s_type |= TUSER|TMASG;
                sp->s_value = a1.a_value;
                sp->s_segment = a1.a_segment;
+               /* FIXME: review .equ to an external symbol/offset and
+                  what should happen */
                laddr = a1.a_value;
                lmode = ALIST;
                goto loop;
@@ -125,7 +127,7 @@ loop:
 
        case TEXPORT:
                getid(id, getnb());
-               sp = lookup(id, phash, 1);
+               sp = lookup(id, uhash, 1);
                sp->s_type |= TPUBLIC;
                break;
                /* .code etc */
index 67f4aef..c3607e8 100644 (file)
@@ -137,6 +137,7 @@ SYM *lookup(char *id, SYM *htable[], int cf)
 {
        SYM *sp;
        int hash;
+       static int symnext;
 
        hash = symhash(id);
        sp  = htable[hash];
@@ -155,6 +156,7 @@ SYM *lookup(char *id, SYM *htable[], int cf)
                sp->s_type = TNEW;
                sp->s_value = 0;
                sp->s_segment = UNKNOWN;
+               sp->s_number = ++symnext;
                symcopy(sp->s_id, id);
        }
        return (sp);
index 7e8f9cb..e572bab 100644 (file)
@@ -81,14 +81,20 @@ static void chksegment(ADDR *left, ADDR *right, int op)
           absolute either way around produces a segment offset */
        if ((left->a_segment == ABSOLUTE || right->a_segment == ABSOLUTE) &&
                op == '+') {
+               if (left->a_sym)
+                       right->a_sym = left->a_sym;
+               else if (right->a_sym)
+                       left->a_sym = right->a_sym;
                left->a_segment += right->a_segment;
                return;
        }
        /* Subtraction within segment produces an absolute */
        if (left->a_segment == right->a_segment && op == '-') {
                left->a_segment = ABSOLUTE;
+               left->a_sym = NULL;
                return;
        }
+       left->a_sym = NULL;
        aerr();
 }
 
@@ -209,8 +215,14 @@ void expr2(ADDR *ap)
                        ap->a_value = 0;
                        return;
                }
-               if (mode == TNEW)
+               /* An external symbol has to be tracked and output in
+                  the relocations. Any known internal symbol is just
+                  encoded as a relocation relative to a segment */
+               if (mode == TNEW) {
                        uerr(id);
+                       ap->a_sym = sp;
+               } else
+                       ap->a_sym = NULL;
                ap->a_type  = TUSER;
                ap->a_value = sp->s_value;
                ap->a_segment = sp->s_segment;
index ec09198..0144429 100644 (file)
@@ -73,10 +73,17 @@ void outraw(ADDR *a)
 {
        if (a->a_segment != ABSOLUTE) {
                /* FIXME@ handle symbols */
-               if (segment == BSS && a->a_value)
+               if (segment == BSS)
                        err('b');
-               outbyte(REL_ESC);
-               outbyte((2 << 4) | REL_SIMPLE | a->a_segment);
+               if (a->a_sym == NULL) {
+                       outbyte(REL_ESC);
+                       outbyte((1 << 4) | REL_SIMPLE | a->a_segment);
+               } else {
+                       outbyte(REL_ESC);
+                       outbyte((1 << 4 ) | REL_SYMBOL);
+                       outbyte(a->a_sym->s_number & 0xFF);
+                       outbyte(a->a_sym->s_number >> 8);
+               }
        }
        outaw(a->a_value);
 }
@@ -105,14 +112,66 @@ void outab(uint8_t b)
 void outrab(ADDR *a)
 {
        /* FIXME: handle symbols */
-       if (segment == BSS && a->a_value) {
-               err('b');
-               outbyte(REL_ESC);
-               outbyte((2 << 4) | REL_SIMPLE | a->a_segment);
+       if (a->a_segment != ABSOLUTE) {
+               if (segment == BSS)
+                       err('b');
+               if (a->a_sym == NULL) {
+                       outbyte(REL_ESC);
+                       outbyte((0 << 4) | REL_SIMPLE | a->a_segment);
+               } else {
+                       outbyte(REL_ESC);
+                       outbyte((0 << 4 ) | REL_SYMBOL);
+                       outbyte(a->a_sym->s_number & 0xFF);
+                       outbyte(a->a_sym->s_number >> 8);
+               }
        }
        outab(a->a_value);
 }
 
+static void putsymbol(SYM *s, FILE *ofp)
+{
+       int i;
+       uint8_t flag = 0;
+       printf("Putsymbol %s\n", s->s_id);
+       if (s->s_type == TNEW)
+               flag |= S_UNKNOWN;
+       else {
+               if (s->s_type & TPUBLIC)
+                       flag |= S_PUBLIC;
+               flag |= s->s_segment;
+       }
+       putc(flag, ofp);
+       putc(s->s_number, ofp);
+       putc(s->s_number >> 8, ofp);
+       for (i = 0; i < 16; i++) {
+               putc(s->s_id[i], ofp);
+               if (!s->s_id[i])
+                       break;
+       }
+       if (!(flag & S_UNKNOWN)) {
+               putc(s->s_value, ofp);
+               putc(s->s_value >> 8, ofp);
+       }
+}
+
+static void writesymbols(SYM *hash[], FILE *ofp, int flag)
+{
+       int i;
+       fseek(ofp, obh.o_symbase, SEEK_SET);
+       for (i = 0; i < NHASH; i++) {
+               SYM *s;
+               for (s = hash[i]; s != NULL; s = s->s_fp) {
+                       int t = s->s_type & TMMODE;
+                       int n;
+                       if (t != TUSER && t != TNEW)
+                               continue;
+                       n =  (t == TNEW) || (t == TUSER && (s->s_type & TPUBLIC));
+                       if (n == flag)
+                               putsymbol(s, ofp);
+               }
+       }
+}
+
 /*
  * Put out the end of file
  * hex item at the very end of
@@ -120,6 +179,13 @@ void outrab(ADDR *a)
  */
 void outeof(void)
 {
+       writesymbols(phash, ofp, 1);
+       writesymbols(uhash, ofp, 1);
+       if (debug_write) {
+               obh.o_dbgbase = ftell(ofp);
+               writesymbols(phash, ofp, 0);
+               writesymbols(uhash, ofp, 0);
+       }
        rewind(ofp);
        obh.o_magic = MAGIC_OBJ;
        fwrite(&obh, sizeof(obh), 1, ofp);