summaryrefslogtreecommitdiffstats
path: root/tpu.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-07-26 19:38:36 +0200
committerLouis Burda <quent.burda@gmail.com>2023-07-26 19:38:36 +0200
commit0f06ef7127b669207fd8f09b88ecb660b38eb971 (patch)
treed01a688f33f446b3da809f9a154a8748cb5e6506 /tpu.c
parent29465804bb9f3bc0eb0f538ec450e9177c0c4767 (diff)
downloadtis100-0f06ef7127b669207fd8f09b88ecb660b38eb971.tar.gz
tis100-0f06ef7127b669207fd8f09b88ecb660b38eb971.zip
Fix more issues caused by negative literals
Diffstat (limited to 'tpu.c')
-rw-r--r--tpu.c96
1 files changed, 65 insertions, 31 deletions
diff --git a/tpu.c b/tpu.c
index 55e4d53..3e8dee6 100644
--- a/tpu.c
+++ b/tpu.c
@@ -138,7 +138,9 @@ tpu_port_init(struct tpu_port *port)
port->clr_post_run = false;
port->reading = false;
port->writing = false;
+ port->in_set = false;
port->in = -1;
+ port->out_set = false;
port->out = -1;
}
@@ -246,20 +248,22 @@ tpu_update_ports(struct tpu *tpu)
for (i = 0; i < 4; i++) {
port = &tpu->ports[i];
if (!port->attached) continue;
- if (port->out >= 0 && port->dst_port->in < 0) {
- port->dst_port->reading = false;
+ if (port->out_set && !port->dst_port->in_set) {
port->dst_port->in = port->out;
+ port->dst_port->in_set = true;
+ port->dst_port->reading = false;
+ port->out_set = false;
port->writing = false;
- port->out = -1;
}
- if (port->dst_port->out >= 0 && port->in < 0) {
- port->reading = false;
+ if (port->dst_port->out_set && !port->in_set) {
port->in = port->dst_port->out;
+ port->in_set = true;
+ port->reading = false;
+ port->dst_port->out_set = false;
port->dst_port->writing = false;
- port->dst_port->out = -1;
}
if (tpu->status == STATUS_RUN && port->clr_post_run) {
- port->in = -1;
+ port->in_set = false;
port->clr_post_run = false;
}
}
@@ -323,18 +327,19 @@ tpu_add_inst(struct tpu *tpu, enum tpu_inst_type inst_type,
* (->dst_port->out) -- the read value (->in) is cleared at the end of
* an instruction step */
-static int
-tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir)
+static bool
+tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir, int *lit)
{
struct tpu_port *port;
port = &tpu->ports[dir];
port->clr_post_run = true;
- if (port->in < 0) {
+ if (!port->in_set) {
port->reading = true;
- return -1;
+ return false;
}
- return port->in;
+ *lit = port->in;
+ return true;
}
static bool
@@ -343,10 +348,11 @@ tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, int lit)
struct tpu_port *port;
port = &tpu->ports[dir];
- if (port->out >= 0) {
+ if (port->out_set) {
port->writing = true;
return false;
}
+ port->out_set = true;
port->out = lit;
return true;
}
@@ -359,31 +365,33 @@ tpu_jmp_label(struct tpu *tpu, const char *label)
}
int
-tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op)
+tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op, int *lit)
{
- int i, v;
+ int i;
switch (op->type) {
case OP_ACC:
- return tpu->acc;
+ *lit = tpu->acc;
+ return true;
case OP_NIL:
- return 0;
+ *lit = 0;
+ return true;
case OP_LEFT: case OP_RIGHT: case OP_UP: case OP_DOWN:
- return tpu_port_read(tpu, op_to_dir(op->type));
+ return tpu_port_read(tpu, op_to_dir(op->type), lit);
case OP_ANY:
for (i = 0; i < 4; i++) {
- v = tpu_port_read(tpu, (enum tpu_port_dir) i);
- if (v >= 0) {
+ if (tpu_port_read(tpu, (enum tpu_port_dir) i, lit)) {
tpu->last = i;
- return v;
+ return true;
}
}
- return -1;
+ return false;
case OP_LAST:
- if (tpu->last < 0) return 0;
- return tpu_port_read(tpu, (enum tpu_port_dir) tpu->last);
+ if (tpu->last < 0) return false;
+ return tpu_port_read(tpu, (enum tpu_port_dir) tpu->last, lit);
case OP_LIT:
- return op->val.lit;
+ *lit = op->val.lit;
+ return true;
case OP_LABEL:
abort();
}
@@ -426,8 +434,8 @@ tpu_exec_mov(struct tpu *tpu, struct tpu_inst *inst)
if (inst->type != INST_MOV) abort();
- lit = tpu_exec_get(tpu, &inst->ops[0]);
- if (lit < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &lit))
+ return STATUS_READ;
if (!tpu_exec_put(tpu, &inst->ops[1], lit))
return STATUS_WRITE;
@@ -462,14 +470,14 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst)
tpu->pc += 1;
return STATUS_RUN;
case INST_ADD:
- val = tpu_exec_get(tpu, &inst->ops[0]);
- if (val < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &val))
+ return STATUS_READ;
tpu->acc = MIN(MAX(tpu->acc + val, -999), 999);
tpu->pc += 1;
return STATUS_RUN;
case INST_SUB:
- val = tpu_exec_get(tpu, &inst->ops[0]);
- if (val < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &val))
+ return STATUS_READ;
tpu->acc = MIN(MAX(tpu->acc - val, -999), 999);
tpu->pc += 1;
return STATUS_RUN;
@@ -637,3 +645,29 @@ tis_step(struct tis *tis)
return running;
}
+
+void
+tis_communicate(struct tis *tis, FILE *tis_stdin, FILE *tis_stdout)
+{
+ char buf[16], *s;
+ int val;
+
+ if (tis_stdin && tis->stdin_port.attached && !tis->stdin_port.out_set) {
+ while ((s = fgets(buf, sizeof(buf), tis_stdin))) {
+ if ((s = strchr(buf, '\n'))) *s = '\0';
+ if (!*buf) continue;
+ val = (int) strtol(buf, &s, 10);
+ if (!s || *s != '\0')
+ die("communicate: invalid input '%s'", buf);
+ tis->stdin_port.out = val;
+ tis->stdin_port.out_set = true;
+ break;
+ }
+ }
+
+ if (tis->stdout_port.attached && tis->stdout_port.in_set) {
+ if (tis_stdout)
+ fprintf(tis_stdout, "%i\n", tis->stdout_port.in);
+ tis->stdout_port.in_set = false;
+ }
+}