summaryrefslogtreecommitdiffstats
path: root/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'asm.c')
-rw-r--r--asm.c69
1 files changed, 46 insertions, 23 deletions
diff --git a/asm.c b/asm.c
index eca2c69..cd18747 100644
--- a/asm.c
+++ b/asm.c
@@ -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;