diff options
Diffstat (limited to 'asm.c')
| -rw-r--r-- | asm.c | 69 |
1 files changed, 46 insertions, 23 deletions
@@ -7,7 +7,7 @@ #include <stdint.h> #define NAMEALPH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" -#define WHITESPACE " \t\v\r\n" +#define WHITESPACE " \t\v\r\n," enum asm_tok { /* Global */ @@ -88,10 +88,10 @@ strlcat_op_name(char *buf, struct tpu_inst_op *op, size_t n) char hhbuf[4]; if (op->type == OP_LIT) { - snprintf(hhbuf, 4, "%hhu", op->lit); + snprintf(hhbuf, 4, "%hhu", op->val.lit); return strdcat(buf, hhbuf, n); } else if (op->type == OP_LABEL) { - return strdcat(buf, op->label, n); + return strdcat(buf, op->val.label, n); } else { return strdcat(buf, op_reprs[op->type], n); } @@ -144,9 +144,7 @@ tok_next(struct asm_tokenizer *tok) if (!s[len]) return TOK_NL; tok->tokstr = (s += len); - if (*s == ',') die("load: line %lu, misaligned comma", tok->lineno); - - len = strcspn(s, WHITESPACE ","); + len = strcspn(s, WHITESPACE); tok->off += len; if (s[len]) { s[len] = '\0'; @@ -181,8 +179,6 @@ tok_next(struct asm_tokenizer *tok) return TOK_ANY; } else if (!strcasecmp(s, "last")) { return TOK_LAST; - } else if (is_lit(s)) { - return TOK_LIT; } else if (!strcasecmp(s, "nop")) { return TOK_NOP; } else if (!strcasecmp(s, "mov")) { @@ -209,10 +205,13 @@ tok_next(struct asm_tokenizer *tok) return TOK_JLZ; } else if (!strcasecmp(s, "jro")) { return TOK_JRO; + } else if (is_lit(s)) { + return TOK_LIT; } else if (*s == '#') { tok->off += strlen(tok->linebuf + tok->off); return TOK_COMMENT; } else if (len && strspn(s, NAMEALPH) == len-1 && s[len-1] == ':') { + s[len-1] = '\0'; return TOK_LABEL; } else if (*s == 'X' && atoi(s+1) > 0) { return TOK_XPOS; @@ -259,13 +258,31 @@ tok_next_in(struct asm_tokenizer *tokenizer, ...) exit(1); } +static void +tpu_validate(struct tpu *tpu) +{ + size_t dst; + int i; + + for (i = 0; i < TPU_MAX_INST; i++) { + if (tpu->insts[i].ops[0].type == OP_LABEL) { + dst = label_map_get(&tpu->labels, + tpu->insts[i].ops[0].val.label); + if (dst == TPU_MAX_INST) + die("load: tpu X%lu Y%lu, label '%s' not defined", + tpu->x, tpu->y, + tpu->insts[i].ops[0].val.label); + } + } +} + void tis_load(struct tis *tis, const char *filepath) { struct asm_tokenizer tokenizer; - enum tpu_inst_op_type op1, op2; + int op1, op2; enum asm_tok op1_tok, op2_tok; - uint8_t op1_lit, op2_lit; + union tpu_inst_op_val op1v, op2v; enum tpu_inst_type inst; struct tpu *tpu = NULL; struct tpu_map_link *link; @@ -273,7 +290,6 @@ tis_load(struct tis *tis, const char *filepath) int stdin_x, stdin_y; int stdout_x, stdout_y; enum asm_tok tok; - char *label; size_t i; tis_deinit(tis); @@ -322,6 +338,7 @@ tis_load(struct tis *tis, const char *filepath) break; case TOK_END: if (!tpu) goto disallowed; + tpu_validate(tpu); tpu = NULL; tok_next_in(&tokenizer, TOK_NL, -1); break; @@ -336,32 +353,39 @@ tis_load(struct tis *tis, const char *filepath) TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); if (op1_tok == TOK_NL) { - if (!tpu_add_inst(tpu, inst, -1, 0, -1, 0)) + if (!tpu_add_inst(tpu, inst, -1, op1v, -1, op2v)) die("load: line %lu, invalid instruction", tokenizer.lineno); break; } - op1 = tok_to_optype(op1_tok); + op1 = (int) tok_to_optype(op1_tok); if (op1 == OP_LIT) - op1_lit = str_to_lit(tokenizer.tokstr); + op1v.lit = str_to_lit(tokenizer.tokstr); + else if (op1 == OP_LABEL) { + op1v.label = strdup(tokenizer.tokstr); + if (!op1v.label) die("strdup:"); + } op2_tok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); if (op2_tok == TOK_NL) { - if (!tpu_add_inst(tpu, inst, (int) op1, - op1_lit, -1, 0)) + if (!tpu_add_inst(tpu, inst, op1, op1v, -1, op2v)) die("load: line %lu, invalid instruction", tokenizer.lineno); break; } - op2 = tok_to_optype(op2_tok); + op2 = (int) tok_to_optype(op2_tok); if (op2 == OP_LIT) - op2_lit = str_to_lit(tokenizer.tokstr); - if (!tpu_add_inst(tpu, inst, (int) op1, op1_lit, - (int) op2, op2_lit)) + op2v.lit = str_to_lit(tokenizer.tokstr); + else if (op2 == OP_LABEL) { + op2v.label = strdup(tokenizer.tokstr); + if (!op2v.label) die("strdup:"); + } + + if (!tpu_add_inst(tpu, inst, op1, op1v, op2, op2v)) die("load: line %lu, invalid instruction", tokenizer.lineno); tok_next_in(&tokenizer, TOK_NL, -1); @@ -370,11 +394,10 @@ tis_load(struct tis *tis, const char *filepath) tok_next_in(&tokenizer, TOK_NL, -1); break; case TOK_LABEL: - label = strdup(tokenizer.tokstr); - if (!label_map_add(&tpu->labels, label, tpu->inst_cnt)) + if (!label_map_add(&tpu->labels, + tokenizer.tokstr, tpu->inst_cnt)) die("load: line %lu, duplicate label", tokenizer.lineno); - tok_next_in(&tokenizer, TOK_NL, -1); break; case TOK_NL: break; |
