diff options
author | Juan J. Martinez <jjm@usebox.net> | 2023-05-09 12:14:54 +0100 |
---|---|---|
committer | Juan J. Martinez <jjm@usebox.net> | 2023-05-09 12:14:54 +0100 |
commit | 00f66fd0d5de41b4c2fdaa7ec2ddf42d041e6af4 (patch) | |
tree | 7421df2a3f7d562a75c7d6ed2143370df32af2d4 | |
parent | d49b5caeb379cc2f49f7f3d04035ffc6fd60bf05 (diff) | |
download | tr8vm-00f66fd0d5de41b4c2fdaa7ec2ddf42d041e6af4.tar.gz tr8vm-00f66fd0d5de41b4c2fdaa7ec2ddf42d041e6af4.zip |
Implelent proper defines
As oppossed to labels to arbitraty addresses.
This also prepares the way to support calculated values.
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | tr8as.c | 163 |
2 files changed, 102 insertions, 65 deletions
@@ -287,8 +287,8 @@ and `>`for the high byte. .dw imm [, imm] Literal word (16-bit value). -.equ label imm -Define a label assigning an arbitrary immediate. Because it is a label, the value will be 16-bit unless `<` or `>` are used. +.equ id value +Define an ID assigning a constant value. When the id is used, it will be replaced with its value. .include "filename" Assemble the file at current position. @@ -35,6 +35,7 @@ #define MAX_ID 0x40 #define MAX_LABELS 0x200 #define MAX_REFS 0x1000 +#define MAX_DEFS 0x200 #define FHH 2 #define FHL 1 @@ -71,6 +72,13 @@ typedef struct typedef struct { + char id[MAX_ID + 1]; + char value[MAX_ID + 1]; + Location loc; +} Define; + +typedef struct +{ uint8_t out[UINT16_MAX + 1]; size_t size; @@ -82,6 +90,9 @@ typedef struct Reference refs[MAX_REFS]; uint16_t rcnt; + + Define defs[MAX_DEFS]; + uint16_t dcnt; } As; typedef struct @@ -166,6 +177,39 @@ static uint8_t isspecial(char c) return c == '$' || c == '_' || c == '.' || c == '#' || c == '<' || c == '>'; } +static char * find_define(As *as, char *word, char *found) +{ + uint8_t i; + + for (i = 0; i < as->dcnt; i++) + if (!strcmp(word, as->defs[i].id)) + return find_define(as, as->defs[i].value, as->defs[i].value); + + return found; +} + +static uint8_t new_define(As *as, char *id, char *value) +{ + if (find_define(as, id, NULL)) + return error_l("Id redefined", &as->loc, id); + + value = find_define(as, value, value); + + if (!strcmp(id, value)) + return error_l("Recursive definition", &as->loc, id); + + strcpy(as->defs[as->dcnt].id, id); + strcpy(as->defs[as->dcnt].value, value); + + as->defs[as->dcnt].loc.filename = as->loc.filename; + as->defs[as->dcnt++].loc.line = as->loc.line; + + if (as->dcnt == MAX_DEFS) + return error("Too many definitions", NULL); + + return 1; +} + static uint8_t next_word(As *as, char **c, char *word, uint8_t *wlen) { *c = skip_whitespace(*c); @@ -187,10 +231,28 @@ static uint8_t next_word(As *as, char **c, char *word, uint8_t *wlen) return 1; } -static uint8_t next_imm(char *word, uint16_t *n) +static uint8_t next_imm(As *as, char *word, uint16_t *n) { + Mod mod = ModNone; + char *def; + *n = 0; + if (*word == '<') + { + mod = ModLow; + word++; + } + else if (*word == '>') + { + mod = ModHigh; + word++; + } + + def = find_define(as, word, NULL); + if (def) + word = def; + if (*word == '0') { /* hex */ @@ -210,7 +272,7 @@ static uint8_t next_imm(char *word, uint16_t *n) word++; } - return *word; + goto done; } /* bin */ else if (word[1] == 'b') @@ -225,7 +287,7 @@ static uint8_t next_imm(char *word, uint16_t *n) word++; } - return *word; + goto done; } } @@ -240,7 +302,18 @@ static uint8_t next_imm(char *word, uint16_t *n) word++; } - return *word; +done: + if (*word == 0) + { + if (mod == ModLow) + *n &= 0xff; + else if (mod == ModHigh) + *n >>= 8; + + return 1; + } + + return 0; } static uint8_t parse_register(char *word) @@ -285,15 +358,6 @@ static uint8_t new_label(As *as, char *word) return 1; } -static uint8_t new_label_imm(As *as, char *word, uint16_t imm) -{ - if (!new_label(as, word)) - return 1; - - as->labels[as->lcnt - 1].addr = imm; - return 1; -} - static uint8_t new_ref(As *as, char *word, uint16_t mask, uint16_t addr) { Mod mod = ModNone; @@ -405,7 +469,7 @@ static uint8_t parse_org(As *as, char **c) if (wlen == 0) return error_l("Syntax error", &as->loc, "expected immediate"); - if (next_imm(word, &as->addr)) + if (!next_imm(as, word, &as->addr)) return error_l("Syntax error", &as->loc, word); if (as->addr > as->size) @@ -573,29 +637,25 @@ static uint8_t parse_incbin(As *as, char **c) static uint8_t parse_equ(As *as, char **c) { - char label[MAX_ID + 1]; - char word[MAX_ID + 1]; + char id[MAX_ID + 1]; + char value[MAX_ID + 1]; uint8_t wlen; - uint16_t imm; /* .equ label imm */ - if (!next_word(as, c, label, &wlen)) + if (!next_word(as, c, id, &wlen)) return 0; if (wlen == 0) - return error_l("Syntax error", &as->loc, "expected label"); + return error_l("Syntax error", &as->loc, "expected id"); - if (!next_word(as, c, word, &wlen)) + if (!next_word(as, c, value, &wlen)) return 0; if (wlen == 0) - return error_l("Syntax error", &as->loc, "expected immediate"); + return error_l("Syntax error", &as->loc, "expected value"); - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - - return new_label_imm(as, label, imm); + return new_define(as, id, value); } static uint8_t parse_db(As *as, char **c) @@ -614,11 +674,8 @@ static uint8_t parse_db(As *as, char **c) if (wlen == 0) return error_l("Syntax error", &as->loc, "expected immediate"); - if (isdigit(*word)) + if (next_imm(as, word, &imm)) { - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - if (imm > 0xff) return error_l("Overflow in immediate", &as->loc, word); } @@ -656,11 +713,8 @@ static uint8_t parse_dw(As *as, char **c) if (wlen == 0) return error_l("Syntax error", &as->loc, "expected immediate"); - if (isdigit(*word)) - { - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - } + if (next_imm(as, word, &imm)) + return error_l("Syntax error", &as->loc, word); else if (!new_ref(as, word, 0xffff, as->addr)) return 0; @@ -773,11 +827,8 @@ static uint8_t parse_r1_r2_or_imm(As *as, char **c, uint8_t *r1, uint8_t *r2, ui return 1; /* ? r1, imm */ - if (isdigit(*word)) + if (next_imm(as, word, imm)) { - if (next_imm(word, imm)) - return error_l("Syntax error", &as->loc, word); - if (*imm > 0xff) return error_l("Overflow in immediate", &as->loc, word); } @@ -818,7 +869,7 @@ static uint8_t parse_r1_imm(As *as, char **c, uint8_t *r1, uint16_t *imm) if (!isdigit(*word)) return error_l("Syntax error", &as->loc, "expected immediate"); - if (next_imm(word, imm)) + if (!next_imm(as, word, imm)) return error_l("Syntax error", &as->loc, word); return 1; @@ -1232,10 +1283,7 @@ static uint8_t parse_indirect(As *as, char **c, uint8_t *r1, uint8_t *r2, uint16 if (wlen == 0) return error_l("Syntax error", &as->loc, "expected immediate"); - if (!isdigit(*word)) - return error_l("Syntax error", &as->loc, "expected immediate"); - - if (next_imm(word, imm)) + if (!next_imm(as, word, imm)) return error_l("Syntax error", &as->loc, word); if (*imm > 0xff) @@ -1301,14 +1349,10 @@ static uint8_t parse_jmp(As *as, char **c) return error_l("Syntax error", &as->loc, "expected label or immediate"); /* JMP imm */ - if (isdigit(*word)) - { - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - } - /* JMP label */ - else if (!new_ref(as, word, 0xffff, as->addr + 2)) - return 0; + if (!next_imm(as, word, &imm)) + /* JMP label */ + if (!new_ref(as, word, 0xffff, as->addr + 2)) + return 0; return (emit(as, 9, 0, FHH, FL) && emit_imm(as, imm)); } @@ -1339,14 +1383,10 @@ static uint8_t parse_call(As *as, char **c) return error_l("Syntax error", &as->loc, "expected label or immediate"); /* CALL imm */ - if (isdigit(*word)) - { - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - } - /* CALL label */ - else if (!new_ref(as, word, 0xffff, as->addr + 2)) - return 0; + if (!next_imm(as, word, &imm)) + /* CALL label */ + if (!new_ref(as, word, 0xffff, as->addr + 2)) + return 0; return (emit(as, 9, 0, FHH, 0) && emit_imm(as, imm)); } @@ -1433,11 +1473,8 @@ static uint8_t parse_ld(As *as, char **c) return emit(as, 1, r1, FHH, (r2 << 6)); /* LD r1, imm */ - if (isdigit(*word)) + if (next_imm(as, word, &imm)) { - if (next_imm(word, &imm)) - return error_l("Syntax error", &as->loc, word); - if (imm > 0xff) return error_l("Overflow in immediate", &as->loc, word); } |