diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-07-26 19:38:36 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-07-26 19:38:36 +0200 |
| commit | 0f06ef7127b669207fd8f09b88ecb660b38eb971 (patch) | |
| tree | d01a688f33f446b3da809f9a154a8748cb5e6506 /tpu.c | |
| parent | 29465804bb9f3bc0eb0f538ec450e9177c0c4767 (diff) | |
| download | tis100-0f06ef7127b669207fd8f09b88ecb660b38eb971.tar.gz tis100-0f06ef7127b669207fd8f09b88ecb660b38eb971.zip | |
Fix more issues caused by negative literals
Diffstat (limited to 'tpu.c')
| -rw-r--r-- | tpu.c | 96 |
1 files changed, 65 insertions, 31 deletions
@@ -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; + } +} |
