From bc35c4460c5fce3fd9a457f651bca6c1b5e287fd Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 31 Oct 2017 21:40:35 +0000 Subject: [PATCH] as: Fix more bugs, add < and > for lo/hi relocations Still plenty of bugs I am sure. --- Applications/MWC/cmd/asz80/as.h | 9 ++-- Applications/MWC/cmd/asz80/as1-nova.c | 4 ++ Applications/MWC/cmd/asz80/as1.c | 10 ++++- Applications/MWC/cmd/asz80/as3.c | 6 ++- Applications/MWC/cmd/asz80/as4.c | 61 +++++++++++++++++++++------ Applications/MWC/cmd/asz80/obj.h | 2 +- 6 files changed, 71 insertions(+), 21 deletions(-) diff --git a/Applications/MWC/cmd/asz80/as.h b/Applications/MWC/cmd/asz80/as.h index cb8c766f..e562ed83 100644 --- a/Applications/MWC/cmd/asz80/as.h +++ b/Applications/MWC/cmd/asz80/as.h @@ -352,7 +352,7 @@ typedef uint32_t VALUE; /* For symbol values */ /* * Segments */ -#define UNKNOWN -1 +#define UNKNOWN 15 #define ABSOLUTE 0 #define CODE 1 #define DATA 2 @@ -375,9 +375,12 @@ typedef uint32_t VALUE; /* For symbol values */ * Address description. */ typedef struct ADDR { - int a_type; /* Type */ + uint16_t a_type; /* Type */ VALUE a_value; /* Index offset, etc */ - int a_segment; /* Segment relative to */ + uint8_t a_segment; /* Segment relative to */ + uint8_t a_flags; /* To track high */ +#define A_HIGH 1 +#define A_LOW 2 struct SYM *a_sym; /* Symbol tied to this address */ /* NULL indicates simple own segment */ } ADDR; diff --git a/Applications/MWC/cmd/asz80/as1-nova.c b/Applications/MWC/cmd/asz80/as1-nova.c index 8db69097..8ca254ea 100644 --- a/Applications/MWC/cmd/asz80/as1-nova.c +++ b/Applications/MWC/cmd/asz80/as1-nova.c @@ -19,6 +19,10 @@ void getaddr(ADDR *ap) int reg; int c; + ap->a_sym = NULL; + ap->a_flags = 0; + ap->a_type = 0; + /* We only have one addressing format we ever use.. an address. Quite how we encode it is another saga because our memory ops use register relative or pc relative */ diff --git a/Applications/MWC/cmd/asz80/as1.c b/Applications/MWC/cmd/asz80/as1.c index b2592bb4..de5b16ea 100644 --- a/Applications/MWC/cmd/asz80/as1.c +++ b/Applications/MWC/cmd/asz80/as1.c @@ -55,8 +55,16 @@ void getaddr(ADDR *ap) int reg; int c; + ap->a_flags = 0; + ap->a_sym = NULL; + if ((c=getnb()) != '(') { - unget(c); + if (c == '<') + ap->a_flags |= A_LOW; + else if (c == '>') + ap->a_flags |= A_HIGH; + else + unget(c); expr1(ap, LOPRI, 0); return; } diff --git a/Applications/MWC/cmd/asz80/as3.c b/Applications/MWC/cmd/asz80/as3.c index 25e7df06..f86da3c5 100644 --- a/Applications/MWC/cmd/asz80/as3.c +++ b/Applications/MWC/cmd/asz80/as3.c @@ -67,12 +67,12 @@ static void chksegment(ADDR *left, ADDR *right, int op) /* Subtraction within segment produces an absolute */ if (op == '-') { /* Unknown symbols may get segment forced as a result */ - if (left->a_segment == -1) { + if (left->a_segment == UNKNOWN) { left->a_segment = right->a_segment; if (left->a_sym) setsegment(left->a_sym, left->a_segment); } - if (right->a_segment == -1) { + if (right->a_segment == UNKNOWN) { right->a_segment = left->a_segment; if (right->a_sym) setsegment(right->a_sym, right->a_segment); @@ -204,6 +204,8 @@ void expr2(ADDR *ap) ap->a_value = 0; return; } + if (mode != TNEW && mode != TUSER) + qerr(SYNTAX_ERROR); /* 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 */ diff --git a/Applications/MWC/cmd/asz80/as4.c b/Applications/MWC/cmd/asz80/as4.c index a2164c74..27767104 100644 --- a/Applications/MWC/cmd/asz80/as4.c +++ b/Applications/MWC/cmd/asz80/as4.c @@ -82,6 +82,8 @@ void outaw(uint16_t w) static void check_store_allowed(uint8_t segment, uint16_t value) { + if (value == 0) + return; if (segment == BSS) err('b', DATA_IN_BSS); if (segment == ZP) @@ -91,22 +93,38 @@ static void check_store_allowed(uint8_t segment, uint16_t value) /* * Symbol numbers and relocatios are always written little endian * for simplicity. + * + * A_LOW and A_HIGH indicate 8bit partial relocations. We handle these + * internally. */ void outraw(ADDR *a) { + int s = 1 << 4; if (a->a_segment != ABSOLUTE) { - check_store_allowed(segment, a->a_value); + outbyte(REL_ESC); + check_store_allowed(segment, 1); + /* low bits of 16 bit is an 8bit relocation with + overflow suppressed */ + if (a->a_flags & A_LOW) { + outbyte(REL_OVERFLOW); + s = 0 << 4; + } + if (a->a_flags & A_HIGH) + outbyte(REL_HIGH); if (a->a_sym == NULL) { - outbyte(REL_ESC); - outbyte((1 << 4) | REL_SIMPLE | a->a_segment); + /* low bits of 16 bit is an 8bit relocation with + overflow suppressed */ + outbyte(s | REL_SIMPLE | a->a_segment); } else { - outbyte(REL_ESC); - outbyte((1 << 4 ) | REL_SYMBOL); + outbyte(s | REL_SYMBOL); outbyte(a->a_sym->s_number & 0xFF); outbyte(a->a_sym->s_number >> 8); } } - outaw(a->a_value); + if (a->a_flags & A_LOW) + outab(a->a_value); + else + outaw(a->a_value); } /* @@ -140,7 +158,7 @@ void outabchk(uint16_t b) void outrabrel(ADDR *a) { if (a->a_segment != ABSOLUTE) { - check_store_allowed(segment, a->a_value); + check_store_allowed(segment, 1); if (a->a_sym) { outbyte(REL_ESC); outbyte((0 << 4 ) | REL_PCREL); @@ -157,21 +175,36 @@ void outrabrel(ADDR *a) outab(a->a_value); } +/* + * We should probably fold outraw and outrab as they are not very + * different except in the default value of s. + */ void outrab(ADDR *a) { + int s = 0; if (a->a_segment != ABSOLUTE) { - check_store_allowed(segment, a->a_value); + check_store_allowed(segment, 1); + outbyte(REL_ESC); + if (a->a_flags & A_LOW) { + outbyte(REL_OVERFLOW); + a->a_value &= 0xFF; + } + if (a->a_flags & A_HIGH) { + outbyte(REL_HIGH); + s = 1 << 4; + } if (a->a_sym == NULL) { - outbyte(REL_ESC); - outbyte((0 << 4) | REL_SIMPLE | a->a_segment); + outbyte(s | REL_SIMPLE | a->a_segment); } else { - outbyte(REL_ESC); - outbyte((0 << 4 ) | REL_SYMBOL); + outbyte(s | REL_SYMBOL); outbyte(a->a_sym->s_number & 0xFF); outbyte(a->a_sym->s_number >> 8); } } - outabchk(a->a_value); + if (s) + outaw(a->a_value); + else + outabchk(a->a_value); } static void putsymbol(SYM *s, FILE *ofp) @@ -184,7 +217,7 @@ static void putsymbol(SYM *s, FILE *ofp) if (s->s_type & TPUBLIC) flag |= S_PUBLIC; } - /* 0 absolute, 1-n segments, -1 don't care */ + /* 0 absolute, 1-n segments, 15 don't care */ flag |= (s->s_segment & S_SEGMENT); putc(flag, ofp); fwrite(s->s_id, 16, 1, ofp); diff --git a/Applications/MWC/cmd/asz80/obj.h b/Applications/MWC/cmd/asz80/obj.h index 855b6637..32b59a56 100644 --- a/Applications/MWC/cmd/asz80/obj.h +++ b/Applications/MWC/cmd/asz80/obj.h @@ -85,7 +85,7 @@ struct objhdr /* * Segments */ -#define UNKNOWN -1 +#define UNKNOWN 15 #define ABSOLUTE 0 /* Constant, not relocated */ #define CODE 1 /* Relocated versus code */ #define DATA 2 /* Relocated versus data */ -- 2.34.1