summaryrefslogtreecommitdiffstats
path: root/asm.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-07-26 22:15:15 +0200
committerLouis Burda <quent.burda@gmail.com>2023-07-26 22:15:15 +0200
commit33995e119a16fbf13c51cf3a72a6cc52d70a75a8 (patch)
tree872cb861564b452468954639851635410d714697 /asm.c
parent0f06ef7127b669207fd8f09b88ecb660b38eb971 (diff)
downloadtis100-33995e119a16fbf13c51cf3a72a6cc52d70a75a8.tar.gz
tis100-33995e119a16fbf13c51cf3a72a6cc52d70a75a8.zip
Add support for multiple input and output ports
Diffstat (limited to 'asm.c')
-rw-r--r--asm.c180
1 files changed, 118 insertions, 62 deletions
diff --git a/asm.c b/asm.c
index 91623ab..e42da16 100644
--- a/asm.c
+++ b/asm.c
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stdio.h>
#include <string.h>
#include <stdint.h>
@@ -15,7 +16,7 @@
enum asm_tok {
/* Global */
- TOK_STDIN, TOK_STDOUT, TOK_TPU, TOK_END,
+ TOK_IN, TOK_OUT, TOK_TPU, TOK_END,
/* Operands (order like OP_*) */
TOK_ACC, TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN,
@@ -40,7 +41,7 @@ struct asm_tokenizer {
static const char *tok_strs[] = {
/* Global */
- "stdin", "stdout", "tpu", "end",
+ NULL, NULL, "tpu", "end",
/* Operands (order like OP_*) */
"acc", "nil", "left", "right", "up", "down",
@@ -56,15 +57,15 @@ static const char *tok_strs[] = {
static const char *tok_reprs[] = {
/* Global */
- "'STDIN'", "'STDOUT'", "'TPU'", "'END'",
+ "IN.<C>", "OUT.<C>", "TPU", "END",
/* Operands (order like OP_*) */
- "'ACC'", "'NIL'", "'LEFT'", "'RIGHT'", "'UP'", "'DOWN'",
- "'ANY'", "'LAST'", "<LIT>", "<NAME>",
+ "ACC", "NIL", "LEFT", "RIGHT", "UP", "DOWN",
+ "ANY", "LAST", "<LIT>", "<NAME>",
/* Instructions (order like INST_*) */
- "'NOP'", "'MOV'", "'SWP'", "'SAV'", "'ADD'", "'SUB'",
- "'NEG'", "'JMP'", "'JEZ'", "'JNZ'", "'JGZ'", "'JLZ'", "'JRO'",
+ "NOP", "MOV", "SWP", "SAV", "ADD", "SUB",
+ "NEG", "JMP", "JEZ", "JNZ", "JGZ", "JLZ", "JRO",
/* Misc */
"#<COMMENT>", "<LABEL>:", "X<INT>", "Y<INT>", "<NL>", "<EOF>"
@@ -83,7 +84,15 @@ is_int(const char *str)
return true;
}
-bool
+static int
+asm_port_char_to_index(char c)
+{
+ if (!isalpha(c))
+ die("invalid io port char '%c'", c);
+ return tolower(c) - 'a';
+}
+
+static bool
asm_is_lit(const char *str)
{
const char *c;
@@ -95,7 +104,7 @@ asm_is_lit(const char *str)
return !*c;
}
-int
+static int
asm_str_to_lit(const char *str)
{
int m, v, b, i, o;
@@ -159,11 +168,11 @@ tok_to_op(struct asm_tokenizer *tokenizer, enum asm_tok tok)
static size_t
strlcat_op_name(char *buf, struct tpu_inst_op *op, size_t n)
{
- char hhbuf[5];
+ char tmp[5];
if (op->type == OP_LIT) {
- snprintf(hhbuf, 5, "%i", op->val.lit);
- return strdcat(buf, hhbuf, n);
+ snprintf(tmp, 5, "%i", op->val.lit);
+ return strdcat(buf, tmp, n);
} else if (op->type == OP_LABEL) {
return strdcat(buf, op->val.label, n);
} else {
@@ -231,7 +240,11 @@ tok_next(struct asm_tokenizer *tok)
return (enum asm_tok) i;
}
- if (asm_is_lit(s)) {
+ if (!strncasecmp(s, "in.", 3) && len == 4) {
+ return TOK_IN;
+ } else if (!strncasecmp(s, "out.", 4) && len == 5) {
+ return TOK_OUT;
+ } else if (asm_is_lit(s)) {
return TOK_LIT;
} else if (*s == '#') {
tok->off += strlen(tok->linebuf + tok->off);
@@ -307,6 +320,7 @@ tpu_validate(struct tpu *tpu)
void
tis_load(struct tis *tis, const char *filepath)
{
+ struct tpu_io_port *io_port;
struct asm_tokenizer tokenizer;
struct tpu_inst_op op1, op2;
enum tpu_inst_type inst_type;
@@ -314,18 +328,16 @@ tis_load(struct tis *tis, const char *filepath)
struct tpu *tpu = NULL;
struct tpu_map_link *link;
struct tpu_port *port;
- bool stdin_set, stdout_set;
- int stdin_x, stdin_y;
- int stdout_x, stdout_y;
enum asm_tok tok, optok;
char instbuf[TPU_MAX_INST_LEN+1];
- size_t i, len;
+ int io_x, io_y;
+ ssize_t i, k;
+ size_t len;
+ char c;
tis_deinit(tis);
tis_init(tis);
- stdin_set = stdout_set = false;
-
tokenizer.filepath = filepath;
tokenizer.file = fopen(filepath, "r");
if (!tokenizer.file) die("load: fopen '%s':", filepath);
@@ -336,23 +348,41 @@ tis_load(struct tis *tis, const char *filepath)
tokenizer.linebuf[tokenizer.off] = '\0';
while ((tok = tok_next(&tokenizer)) != TOK_EOF) {
switch (tok) {
- case TOK_STDIN:
- if (tpu || stdin_set) goto disallowed;
- tok_next_in(&tokenizer, TOK_XPOS, -1);
- stdin_x = atoi(tokenizer.tokstr + 1);
- tok_next_in(&tokenizer, TOK_YPOS, -1);
- stdin_y = atoi(tokenizer.tokstr + 1);
- tok_next_in(&tokenizer, TOK_NL, -1);
- stdin_set = true;
- break;
- case TOK_STDOUT:
- if (tpu || stdout_set) goto disallowed;
+ case TOK_IN:
+ case TOK_OUT:
+ if (tpu) goto disallowed;
+
+ io_port = malloc(sizeof(struct tpu_io_port));
+ if (!io_port) die("malloc:");
+
+ len = strlen(tokenizer.tokstr);
+ c = tokenizer.tokstr[len-1];
+ k = asm_port_char_to_index(c);
+
+ if (tok == TOK_IN) {
+ if (tis->in_ports[k])
+ die("load: line %lu, duplicate in.%c",
+ tokenizer.lineno, c);
+ tis->in_ports[k] = io_port;
+ } else {
+ if (tis->out_ports[k])
+ die("load: loute %lu, duplicate out.%c",
+ tokenizer.lineno, c);
+ tis->out_ports[k] = io_port;
+ }
+
tok_next_in(&tokenizer, TOK_XPOS, -1);
- stdout_x = atoi(tokenizer.tokstr + 1);
+ io_x = atoi(tokenizer.tokstr + 1);
tok_next_in(&tokenizer, TOK_YPOS, -1);
- stdout_y = atoi(tokenizer.tokstr + 1);
+ io_y = atoi(tokenizer.tokstr + 1);
tok_next_in(&tokenizer, TOK_NL, -1);
- stdout_set = true;
+
+ if (tok == TOK_IN)
+ tpu_io_port_init(io_port, c, DIR_UP,
+ PORT_IN, io_x, io_y);
+ else
+ tpu_io_port_init(io_port, c, DIR_DOWN,
+ PORT_OUT, io_x, io_y);
break;
case TOK_TPU:
if (tpu) goto disallowed;
@@ -445,41 +475,37 @@ tis_load(struct tis *tis, const char *filepath)
for (link = tis->tpu_map.buckets[i]; link; link = link->next) {
tpu_init_ports(link->tpu, &tis->tpu_map);
- if (stdin_set && link->x == stdin_x && link->y == stdin_y) {
- port = &link->tpu->ports[DIR_UP];
- if (port->attached)
- die("load: stdin port in use");
+ for (k = -TIS_MAX_IO_PORTS; k < TIS_MAX_IO_PORTS; k++) {
+ io_port = k < 0 ? tis->in_ports[-k-1]
+ : tis->out_ports[k];
+ if (!io_port || io_port->port.attached) continue;
+ if (link->tpu->x != io_port->x) continue;
+ if (link->tpu->y != io_port->y) continue;
+ port = &link->tpu->ports[io_port->dir];
+ if (port->attached) {
+ die("load: io_port X%i Y%i (%s) busy",
+ io_port->x, io_port->y,
+ dir_reprs[io_port->dir]);
+ }
port->attached = true;
port->dst_tpu = NULL;
- port->dst_port = &tis->stdin_port;
- port->type = PORT_IN;
- tis->stdin_port.attached = true;
- tis->stdin_port.dst_tpu = link->tpu;
- tis->stdin_port.dst_port = port;
- }
-
- if (stdout_set && link->x == stdout_x && link->y == stdout_y) {
- port = &link->tpu->ports[DIR_DOWN];
- if (port->attached)
- die("load: stdout port in use");
- port->attached = true;
- port->dst_tpu = NULL;
- port->dst_port = &tis->stdout_port;
- port->type = PORT_OUT;
- tis->stdout_port.attached = true;
- tis->stdout_port.dst_tpu = link->tpu;
- tis->stdout_port.dst_port = port;
+ port->dst_port = &io_port->port;
+ port->type = io_port->type;
+ io_port->port.attached = true;
+ io_port->port.dst_tpu = link->tpu;
+ io_port->port.dst_port = port;
}
}
}
- if (stdin_set && !tis->stdin_port.attached)
- die("load: stdin tpu (X%i Y%i) not found",
- stdin_x, stdin_y);
-
- if (stdout_set && !tis->stdout_port.attached)
- die("load: stdout tpu (X%i Y%i) not found",
- stdout_x, stdout_y);
+ for (i = -TIS_MAX_IO_PORTS; i < TIS_MAX_IO_PORTS; i++) {
+ io_port = i < 0 ? tis->in_ports[-i-1] : tis->out_ports[i];
+ if (io_port && !io_port->port.attached) {
+ die("load: io_port X%i Y%i (%s) not found",
+ io_port->x, io_port->y,
+ dir_reprs[io_port->dir]);
+ }
+ }
fclose(tokenizer.file);
@@ -494,3 +520,33 @@ disallowed:
tokenizer.lineno, tok_reprs[tok]);
}
}
+
+void
+tis_load_io(struct tis *tis, const char **argv)
+{
+ const char **arg;
+ int n, i;
+ char c;
+
+ for (arg = argv; *arg; arg++) {
+ if (sscanf(*arg, "--in.%c%n", &c, &n) == 1 && n == 6) {
+ i = asm_port_char_to_index(c);
+ if (!tis->in_ports[i])
+ die("in.%c io port not initialized", c);
+ tis->in_ports[i]->file = fopen(*++arg, "r");
+ if (!tis->in_ports[i]->file)
+ die("fopen '%s':", *arg);
+ setvbuf(tis->in_ports[i]->file, NULL, _IONBF, 0);
+ } else if (sscanf(*arg, "--out.%c%n", &c, &n) == 1 && n == 7) {
+ i = asm_port_char_to_index(c);
+ if (!tis->out_ports[i])
+ die("out.%c io port not initialized", c);
+ tis->out_ports[i]->file = fopen(*++arg, "w+");
+ if (!tis->out_ports[i]->file)
+ die("fopen '%s':", *arg);
+ setvbuf(tis->out_ports[i]->file, NULL, _IONBF, 0);
+ } else {
+ die("parse: unknown cmdline option '%s'", *arg);
+ }
+ }
+}