| ... | ... |
@@ -14,6 +14,7 @@ WITH REGARD TO THIS SOFTWARE. |
| 14 | 14 |
#define TRIM 0x0100 |
| 15 | 15 |
#define LENGTH 0x10000 |
| 16 | 16 |
|
| 17 |
+#define REFERENCES 2048 |
|
| 17 | 18 |
#define LABELS 512 |
| 18 | 19 |
#define MACROS 256 |
| 19 | 20 |
|
| ... | ... |
@@ -31,15 +32,21 @@ typedef struct {
|
| 31 | 32 |
Uint16 addr, refs; |
| 32 | 33 |
} Label; |
| 33 | 34 |
|
| 35 |
+typedef struct {
|
|
| 36 |
+ char name[64], rune; |
|
| 37 |
+ Uint16 addr; |
|
| 38 |
+} Reference; |
|
| 39 |
+ |
|
| 34 | 40 |
typedef struct {
|
| 35 | 41 |
Uint8 data[LENGTH]; |
| 36 |
- Uint16 ptr, length, llen, mlen; |
|
| 42 |
+ Uint16 ptr, length, llen, mlen, rlen; |
|
| 37 | 43 |
Label labels[LABELS]; |
| 38 | 44 |
Macro macros[MACROS]; |
| 45 |
+ Reference refs[REFERENCES]; |
|
| 46 |
+ char scope[64]; |
|
| 39 | 47 |
} Program; |
| 40 | 48 |
|
| 41 | 49 |
Program p; |
| 42 |
-static Uint16 addr = 0; |
|
| 43 | 50 |
|
| 44 | 51 |
/* clang-format off */ |
| 45 | 52 |
|
| ... | ... |
@@ -50,7 +57,6 @@ static char ops[][4] = {
|
| 50 | 57 |
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT" |
| 51 | 58 |
}; |
| 52 | 59 |
|
| 53 |
-static int cpos(char *s, char a){ int i = 0; char c; while((c = s[i++])) if(c == a) return i; return -1; }
|
|
| 54 | 60 |
static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */
|
| 55 | 61 |
static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */
|
| 56 | 62 |
static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */
|
| ... | ... |
@@ -58,11 +64,16 @@ static int slen(char *s) { int i = 0; while(s[i]) ++i; return i; } /* string l
|
| 58 | 64 |
static char *scpy(char *src, char *dst, int len) { int i = 0; while((dst[i] = src[i]) && i < len - 2) i++; dst[i + 1] = '\0'; return dst; } /* string copy */
|
| 59 | 65 |
static char *scat(char *dst, const char *src) { char *ptr = dst + slen(dst); while(*src) *ptr++ = *src++; *ptr = '\0'; return dst; } /* string cat */
|
| 60 | 66 |
|
| 61 |
-#pragma mark - Helpers |
|
| 62 |
- |
|
| 63 | 67 |
/* clang-format on */ |
| 64 | 68 |
|
| 65 |
-#pragma mark - I/O |
|
| 69 |
+static int tokenize(char *w, FILE *f); |
|
| 70 |
+ |
|
| 71 |
+static int |
|
| 72 |
+error(const char *name, const char *msg) |
|
| 73 |
+{
|
|
| 74 |
+ fprintf(stderr, "%s: %s\n", name, msg); |
|
| 75 |
+ return 0; |
|
| 76 |
+} |
|
| 66 | 77 |
|
| 67 | 78 |
static Macro * |
| 68 | 79 |
findmacro(char *name) |
| ... | ... |
@@ -109,45 +120,6 @@ findopcode(char *s) |
| 109 | 120 |
return 0; |
| 110 | 121 |
} |
| 111 | 122 |
|
| 112 |
-static void |
|
| 113 |
-pushbyte(Uint8 b, int lit) |
|
| 114 |
-{
|
|
| 115 |
- if(lit) pushbyte(findopcode("LIT"), 0);
|
|
| 116 |
- p.data[p.ptr++] = b; |
|
| 117 |
- p.length = p.ptr; |
|
| 118 |
-} |
|
| 119 |
- |
|
| 120 |
-static void |
|
| 121 |
-pushshort(Uint16 s, int lit) |
|
| 122 |
-{
|
|
| 123 |
- if(lit) pushbyte(findopcode("LIT2"), 0);
|
|
| 124 |
- pushbyte((s >> 8) & 0xff, 0); |
|
| 125 |
- pushbyte(s & 0xff, 0); |
|
| 126 |
-} |
|
| 127 |
- |
|
| 128 |
-static void |
|
| 129 |
-pushword(char *s) |
|
| 130 |
-{
|
|
| 131 |
- int i = 0; |
|
| 132 |
- char c; |
|
| 133 |
- while((c = s[i++])) pushbyte(c, 0); |
|
| 134 |
-} |
|
| 135 |
- |
|
| 136 |
-static char * |
|
| 137 |
-sublabel(char *src, char *scope, char *name) |
|
| 138 |
-{
|
|
| 139 |
- return scat(scat(scpy(scope, src, 64), "/"), name); |
|
| 140 |
-} |
|
| 141 |
- |
|
| 142 |
-#pragma mark - Parser |
|
| 143 |
- |
|
| 144 |
-static int |
|
| 145 |
-error(const char *name, const char *msg) |
|
| 146 |
-{
|
|
| 147 |
- fprintf(stderr, "%s: %s\n", name, msg); |
|
| 148 |
- return 0; |
|
| 149 |
-} |
|
| 150 |
- |
|
| 151 | 123 |
static int |
| 152 | 124 |
makemacro(char *name, FILE *f) |
| 153 | 125 |
{
|
| ... | ... |
@@ -186,216 +158,199 @@ makelabel(char *name) |
| 186 | 158 |
if(p.llen == LABELS) |
| 187 | 159 |
return error("Too many labels", name);
|
| 188 | 160 |
l = &p.labels[p.llen++]; |
| 189 |
- l->addr = addr; |
|
| 161 |
+ l->addr = p.ptr; |
|
| 190 | 162 |
l->refs = 0; |
| 191 | 163 |
scpy(name, l->name, 64); |
| 192 | 164 |
return 1; |
| 193 | 165 |
} |
| 194 | 166 |
|
| 195 | 167 |
static int |
| 196 |
-addref(Label *l, Uint8 rel) |
|
| 168 |
+doinclude(const char *filename) |
|
| 197 | 169 |
{
|
| 198 |
- if(rel) {
|
|
| 199 |
- int pos = cpos(l->name, '/'); |
|
| 200 |
- if(pos != -1) {
|
|
| 201 |
- char parent[64]; |
|
| 202 |
- Label *rl = findlabel(scpy(l->name, parent, pos)); |
|
| 203 |
- if(rl) |
|
| 204 |
- ++rl->refs; |
|
| 205 |
- } |
|
| 206 |
- } |
|
| 207 |
- return ++l->refs; |
|
| 170 |
+ FILE *f; |
|
| 171 |
+ char w[64]; |
|
| 172 |
+ if(!(f = fopen(filename, "r"))) |
|
| 173 |
+ return error("Include failed to open", filename);
|
|
| 174 |
+ while(fscanf(f, "%63s", w) == 1) |
|
| 175 |
+ if(!tokenize(w, f)) |
|
| 176 |
+ return error("Unknown token", w);
|
|
| 177 |
+ fclose(f); |
|
| 178 |
+ return 1; |
|
| 208 | 179 |
} |
| 209 | 180 |
|
| 210 |
-static int |
|
| 211 |
-skipblock(char *w, int *cap, char a, char b) |
|
| 181 |
+static void |
|
| 182 |
+writebyte(Uint8 b, int lit) |
|
| 212 | 183 |
{
|
| 213 |
- if(w[0] == b) {
|
|
| 214 |
- *cap = 0; |
|
| 215 |
- return 1; |
|
| 216 |
- } |
|
| 217 |
- if(w[0] == a) *cap = 1; |
|
| 218 |
- if(*cap) return 1; |
|
| 219 |
- return 0; |
|
| 184 |
+ if(lit) writebyte(findopcode("LIT"), 0);
|
|
| 185 |
+ p.data[p.ptr++] = b; |
|
| 186 |
+ p.length = p.ptr; |
|
| 220 | 187 |
} |
| 221 | 188 |
|
| 222 |
-static int |
|
| 223 |
-walktoken(char *w) |
|
| 189 |
+static void |
|
| 190 |
+writeshort(Uint16 s, int lit) |
|
| 224 | 191 |
{
|
| 225 |
- Macro *m; |
|
| 226 |
- if(findopcode(w) || scmp(w, "BRK", 4)) |
|
| 227 |
- return 1; |
|
| 228 |
- switch(w[0]) {
|
|
| 229 |
- case '[': return 0; |
|
| 230 |
- case ']': return 0; |
|
| 231 |
- case '\'': return 1; |
|
| 232 |
- case '.': return 2; /* zero-page: LIT addr-lb */ |
|
| 233 |
- case ',': return 2; /* relative: LIT addr-rel */ |
|
| 234 |
- case ':': return 2; /* absolute: addr-hb addr-lb */ |
|
| 235 |
- case ';': return 3; /* absolute: LIT addr-hb addr-lb */ |
|
| 236 |
- case '$': return shex(w + 1); |
|
| 237 |
- case '#': return slen(w + 1) == 4 ? 3 : 2; |
|
| 238 |
- case '"': return slen(w + 1); |
|
| 239 |
- } |
|
| 240 |
- if((m = findmacro(w))) {
|
|
| 241 |
- int i, res = 0; |
|
| 242 |
- for(i = 0; i < m->len; ++i) |
|
| 243 |
- res += walktoken(m->items[i]); |
|
| 244 |
- return res; |
|
| 245 |
- } |
|
| 246 |
- if(sihx(w) && slen(w) == 2) |
|
| 247 |
- return 1; |
|
| 248 |
- else if(sihx(w) && slen(w) == 4) |
|
| 249 |
- return 2; |
|
| 250 |
- return error("Invalid token", w);
|
|
| 192 |
+ if(lit) writebyte(findopcode("LIT2"), 0);
|
|
| 193 |
+ writebyte((s >> 8) & 0xff, 0); |
|
| 194 |
+ writebyte(s & 0xff, 0); |
|
| 251 | 195 |
} |
| 252 | 196 |
|
| 253 |
-static int |
|
| 254 |
-parsetoken(char *w) |
|
| 197 |
+static char * |
|
| 198 |
+sublabel(char *src, char *scope, char *name) |
|
| 255 | 199 |
{
|
| 256 |
- Label *l; |
|
| 257 |
- Macro *m; |
|
| 258 |
- if(w[0] == '.' && (l = findlabel(w + 1))) { /* zero-page */
|
|
| 259 |
- if(l->addr > 0xff) |
|
| 260 |
- return error("Address is not in zero page", w);
|
|
| 261 |
- pushbyte(l->addr, 1); |
|
| 262 |
- return addref(l, 1); |
|
| 263 |
- } else if(w[0] == ',' && (l = findlabel(w + 1))) { /* relative */
|
|
| 264 |
- int off = l->addr - p.ptr - 3; |
|
| 265 |
- if(off < -126 || off > 126) |
|
| 266 |
- return error("Address is too far", w);
|
|
| 267 |
- pushbyte((Sint8)off, 1); |
|
| 268 |
- return addref(l, 0); |
|
| 269 |
- } else if(w[0] == ':' && (l = findlabel(w + 1))) { /* raw */
|
|
| 270 |
- pushshort(l->addr, 0); |
|
| 271 |
- return addref(l, 1); |
|
| 272 |
- } else if(w[0] == ';' && (l = findlabel(w + 1))) { /* absolute */
|
|
| 273 |
- pushshort(l->addr, 1); |
|
| 274 |
- return addref(l, 1); |
|
| 275 |
- } else if(findopcode(w) || scmp(w, "BRK", 4)) { /* opcode */
|
|
| 276 |
- pushbyte(findopcode(w), 0); |
|
| 277 |
- return 1; |
|
| 278 |
- } else if(w[0] == '"') { /* string */
|
|
| 279 |
- pushword(w + 1); |
|
| 280 |
- return 1; |
|
| 281 |
- } else if(w[0] == '\'') { /* char */
|
|
| 282 |
- pushbyte((Uint8)w[1], 0); |
|
| 283 |
- return 1; |
|
| 284 |
- } else if(w[0] == '#') { /* immediate */
|
|
| 285 |
- if(sihx(w + 1) && slen(w + 1) == 2) |
|
| 286 |
- pushbyte(shex(w + 1), 1); |
|
| 287 |
- else if(sihx(w + 1) && slen(w + 1) == 4) |
|
| 288 |
- pushshort(shex(w + 1), 1); |
|
| 289 |
- else |
|
| 290 |
- return error("Invalid hexadecimal literal", w);
|
|
| 291 |
- return 1; |
|
| 292 |
- } else if(sihx(w)) { /* raw */
|
|
| 293 |
- if(slen(w) == 2) |
|
| 294 |
- pushbyte(shex(w), 0); |
|
| 295 |
- else if(slen(w) == 4) |
|
| 296 |
- pushshort(shex(w), 0); |
|
| 297 |
- else |
|
| 298 |
- return error("Invalid hexadecimal value", w);
|
|
| 299 |
- return 1; |
|
| 300 |
- } else if((m = findmacro(w))) {
|
|
| 301 |
- int i; |
|
| 302 |
- for(i = 0; i < m->len; ++i) |
|
| 303 |
- if(!parsetoken(m->items[i])) |
|
| 304 |
- return error("Invalid macro", m->name);
|
|
| 305 |
- return 1; |
|
| 306 |
- } |
|
| 307 |
- return error("Invalid token", w);
|
|
| 200 |
+ return scat(scat(scpy(scope, src, 64), "/"), name); |
|
| 308 | 201 |
} |
| 309 | 202 |
|
| 310 |
-static int |
|
| 311 |
-doinclude(const char *filename, int (*pass)(FILE *)) |
|
| 203 |
+static void |
|
| 204 |
+prefill(char *scope, char *label, Uint16 addr) |
|
| 312 | 205 |
{
|
| 313 |
- FILE *f; |
|
| 314 |
- int ret; |
|
| 315 |
- if(!(f = fopen(filename, "r"))) |
|
| 316 |
- return error("Include failed to open", filename);
|
|
| 317 |
- ret = pass(f); |
|
| 318 |
- fclose(f); |
|
| 319 |
- return ret; |
|
| 206 |
+ char subw[64]; |
|
| 207 |
+ Reference *r = &p.refs[p.rlen++]; |
|
| 208 |
+ if(label[1] == '&') |
|
| 209 |
+ scpy(sublabel(subw, scope, label + 2), r->name, 64); |
|
| 210 |
+ else |
|
| 211 |
+ scpy(label + 1, r->name, 64); |
|
| 212 |
+ r->rune = label[0]; |
|
| 213 |
+ r->addr = addr; |
|
| 320 | 214 |
} |
| 321 | 215 |
|
| 322 | 216 |
static int |
| 323 |
-pass1(FILE *f) |
|
| 217 |
+tokenize(char *w, FILE *f) |
|
| 324 | 218 |
{
|
| 325 |
- int ccmnt = 0; |
|
| 326 |
- char w[64], scope[64], subw[64]; |
|
| 327 |
- scope[0] = 0; |
|
| 328 |
- while(fscanf(f, "%63s", w) == 1) {
|
|
| 329 |
- if(skipblock(w, &ccmnt, '(', ')')) continue;
|
|
| 330 |
- if(slen(w) >= 63) |
|
| 331 |
- return error("Pass 1 - Invalid token", w);
|
|
| 332 |
- if(w[0] == '|') {
|
|
| 333 |
- if(!sihx(w + 1)) |
|
| 334 |
- return error("Pass 1 - Invalid padding", w);
|
|
| 335 |
- addr = shex(w + 1); |
|
| 336 |
- } else if(w[0] == '%') {
|
|
| 337 |
- if(!makemacro(w + 1, f)) |
|
| 338 |
- return error("Pass 1 - Invalid macro", w);
|
|
| 339 |
- } else if(w[0] == '@') {
|
|
| 340 |
- if(!makelabel(w + 1)) |
|
| 341 |
- return error("Pass 1 - Invalid label", w);
|
|
| 342 |
- scpy(w + 1, scope, 64); |
|
| 343 |
- } else if(w[0] == '&') {
|
|
| 344 |
- if(!makelabel(sublabel(subw, scope, w + 1))) |
|
| 345 |
- return error("Pass 1 - Invalid sublabel", w);
|
|
| 346 |
- } else if(w[0] == '~') {
|
|
| 347 |
- if(!doinclude(w + 1, pass1)) |
|
| 348 |
- return 0; |
|
| 349 |
- } else if(sihx(w)) |
|
| 350 |
- addr += slen(w) / 2; |
|
| 351 |
- else |
|
| 352 |
- addr += walktoken(w); |
|
| 219 |
+ char word[64]; |
|
| 220 |
+ char subw[64]; |
|
| 221 |
+ char c; |
|
| 222 |
+ Macro *m; |
|
| 223 |
+ int i = 0; |
|
| 224 |
+ if(slen(w) >= 63) |
|
| 225 |
+ return error("Invalid token", w);
|
|
| 226 |
+ switch(w[0]) {
|
|
| 227 |
+ case '(': /* comment */
|
|
| 228 |
+ while(fscanf(f, "%63s", word) == 1) |
|
| 229 |
+ if(word[0] == ')') break; |
|
| 230 |
+ break; |
|
| 231 |
+ case '~': /* include */ |
|
| 232 |
+ if(!doinclude(w + 1)) |
|
| 233 |
+ return error("Invalid include", w);
|
|
| 234 |
+ break; |
|
| 235 |
+ case '%': /* macro */ |
|
| 236 |
+ if(!makemacro(w + 1, f)) |
|
| 237 |
+ return error("Invalid macro", w);
|
|
| 238 |
+ break; |
|
| 239 |
+ case '|': /* pad-absolute */ |
|
| 240 |
+ if(!sihx(w + 1)) |
|
| 241 |
+ return error("Invalid padding", w);
|
|
| 242 |
+ p.ptr = shex(w + 1); |
|
| 243 |
+ break; |
|
| 244 |
+ case '$': /* pad-relative */ |
|
| 245 |
+ if(!sihx(w + 1)) |
|
| 246 |
+ return error("Invalid padding", w);
|
|
| 247 |
+ p.ptr += shex(w + 1); |
|
| 248 |
+ break; |
|
| 249 |
+ case '@': /* label */ |
|
| 250 |
+ if(!makelabel(w + 1)) |
|
| 251 |
+ return error("Invalid label", w);
|
|
| 252 |
+ scpy(w + 1, p.scope, 64); |
|
| 253 |
+ break; |
|
| 254 |
+ case '&': /* sublabel */ |
|
| 255 |
+ if(!makelabel(sublabel(subw, p.scope, w + 1))) |
|
| 256 |
+ return error("Invalid sublabel", w);
|
|
| 257 |
+ break; |
|
| 258 |
+ case '#': /* literals hex */ |
|
| 259 |
+ if(!sihx(w + 1) || (slen(w) != 3 && slen(w) != 5)) |
|
| 260 |
+ return error("Invalid hex literal", w);
|
|
| 261 |
+ if(slen(w) == 3) |
|
| 262 |
+ writebyte(shex(w + 1), 1); |
|
| 263 |
+ else if(slen(w) == 5) |
|
| 264 |
+ writeshort(shex(w + 1), 1); |
|
| 265 |
+ break; |
|
| 266 |
+ case '.': /* literal byte zero-page */ |
|
| 267 |
+ case ',': /* literal byte relative */ |
|
| 268 |
+ prefill(p.scope, w, p.ptr); |
|
| 269 |
+ writebyte(0xff, 1); |
|
| 270 |
+ break; |
|
| 271 |
+ case ';': /* literal short absolute */ |
|
| 272 |
+ prefill(p.scope, w, p.ptr); |
|
| 273 |
+ writeshort(0xffff, 1); |
|
| 274 |
+ break; |
|
| 275 |
+ case ':': /* raw short absolute */ |
|
| 276 |
+ prefill(p.scope, w, p.ptr); |
|
| 277 |
+ writeshort(0xffff, 0); |
|
| 278 |
+ break; |
|
| 279 |
+ case '\'': /* raw char */ |
|
| 280 |
+ writebyte((Uint8)w[1], 0); |
|
| 281 |
+ break; |
|
| 282 |
+ case '"': /* raw string */ |
|
| 283 |
+ i = 0; |
|
| 284 |
+ while((c = w[++i])) |
|
| 285 |
+ writebyte(c, 0); |
|
| 286 |
+ break; |
|
| 287 |
+ case '[': break; /* ignored */ |
|
| 288 |
+ case ']': break; /* ignored */ |
|
| 289 |
+ default: |
|
| 290 |
+ /* opcode */ |
|
| 291 |
+ if(findopcode(w) || scmp(w, "BRK", 4)) |
|
| 292 |
+ writebyte(findopcode(w), 0); |
|
| 293 |
+ /* raw byte */ |
|
| 294 |
+ else if(sihx(w) && slen(w) == 2) |
|
| 295 |
+ writebyte(shex(w), 0); |
|
| 296 |
+ /* raw short */ |
|
| 297 |
+ else if(sihx(w) && slen(w) == 4) |
|
| 298 |
+ writeshort(shex(w), 0); |
|
| 299 |
+ /* macro */ |
|
| 300 |
+ else if((m = findmacro(w))) {
|
|
| 301 |
+ for(i = 0; i < m->len; ++i) |
|
| 302 |
+ if(!tokenize(m->items[i], f)) |
|
| 303 |
+ return 0; |
|
| 304 |
+ return 1; |
|
| 305 |
+ } else |
|
| 306 |
+ return error("Unknown token", w);
|
|
| 353 | 307 |
} |
| 354 |
- rewind(f); |
|
| 355 | 308 |
return 1; |
| 356 | 309 |
} |
| 357 | 310 |
|
| 358 | 311 |
static int |
| 359 |
-pass2(FILE *f) |
|
| 312 |
+resolve(void) |
|
| 360 | 313 |
{
|
| 361 |
- int ccmnt = 0, cmacr = 0; |
|
| 362 |
- char w[64], scope[64], subw[64]; |
|
| 363 |
- scope[0] = 0; |
|
| 364 |
- while(fscanf(f, "%63s", w) == 1) {
|
|
| 365 |
- if(w[0] == '%') continue; |
|
| 366 |
- if(w[0] == '&') continue; |
|
| 367 |
- if(w[0] == '[') continue; |
|
| 368 |
- if(w[0] == ']') continue; |
|
| 369 |
- if(skipblock(w, &ccmnt, '(', ')')) continue;
|
|
| 370 |
- if(skipblock(w, &cmacr, '{', '}')) continue;
|
|
| 371 |
- if(w[0] == '|') {
|
|
| 372 |
- if(p.length && (Uint16)shex(w + 1) < p.ptr) |
|
| 373 |
- return error("Pass 2 - Memory overwrite", w);
|
|
| 374 |
- p.ptr = shex(w + 1); |
|
| 375 |
- continue; |
|
| 376 |
- } else if(w[0] == '$') {
|
|
| 377 |
- if(p.length && (Uint16)(p.ptr + shex(w + 1)) < p.ptr) |
|
| 378 |
- return error("Pass 2 - Memory overwrite", w);
|
|
| 379 |
- p.ptr += shex(w + 1); |
|
| 380 |
- continue; |
|
| 381 |
- } else if(w[0] == '@') {
|
|
| 382 |
- scpy(w + 1, scope, 64); |
|
| 383 |
- continue; |
|
| 384 |
- } else if(w[0] == '~') {
|
|
| 385 |
- if(!doinclude(w + 1, pass2)) |
|
| 386 |
- return 0; |
|
| 387 |
- continue; |
|
| 314 |
+ Label *l; |
|
| 315 |
+ int i; |
|
| 316 |
+ for(i = 0; i < p.rlen; ++i) {
|
|
| 317 |
+ Reference *r = &p.refs[i]; |
|
| 318 |
+ switch(r->rune) {
|
|
| 319 |
+ case '.': |
|
| 320 |
+ if(!(l = findlabel(r->name))) |
|
| 321 |
+ return error("Unknown zero-page reference", r->name);
|
|
| 322 |
+ p.data[r->addr + 1] = l->addr & 0xff; |
|
| 323 |
+ l->refs++; |
|
| 324 |
+ break; |
|
| 325 |
+ case ',': |
|
| 326 |
+ if(!(l = findlabel(r->name))) |
|
| 327 |
+ return error("Unknown relative reference", r->name);
|
|
| 328 |
+ p.data[r->addr + 1] = (Sint8)(l->addr - r->addr - 3); |
|
| 329 |
+ l->refs++; |
|
| 330 |
+ break; |
|
| 331 |
+ case ';': |
|
| 332 |
+ if(!(l = findlabel(r->name))) |
|
| 333 |
+ return error("Unknown absolute reference", r->name);
|
|
| 334 |
+ p.data[r->addr + 1] = l->addr >> 0x8; |
|
| 335 |
+ p.data[r->addr + 2] = l->addr & 0xff; |
|
| 336 |
+ l->refs++; |
|
| 337 |
+ break; |
|
| 338 |
+ case ':': |
|
| 339 |
+ if(!(l = findlabel(r->name))) |
|
| 340 |
+ return error("Unknown absolute reference", r->name);
|
|
| 341 |
+ p.data[r->addr + 0] = l->addr >> 0x8; |
|
| 342 |
+ p.data[r->addr + 1] = l->addr & 0xff; |
|
| 343 |
+ l->refs++; |
|
| 344 |
+ break; |
|
| 345 |
+ default: |
|
| 346 |
+ return error("Unknown reference", r->name);
|
|
| 388 | 347 |
} |
| 389 |
- if(w[1] == '&' && (w[0] == '.' || w[0] == ',' || w[0] == ';' || w[0] == ':')) |
|
| 390 |
- scpy(sublabel(subw, scope, w + 2), w + 1, 64); |
|
| 391 |
- if(!parsetoken(w)) |
|
| 392 |
- return error("Pass 2 - Unknown label", w);
|
|
| 393 | 348 |
} |
| 394 | 349 |
return 1; |
| 395 | 350 |
} |
| 396 | 351 |
|
| 397 | 352 |
static void |
| 398 |
-cleanup(char *filename) |
|
| 353 |
+review(char *filename) |
|
| 399 | 354 |
{
|
| 400 | 355 |
int i; |
| 401 | 356 |
for(i = 0; i < p.llen; ++i) |
| ... | ... |
@@ -406,6 +361,18 @@ cleanup(char *filename) |
| 406 | 361 |
fprintf(stderr, "Assembled %s in %d bytes(%.2f%% used), %d labels, %d macros.\n", filename, p.length - TRIM, p.length / 652.80, p.llen, p.mlen); |
| 407 | 362 |
} |
| 408 | 363 |
|
| 364 |
+static int |
|
| 365 |
+assemble(FILE *f) |
|
| 366 |
+{
|
|
| 367 |
+ char w[64]; |
|
| 368 |
+ scpy("on-reset", p.scope, 64);
|
|
| 369 |
+ while(fscanf(f, "%63s", w) == 1) |
|
| 370 |
+ if(!tokenize(w, f)) |
|
| 371 |
+ return error("Unknown token", w);
|
|
| 372 |
+ resolve(); |
|
| 373 |
+ return 1; |
|
| 374 |
+} |
|
| 375 |
+ |
|
| 409 | 376 |
int |
| 410 | 377 |
main(int argc, char *argv[]) |
| 411 | 378 |
{
|
| ... | ... |
@@ -414,11 +381,11 @@ main(int argc, char *argv[]) |
| 414 | 381 |
return !error("usage", "input.tal output.rom");
|
| 415 | 382 |
if(!(src = fopen(argv[1], "r"))) |
| 416 | 383 |
return !error("Invalid Input", argv[1]);
|
| 417 |
- if(!pass1(src) || !pass2(src)) |
|
| 384 |
+ if(!assemble(src)) |
|
| 418 | 385 |
return !error("Assembly", "Failed to assemble rom.");
|
| 419 | 386 |
if(!(dst = fopen(argv[2], "wb"))) |
| 420 | 387 |
return !error("Invalid Output", argv[2]);
|
| 421 | 388 |
fwrite(p.data + TRIM, p.length - TRIM, 1, dst); |
| 422 |
- cleanup(argv[2]); |
|
| 389 |
+ review(argv[2]); |
|
| 423 | 390 |
return 0; |
| 424 | 391 |
} |