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:
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);