tis100

Reimplementation of Zachtronics TIS-100 as a TUI game
git clone https://git.sinitax.com/sinitax/tis100
Log | Files | Refs | sfeed.txt

commit 29465804bb9f3bc0eb0f538ec450e9177c0c4767
parent 130db985e5594204897ad28d7463e7e9b5ef94c7
Author: Louis Burda <quent.burda@gmail.com>
Date:   Wed, 26 Jul 2023 19:05:46 +0200

Implement limited integer literal parsing

Diffstat:
M.gitignore | 4++--
Masm.c | 51++++++++++++++++++++++++++++++++++++++-------------
Mtest.sh | 2+-
Atest/jro.asm | 12++++++++++++
Atest/jro.in | 1+
Atest/jro.out | 1+
Dtis100 | 0
Dtis100-curses | 0
Mtpu.c | 29++++++++++++++---------------
Mtpu.h | 8++++----
10 files changed, 73 insertions(+), 35 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,5 +1,5 @@ -tis-as -tis-curses +tis100 +tis100-curses compile_commands.json .cache notes diff --git a/asm.c b/asm.c @@ -2,6 +2,7 @@ #include "util.h" #include "tpu.h" +#include <ctype.h> #include <stdarg.h> #include <stdbool.h> #include <string.h> @@ -72,13 +73,13 @@ static const char *tok_reprs[] = { static bool is_lit(const char *str) { - unsigned long v; - char *end; - - v = strtoul(str, &end, 10); - if (!end || *end) return false; + const char *c; - return v < 256; + c = str; + if (*c == '-') c++; + else if (*c == '+') c++; + for (; *c && isdigit(*c); c++); + return !*c; } static bool @@ -94,10 +95,35 @@ is_int(const char *str) return true; } -static uint8_t +static int str_to_lit(const char *str) { - return (uint8_t) atoi(str); + int m, v, b, i, o; + + if (*str == '-') { + m = -1; + o = 1; + } else if (*str == '+') { + m = 1; + o = 1; + } else { + m = 1; + o = 0; + } + + for (b = 1, i = o; str[i]; i++) + b *= 10; + + if (i >= 4 + o) { + v = 1000; + } else { + for (v = 0, i = o; str[i]; i++) { + b /= 10; + v += b * (str[i] - '0'); + } + } + + return MIN(MAX(m * v, -999), 999); } enum tpu_inst_type @@ -133,10 +159,10 @@ 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[4]; + char hhbuf[5]; if (op->type == OP_LIT) { - snprintf(hhbuf, 4, "%i", op->val.lit); + snprintf(hhbuf, 5, "%i", op->val.lit); return strdcat(buf, hhbuf, n); } else if (op->type == OP_LABEL) { return strdcat(buf, op->val.label, n); @@ -263,15 +289,14 @@ tok_next_in(struct asm_tokenizer *tokenizer, ...) static void tpu_validate(struct tpu *tpu) { - size_t dst; - int i; + int dst, i; for (i = 0; i < tpu->inst_cnt; i++) { if (tpu->insts[i].opcnt >= 1 && tpu->insts[i].ops[0].type == OP_LABEL) { dst = label_map_get(&tpu->label_map, tpu->insts[i].ops[0].val.label); - if (dst == TPU_MAX_INST_CNT) + if (dst < 0) die("load: tpu X%i Y%i, label '%s' not defined", tpu->x, tpu->y, tpu->insts[i].ops[0].val.label); diff --git a/test.sh b/test.sh @@ -5,7 +5,7 @@ for f in test/*.asm; do in="$(echo "$f" | cut -d. -f1).in" out="$(echo "$f" | cut -d. -f1).out" tmp="/tmp/tis-test.out" - ./tis-as "$f" "$in" "$tmp" + ./tis100 "$f" "$in" "$tmp" if [ $? -ne 0 ]; then echo "$f" elif ! diff "$out" "$tmp"; then diff --git a/test/jro.asm b/test/jro.asm @@ -0,0 +1,12 @@ +stdin X1 Y1 +stdout X1 Y1 + +tpu X1 Y1 + mov UP, ACC + jro 2 + mov LEFT, NIL + mov ACC, DOWN + jro 300 + jro -300 +end + diff --git a/test/jro.in b/test/jro.in @@ -0,0 +1 @@ +test diff --git a/test/jro.out b/test/jro.out @@ -0,0 +1 @@ +test diff --git a/tis100 b/tis100 Binary files differ. diff --git a/tis100-curses b/tis100-curses Binary files differ. diff --git a/tpu.c b/tpu.c @@ -96,7 +96,7 @@ label_map_link_pos(struct label_map *map, const char *name) } bool -label_map_add(struct label_map *map, const char *name, size_t pc) +label_map_add(struct label_map *map, const char *name, int pc) { struct label_map_link **pos, *link; @@ -117,13 +117,13 @@ label_map_add(struct label_map *map, const char *name, size_t pc) return true; } -size_t +int label_map_get(struct label_map *map, const char *name) { struct label_map_link **link; link = label_map_link_pos(map, name); - if (!*link) return TPU_MAX_INST_CNT; + if (!*link) return -1; return (*link)->pc; } @@ -338,7 +338,7 @@ tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir) } static bool -tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, uint8_t lit) +tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, int lit) { struct tpu_port *port; @@ -354,11 +354,8 @@ tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, uint8_t lit) static void tpu_jmp_label(struct tpu *tpu, const char *label) { - size_t pc; - - pc = label_map_get(&tpu->label_map, label); - if (pc >= TPU_MAX_INST_CNT) abort(); - tpu->pc = (uint8_t) pc; + tpu->pc = label_map_get(&tpu->label_map, label); + if (tpu->pc < 0 || tpu->pc >= tpu->inst_cnt) abort(); } int @@ -378,7 +375,7 @@ tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op) v = tpu_port_read(tpu, (enum tpu_port_dir) i); if (v >= 0) { tpu->last = i; - return (uint8_t) v; + return v; } } return -1; @@ -393,7 +390,7 @@ tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op) } bool -tpu_exec_put(struct tpu *tpu, struct tpu_inst_op *op, uint8_t lit) +tpu_exec_put(struct tpu *tpu, struct tpu_inst_op *op, int lit) { int i; @@ -432,7 +429,7 @@ tpu_exec_mov(struct tpu *tpu, struct tpu_inst *inst) lit = tpu_exec_get(tpu, &inst->ops[0]); if (lit < 0) return STATUS_READ; - if (!tpu_exec_put(tpu, &inst->ops[1], (uint8_t) lit)) + if (!tpu_exec_put(tpu, &inst->ops[1], lit)) return STATUS_WRITE; return STATUS_RUN; @@ -467,13 +464,13 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst) case INST_ADD: val = tpu_exec_get(tpu, &inst->ops[0]); if (val < 0) return STATUS_READ; - tpu->acc += (uint8_t) val; + 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; - tpu->acc -= (uint8_t) val; + tpu->acc = MIN(MAX(tpu->acc - val, -999), 999); tpu->pc += 1; return STATUS_RUN; case INST_NEG: @@ -509,7 +506,9 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst) return STATUS_RUN; case INST_JRO: tpu->pc += inst->ops[0].val.lit; - if (tpu->pc >= tpu->inst_cnt) tpu->pc = 0; + if (tpu->pc < 0) tpu->pc = 0; + if (tpu->pc >= tpu->inst_cnt) + tpu->pc = (int) tpu->inst_cnt - 1; return STATUS_RUN; default: abort(); diff --git a/tpu.h b/tpu.h @@ -42,7 +42,7 @@ union tpu_inst_op_val { struct label_map_link { char *label; - size_t pc; + int pc; struct label_map_link *next; }; @@ -88,7 +88,7 @@ struct tpu { struct label_map label_map; struct tpu_inst insts[TPU_MAX_INST_CNT]; - size_t inst_cnt, label_cnt; + int inst_cnt, label_cnt; }; struct tpu_map_link { @@ -109,8 +109,8 @@ struct tis { 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, size_t pc); -size_t label_map_get(struct label_map *map, const char *name); +bool label_map_add(struct label_map *map, const char *name, int pc); +int label_map_get(struct label_map *map, const char *name); void tpu_port_init(struct tpu_port *port); void tpu_port_deinit(struct tpu_port *port);