commit 632f9fc0faf20a4dc65a6b4ad63ee8f1b88d6e2a
parent 9eee73f411f146d97b6d4657427ada231939bf81
Author: Devine Lu Linvega <aliceffekt@gmail.com>
Date: Wed, 27 Mar 2024 16:36:28 -0700
(uxnasm) Asbtracted ref resolve
Diffstat:
M | src/uxnasm.c | | | 108 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
1 file changed, 53 insertions(+), 55 deletions(-)
diff --git a/src/uxnasm.c b/src/uxnasm.c
@@ -18,7 +18,7 @@ typedef signed char Sint8;
typedef unsigned short Uint16;
typedef struct {
- char *name, *content;
+ char *name, rune, *content;
Uint16 addr, refs;
} Item;
@@ -226,7 +226,7 @@ makepad(char *w)
}
static int
-addref(char *label, Uint16 addr)
+addref(char *label, char rune, Uint16 addr)
{
Item *r;
if(refs_len >= 0x1000)
@@ -235,12 +235,11 @@ addref(char *label, Uint16 addr)
if(label[0] == '{') {
lambda_stack[lambda_ptr++] = lambda_len;
r->name = push(makelambda(lambda_len++), 0);
- } else if(label[1] == '&')
- r->name = makesublabel(label + 2);
- else if(label[0] == '/')
+ } else if(label[0] == '&' || label[0] == '/') {
r->name = makesublabel(label + 1);
- else
+ } else
r->name = push(label, 0);
+ r->rune = rune;
r->addr = addr;
return 1;
}
@@ -308,15 +307,15 @@ parse(char *w, FILE *f, Context *ctx)
case '&': return !makelabel(w, 0, ctx) ? error_asm("Invalid sublabel") : 1;
case '}': return !makelabel(makelambda(lambda_stack[--lambda_ptr]), 0, ctx) ? error_asm("Invalid label") : 1;
case '#': return !sihx(w + 1) || !writehex(w, ctx) ? error_asm("Invalid hexadecimal") : 1;
- case '_': return addref(w, ptr) && writebyte(0xff, ctx);
- case ',': return addref(w, ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
- case '-': return addref(w, ptr) && writebyte(0xff, ctx);
- case '.': return addref(w, ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
+ case '_': return addref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
+ case ',': return addref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
+ case '-': return addref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
+ case '.': return addref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
case ':': fprintf(stderr, "Deprecated rune %s, use =%s\n", w, w + 1); /* fall-through */
- case '=': return addref(w, ptr) && writeshort(0xffff);
- case ';': return addref(w, ptr + 1) && writebyte(findopcode("LIT2"), ctx) && writeshort(0xffff);
- case '?': return addref(w, ptr + 1) && writebyte(0x20, ctx) && writeshort(0xffff);
- case '!': return addref(w, ptr + 1) && writebyte(0x40, ctx) && writeshort(0xffff);
+ case '=': return addref(w + 1, w[0], ptr) && writeshort(0xffff);
+ case ';': return addref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT2"), ctx) && writeshort(0xffff);
+ case '?': return addref(w + 1, w[0], ptr + 1) && writebyte(0x20, ctx) && writeshort(0xffff);
+ case '!': return addref(w + 1, w[0], ptr + 1) && writebyte(0x40, ctx) && writeshort(0xffff);
case '"': return !writestring(w + 1, ctx) ? error_asm("Invalid string") : 1;
case '$':
case '|': return !makepad(w) ? error_asm("Invalid padding") : 1;
@@ -329,54 +328,52 @@ parse(char *w, FILE *f, Context *ctx)
return writebyte(findopcode(w), ctx);
else if((m = findmacro(w)))
return walkmacro(m, ctx);
- return addref(w, ptr + 1) && writebyte(0x60, ctx) && writeshort(0xffff);
+ return addref(w, ' ', ptr + 1) && writebyte(0x60, ctx) && writeshort(0xffff);
+}
+
+static int
+resolveref(Item *r)
+{
+ Uint16 a;
+ Uint8 *rom = data + r->addr;
+ Item *l = findlabel(r->name);
+ if(!l) return 0;
+ switch(r->rune) {
+ case '_':
+ case ',':
+ *rom = (Sint8)(l->addr - r->addr - 2);
+ if((Sint8)data[r->addr] != (l->addr - r->addr - 2))
+ return error_top("Relative reference is too far", r->name);
+ l->refs++;
+ break;
+ case '-':
+ case '.':
+ *rom = l->addr;
+ l->refs++;
+ break;
+ case ':':
+ case '=':
+ case ';':
+ *rom++ = l->addr >> 8, *rom = l->addr;
+ l->refs++;
+ break;
+ case '?':
+ case '!':
+ default:
+ a = l->addr - r->addr - 2;
+ *rom++ = a >> 8, *rom = a;
+ l->refs++;
+ break;
+ }
}
static int
resolve(void)
{
int i;
- Uint16 a;
for(i = 0; i < refs_len; i++) {
Item *r = &refs[i];
- Uint8 *rom = data + r->addr;
- Item *l;
- switch(r->name[0]) {
- case '_':
- case ',':
- if(!(l = findlabel(r->name + 1))) return error_top("Unknown relative reference", r->name);
- *rom = (Sint8)(l->addr - r->addr - 2);
- if((Sint8)data[r->addr] != (l->addr - r->addr - 2))
- return error_top("Relative reference is too far", r->name);
- l->refs++;
- break;
- case '-':
- case '.':
- if(!(l = findlabel(r->name + 1))) return error_top("Unknown zero-page reference", r->name);
- *rom = l->addr;
- l->refs++;
- break;
- case ':':
- case '=':
- case ';':
- if(!(l = findlabel(r->name + 1))) return error_top("Unknown absolute reference", r->name);
- *rom++ = l->addr >> 8, *rom = l->addr;
- l->refs++;
- break;
- case '?':
- case '!':
- if(!(l = findlabel(r->name + 1))) return error_top("Unknown immediate reference", r->name);
- a = l->addr - r->addr - 2;
- *rom++ = a >> 8, *rom = a;
- l->refs++;
- break;
- default:
- if(!(l = findlabel(r->name))) return error_top("Unknown subroutine reference", r->name);
- a = l->addr - r->addr - 2;
- *rom++ = a >> 8, *rom = a;
- l->refs++;
- break;
- }
+ if(!resolveref(r)) return error_top("Unknown reference", r->name);
}
return 1;
}
@@ -432,4 +429,4 @@ main(int argc, char *argv[])
fwrite(data + PAGE, length - PAGE, 1, dst);
writesym(argv[2]);
return 0;
-}
+}
+\ No newline at end of file