From d92257ddede531b46d5dacc9ec1ab0790cfa5e4b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 27 Oct 2017 22:50:14 +0100 Subject: [PATCH] asz80: write symbols out 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 | 4 ++ Applications/MWC/cmd/asz80/as0.c | 3 +- Applications/MWC/cmd/asz80/as1.c | 6 ++- Applications/MWC/cmd/asz80/as2.c | 2 + Applications/MWC/cmd/asz80/as3.c | 14 +++++- Applications/MWC/cmd/asz80/as4.c | 80 +++++++++++++++++++++++++++++--- 6 files changed, 98 insertions(+), 11 deletions(-) diff --git a/Applications/MWC/cmd/asz80/as.h b/Applications/MWC/cmd/asz80/as.h index bfd9d0e5..a025eb5d 100644 --- a/Applications/MWC/cmd/asz80/as.h +++ b/Applications/MWC/cmd/asz80/as.h @@ -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); diff --git a/Applications/MWC/cmd/asz80/as0.c b/Applications/MWC/cmd/asz80/as0.c index 59d1aa02..355350cc 100644 --- a/Applications/MWC/cmd/asz80/as0.c +++ b/Applications/MWC/cmd/asz80/as0.c @@ -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); diff --git a/Applications/MWC/cmd/asz80/as1.c b/Applications/MWC/cmd/asz80/as1.c index 360732f9..a9f54d23 100644 --- a/Applications/MWC/cmd/asz80/as1.c +++ b/Applications/MWC/cmd/asz80/as1.c @@ -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 */ diff --git a/Applications/MWC/cmd/asz80/as2.c b/Applications/MWC/cmd/asz80/as2.c index 67f4aef2..c3607e81 100644 --- a/Applications/MWC/cmd/asz80/as2.c +++ b/Applications/MWC/cmd/asz80/as2.c @@ -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); diff --git a/Applications/MWC/cmd/asz80/as3.c b/Applications/MWC/cmd/asz80/as3.c index 7e8f9cbf..e572bab4 100644 --- a/Applications/MWC/cmd/asz80/as3.c +++ b/Applications/MWC/cmd/asz80/as3.c @@ -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; diff --git a/Applications/MWC/cmd/asz80/as4.c b/Applications/MWC/cmd/asz80/as4.c index ec091988..0144429d 100644 --- a/Applications/MWC/cmd/asz80/as4.c +++ b/Applications/MWC/cmd/asz80/as4.c @@ -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); -- 2.34.1