summaryrefslogtreecommitdiffstats
path: root/asm.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-12-25 16:49:51 +0100
committerLouis Burda <quent.burda@gmail.com>2023-12-25 16:49:51 +0100
commit238ac5ab6c47bfe0c9cda1490f97f2d7f5d3eaf6 (patch)
tree8bc0450c20060c262743ee986854741531a19f68 /asm.c
parent8ec5b039472f9fbe24f2eb1c5d8e66a7551a33fd (diff)
downloadtis100-238ac5ab6c47bfe0c9cda1490f97f2d7f5d3eaf6.tar.gz
tis100-238ac5ab6c47bfe0c9cda1490f97f2d7f5d3eaf6.zip
Add support for prefix labels
Diffstat (limited to 'asm.c')
-rw-r--r--asm.c70
1 files changed, 51 insertions, 19 deletions
diff --git a/asm.c b/asm.c
index a339fa8..b0ac9a5 100644
--- a/asm.c
+++ b/asm.c
@@ -16,6 +16,9 @@
#define WHITESPACE " \t\v\r\n,"
enum asm_tok {
+ /* Missing */
+ TOK_NONE = -1,
+
/* Global */
TOK_IN, TOK_OUT, TOK_TPU, TOK_END,
@@ -28,13 +31,13 @@ enum asm_tok {
TOK_NEG, TOK_JMP, TOK_JEZ, TOK_JNZ, TOK_JGZ, TOK_JLZ, TOK_JRO,
/* Misc */
- TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, TOK_NL, TOK_EOF
+ TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, TOK_NL, TOK_EOF,
};
struct asm_tokenizer {
const char *filepath;
FILE *file;
- enum asm_tok tok;
+ enum asm_tok next;
char *tokstr;
size_t lineno, off;
char linebuf[256];
@@ -204,10 +207,17 @@ asm_print_inst(char *buf, size_t n, struct tpu_inst *inst)
static enum asm_tok
tok_next(struct asm_tokenizer *tok)
{
+ enum asm_tok v;
size_t len;
char *s;
int i;
+ if (tok->next != TOK_NONE) {
+ v = tok->next;
+ tok->next = TOK_NONE;
+ return v;
+ }
+
if (!tok->linebuf[tok->off]) {
if (feof(tok->file)) return TOK_EOF;
s = fgets(tok->linebuf, sizeof(tok->linebuf), tok->file);
@@ -333,7 +343,8 @@ tis_load_asm(struct tis *tis, const char *filepath)
struct tpu_map_link *link;
struct tpu_port *port;
enum asm_tok tok, optok;
- char instbuf[TPU_MAX_INST_LEN+1];
+ char rowbuf[TPU_MAX_COLS+1];
+ size_t colsused;
int io_x, io_y;
ssize_t i, k;
size_t len;
@@ -345,10 +356,13 @@ tis_load_asm(struct tis *tis, const char *filepath)
tokenizer.file = fopen(filepath, "r");
if (!tokenizer.file) die("load: fopen '%s':", filepath);
+ tokenizer.next = TOK_NONE;
tokenizer.lineno = 0;
tokenizer.off = 0;
tokenizer.tokstr = NULL;
tokenizer.linebuf[tokenizer.off] = '\0';
+
+ colsused = 0;
while ((tok = tok_next(&tokenizer)) != TOK_EOF) {
switch (tok) {
case TOK_IN:
@@ -380,12 +394,15 @@ tis_load_asm(struct tis *tis, const char *filepath)
io_y = atoi(tokenizer.tokstr + 1);
tok_next_in(&tokenizer, TOK_NL, -1);
- if (tok == TOK_IN)
+ if (tok == TOK_IN) {
tpu_io_port_init(io_port, c, DIR_UP,
PORT_IN, io_x, io_y);
- else
+ } else {
tpu_io_port_init(io_port, c, DIR_DOWN,
PORT_OUT, io_x, io_y);
+ }
+
+ colsused = 0;
break;
case TOK_TPU:
if (tpu) goto disallowed;
@@ -400,12 +417,14 @@ tis_load_asm(struct tis *tis, const char *filepath)
if (!tpu_map_add(&tis->tpu_map, tpu))
die("load: duplicate tpu location X%i Y%i",
tpu->x, tpu->y);
+ colsused = 0;
break;
case TOK_END:
if (!tpu) goto disallowed;
tpu_validate(tpu);
tpu = NULL;
tok_next_in(&tokenizer, TOK_NL, -1);
+ colsused = 0;
break;
case TOK_NOP: case TOK_MOV: case TOK_SWP: case TOK_SAV:
case TOK_ADD: case TOK_SUB: case TOK_NEG: case TOK_JMP:
@@ -442,14 +461,17 @@ tis_load_asm(struct tis *tis, const char *filepath)
if (!inst) die("load: line %lu, invalid instruction",
tokenizer.lineno-1);
- len = asm_print_inst(instbuf, sizeof(instbuf), inst);
- if (len >= sizeof(instbuf))
- die("load: line %lu, inst too long",
+ tpu->rows += 1;
+ if (tpu->inst_cnt > TPU_MAX_INST_CNT || tpu->rows > TPU_MAX_ROWS)
+ die("load: line %lu, tpu has too many rows",
tokenizer.lineno-1);
- if (tpu->inst_cnt + tpu->label_cnt > TPU_MAX_INST_CNT)
- die("load: line %lu, line does not fit",
+ len = asm_print_inst(rowbuf, sizeof(rowbuf), inst);
+ if (colsused + len > TPU_MAX_COLS)
+ die("load: line %lu, tpu row is too long",
tokenizer.lineno-1);
+
+ colsused = 0;
break;
case TOK_COMMENT:
if (tpu && !strcmp(tokenizer.tokstr, "DISABLED"))
@@ -457,19 +479,29 @@ tis_load_asm(struct tis *tis, const char *filepath)
tok_next_in(&tokenizer, TOK_NL, -1);
break;
case TOK_LABEL:
- if (strlen(tokenizer.tokstr) > TPU_MAX_INST_LEN - 1)
+ len = strlen(tokenizer.tokstr);
+ strncpy(rowbuf, tokenizer.tokstr, TPU_MAX_COLS);
+ optok = tok_next(&tokenizer);
+ if (!label_map_add(&tpu->label_map, rowbuf,
+ (int) tpu->inst_cnt, optok != TOK_NL))
+ die("load: line %lu, duplicate label %s (pos)",
+ tokenizer.lineno, rowbuf);
+ if (optok == TOK_NL) {
+ tpu->rows += 1;
+ if (tpu->rows > TPU_MAX_ROWS)
+ die("load: line %lu, line does not fit",
+ tokenizer.lineno);
+ colsused = 0;
+ } else {
+ tokenizer.next = optok;
+ colsused = len + 1;
+ }
+ if (len + 1 > TPU_MAX_COLS)
die("load: line %lu, label too long",
tokenizer.lineno);
- if (!label_map_add(&tpu->label_map,
- tokenizer.tokstr, (int) tpu->inst_cnt))
- die("load: line %lu, duplicate label (pos)",
- tokenizer.lineno);
- tpu->label_cnt += 1;
- if (tpu->inst_cnt + tpu->label_cnt > TPU_MAX_INST_CNT)
- die("load: line %lu, line does not fit",
- tokenizer.lineno);
break;
case TOK_NL:
+ colsused = 0;
break;
default:
goto disallowed;