commit 238ac5ab6c47bfe0c9cda1490f97f2d7f5d3eaf6
parent 8ec5b039472f9fbe24f2eb1c5d8e66a7551a33fd
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 25 Dec 2023 16:49:51 +0100
Add support for prefix labels
Diffstat:
M | asm.c | | | 70 | +++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
M | tis100-curses.c | | | 44 | +++++++++++++++++++++++--------------------- |
M | tpu.c | | | 22 | +++++++++++----------- |
M | tpu.h | | | 16 | +++++++++++----- |
4 files changed, 96 insertions(+), 56 deletions(-)
diff --git 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;
diff --git a/tis100-curses.c b/tis100-curses.c
@@ -18,12 +18,10 @@
#define KEY_ESC 0x1b
#define KEY_CTRL(c) ((c) & ~0x60)
-#define TPU_INPUT_ROWS 15
-#define TPU_INPUT_COLS 19
#define TPU_INFO_W 7
#define TPU_INFO_H 4
-#define TPU_W (1 + TPU_INPUT_COLS + TPU_INFO_W)
-#define TPU_H (1 + TPU_INPUT_ROWS + 1)
+#define TPU_W (1 + TPU_MAX_COLS + TPU_INFO_W)
+#define TPU_H (1 + TPU_MAX_ROWS + 1)
#define TIMEOUT 50
@@ -172,10 +170,11 @@ tui_draw_wch(int x, int y, attr_t attr, const cchar_t *c)
static void
tui_draw_tpu(struct tpu *tpu)
{
- char linebuf[TPU_INPUT_COLS + 1];
+ char rowbuf[TPU_MAX_COLS + 1];
struct tpu_port *port;
int sx, sy, x, y, w, h;
- int off, start, inst;
+ int offx, offy, start, inst;
+ struct label *label;
size_t len;
attr_t attr;
int idle;
@@ -195,26 +194,29 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_text(sx + 4, sy + 1 + 4, attr | A_BOLD, " FAILURE ");
tui_draw_text(sx + 4, sy + 1 + 6, attr | A_REVERSE, " ");
} else if (tpu->inst_cnt > 0) {
- start = MAX(0, MIN(tpu->pc - 4, (int) tpu->inst_cnt - TPU_INPUT_ROWS));
+ start = MAX(0, MIN(tpu->pc - 4, (int) tpu->inst_cnt - TPU_MAX_ROWS));
inst = start;
- for (off = 0; off < TPU_INPUT_ROWS && inst < tpu->inst_cnt; ) {
- if (tpu->label_map.labels[inst]) {
- len = strlen(tpu->label_map.labels[inst]);
- if (len > TPU_INPUT_COLS - 1) {
- tui_draw_text(sx + 2, sy + 1 + off, A_DIM,
- "%.*s..:", TPU_INPUT_COLS - 3,
- tpu->label_map.labels[inst]);
+ for (offy = 0; offy < TPU_MAX_ROWS && inst < tpu->inst_cnt; ) {
+ asm_print_inst(rowbuf, sizeof(rowbuf), &tpu->insts[inst]);
+ label = &tpu->label_map.labels[inst];
+ if (label->str) {
+ len = strlen(label->str);
+ tui_draw_text(sx + 1 + offx, sy + 1 + offy,
+ A_DIM, "%s:", label->str);
+ if (label->prefix) {
+ offx += (int) strlen(label->str) + 1;
+ if (offx + 1 + (int) strlen(rowbuf) <= TPU_MAX_COLS)
+ offx += 1;
} else {
- tui_draw_text(sx + 2, sy + 1 + off, A_DIM,
- "%s:", tpu->label_map.labels[inst]);
+ offy += 1;
}
- off++;
}
- asm_print_inst(linebuf, sizeof(linebuf), &tpu->insts[inst]);
- tui_draw_text(sx + 2, sy + 1 + off,
+ tui_draw_text(sx + 1 + offx, sy + 1 + offy,
inst == tpu->pc ? A_STANDOUT | (tpu->idle ? A_DIM : 0) : 0,
- "%-*.*s", TPU_INPUT_COLS, TPU_INPUT_COLS, linebuf);
- inst++; off++;
+ "%-*.*s", TPU_MAX_COLS, TPU_MAX_COLS, rowbuf);
+ inst += 1;
+ offy += 1;
+ offx = 0;
}
}
diff --git a/tpu.c b/tpu.c
@@ -63,8 +63,7 @@ djb_hash(const char *str)
void
label_map_init(struct label_map *map)
{
- memset(map->labels, 0, sizeof(char *) * TPU_MAX_INST_CNT);
- memset(map->buckets, 0, sizeof(void *) * LABEL_MAP_BUCKETS);
+ memset(map, 0, sizeof(struct label_map));
}
void
@@ -77,11 +76,13 @@ label_map_deinit(struct label_map *map)
link = map->buckets[i];
while (link) {
next = link->next;
- free(link->label);
free(link);
link = next;
}
}
+
+ for (i = 0; i < TPU_MAX_INST_CNT; i++)
+ free(map->labels[i].str);
}
static struct label_map_link **
@@ -90,31 +91,30 @@ label_map_link_pos(struct label_map *map, const char *name)
struct label_map_link **link;
link = &map->buckets[djb_hash(name) % LABEL_MAP_BUCKETS];
- while (*link && strcasecmp((*link)->label, name))
+ while (*link && strcasecmp(map->labels[(*link)->pc].str, name))
link = &(*link)->next;
return link;
}
bool
-label_map_add(struct label_map *map, const char *name, int pc)
+label_map_add(struct label_map *map, const char *name, int pc, bool prefix)
{
struct label_map_link **pos, *link;
pos = label_map_link_pos(map, name);
if (*pos) return false;
- if (map->labels[pc]) return false;
+ if (map->labels[pc].str) return false;
+ map->labels[pc].str = strdup(name);
+ if (!map->labels[pc].str) die("strdup:");
+ map->labels[pc].prefix = prefix;
*pos = link = malloc(sizeof(struct label_map_link));
if (!link) die("malloc:");
- link->label = strdup(name);
- if (!link->label) die("strdup:");
link->pc = pc;
link->next = NULL;
- map->labels[pc] = link->label;
-
return true;
}
@@ -217,7 +217,7 @@ tpu_init(struct tpu *tpu)
tpu->acc = 0;
tpu->bak = 0;
tpu->inst_cnt = 0;
- tpu->label_cnt = 0;
+ tpu->rows = 0;
label_map_init(&tpu->label_map);
tpu->last = -1;
diff --git a/tpu.h b/tpu.h
@@ -8,7 +8,8 @@
#define TPU_MAP_BUCKETS 64
#define LABEL_MAP_BUCKETS 64
#define TPU_MAX_INST_CNT 15
-#define TPU_MAX_INST_LEN 18
+#define TPU_MAX_ROWS 15
+#define TPU_MAX_COLS 18
#define TIS_MAX_IO_PORTS 36
/* what tpu will attempt next (order important) */
@@ -42,13 +43,18 @@ union tpu_inst_op_val {
};
struct label_map_link {
- char *label;
int pc;
+ bool prefix;
struct label_map_link *next;
};
+struct label {
+ char *str;
+ bool prefix;
+};
+
struct label_map {
- char *labels[TPU_MAX_INST_CNT]; /* borrowed from label_map_links */
+ struct label labels[TPU_MAX_INST_CNT];
struct label_map_link *buckets[LABEL_MAP_BUCKETS];
};
@@ -98,7 +104,7 @@ struct tpu {
struct label_map label_map;
struct tpu_inst insts[TPU_MAX_INST_CNT];
- size_t inst_cnt, label_cnt;
+ size_t inst_cnt, rows;
};
struct tpu_map_link {
@@ -139,7 +145,7 @@ struct tis_stats {
void label_map_init(struct label_map *map);
void label_map_deinit(struct label_map *map);
-bool label_map_add(struct label_map *map, const char *name, int pc);
+bool label_map_add(struct label_map *map, const char *name, int pc, bool prefix);
int label_map_get(struct label_map *map, const char *name);
void tpu_port_init(struct tpu_port *port, struct tpu *tpu);