commit d21b0e5339a4a2b0a4c1fb7c384f8b3c54de0ca9
parent 7a1d03885ad1781ee45b4cad37a8124e8958cf6c
Author: Louis Burda <quent.burda@gmail.com>
Date: Sun, 19 Mar 2023 00:29:39 +0100
Fixup day 9
Diffstat:
6 files changed, 581 insertions(+), 295 deletions(-)
diff --git a/06/main.c b/06/main.c
@@ -55,7 +55,8 @@ init_planets()
char buf[256], *sep;
int rc;
- hashmap_init(&planets, 100, hashmap_str_hasher, &stdlib_heap_allocator);
+ hashmap_init(&planets, 100, hashmap_str_hasher,
+ hashmap_default_keycmp, &stdlib_heap_allocator);
pos = aoc.input;
end = aoc.input + aoc.input_size;
diff --git a/09/info.mk b/09/info.mk
@@ -0,0 +1,4 @@
+09_SRC = 09/main.c common/main.c common/iccmp.c common/aoc.c common/util.c
+09_SRC += lib/libdvec/build/libdvec.a lib/liballoc/build/liballoc.a
+09_SRC += lib/libmaxint/build/libmaxint.a lib/libhashmap/build/libhashmap.a
+09_HDR = common/aoc.h common/iccmp.h common/util.h
diff --git a/09/main.c b/09/main.c
@@ -1,5 +1,6 @@
#include "aoc.h"
#include "iccmp.h"
+#include "util.h"
#include <stdlib.h>
#include <stdio.h>
@@ -8,56 +9,54 @@ void
part1(void)
{
struct icc icc;
- char *s;
+ char buf[256];
- ASSERT(icc_init(&icc) == OK);
- ASSERT(icc_parse_inst(&icc, aoc.input, aoc.input_size) == OK);
+ icc_init(&icc);
+ icc_parse_inst(&icc, aoc.input, aoc.input_size);
- s = NULL;
- while (icc.status != ICC_HALT) {
+ while (icc.state != ICC_HALT) {
icc_step_inst(&icc);
- switch (icc.status) {
+ switch (icc.state) {
case ICC_INPUT:
mi_setv(&icc.in, 1, MI_POS);
break;
case ICC_OUTPUT:
- debug("OUTPUT : %s\n", (s = mi_decstr(s, &icc.out)));
+ aoc_debug("OUTPUT : %s\n",
+ icc_literal_str(&icc, &icc.out, 0));
break;
}
}
- s = mi_decstr(s, &icc.out);
- aoc.answer = CHKP(aprintf("%s", s));
+ aoc.answer = aprintf("%s", icc_literal_str(&icc, &icc.out, 0));
+ aoc.solution = "2662308295";
- free(s);
- icc_free(&icc);
+ icc_deinit(&icc);
}
void
part2(void)
{
struct icc icc;
- char *s;
+ char buf[256];
- ASSERT(icc_init(&icc) == OK);
- ASSERT(icc_parse_inst(&icc, aoc.input, aoc.input_size) == OK);
+ icc_init(&icc);
+ icc_parse_inst(&icc, aoc.input, aoc.input_size);
- s = NULL;
- while (icc.status != ICC_HALT) {
+ while (icc.state != ICC_HALT) {
icc_step_inst(&icc);
- switch (icc.status) {
+ switch (icc.state) {
case ICC_INPUT:
mi_setv(&icc.in, 2, MI_POS);
break;
case ICC_OUTPUT:
- debug("OUTPUT : %s\n", (s = mi_decstr(s, &icc.out)));
+ aoc_debug("OUTPUT : %s\n",
+ icc_literal_str(&icc, &icc.out, 0));
break;
}
}
- s = mi_decstr(s, &icc.out);
- aoc.answer = CHKP(aprintf("%s", s));
+ aoc.answer = aprintf("%s", icc_literal_str(&icc, &icc.out, 0));
+ aoc.solution = "63441";
- free(s);
- icc_free(&icc);
+ icc_deinit(&icc);
}
diff --git a/common/icc.h b/common/icc.h
@@ -67,6 +67,4 @@ int icc_param_mode(int inst, int param);
int icc_get_param(struct icc *icc, int param, int *out);
int icc_get_dest(struct icc *icc, int param, int *out);
-void icc_input_callback(struct icc *icc, int (*callback)(int));
-
void icc_debug_dump(struct icc *icc, struct dvec *inst);
diff --git a/common/iccmp.c b/common/iccmp.c
@@ -1,439 +1,708 @@
#include "iccmp.h"
+#include "allocator.h"
#include "aoc.h"
+#include "hashmap.h"
+#include "maxint.h"
+#include "util.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+const char *icc_err[] = {
+ [ICC_OK] = "ok",
+ [ICC_INV_INST] = "invalid instruction",
+ [ICC_OOB_WRITE] = "write addr oob",
+ [ICC_OOB_READ] = "read addr oob",
+};
+
+static struct maxint *
+mi_tmp(int64_t val)
+{
+ static mi_ul data = 0;
+ static struct maxint m = { &data, 1, 1, MI_POS };
-int
-icc_init(struct icc *icc)
+ data = ABS(val);
+ m.sign = val >= 0 ? MI_POS : MI_NEG;
+
+ return &m;
+}
+
+static bool
+icc_hashmap_cmp(const void *key1, size_t size1, const void *key2, size_t size2)
{
- icc->instp = 0;
- icc->status = ICC_OK;
- icc->base = MI_INIT;
- icc->debug = aoc.debug;
- mi_setv(&icc->base, 0, MI_POS);
- icc->in = icc->out = MI_INIT;
- icc->r1 = icc->r2 = icc->r3 = icc->r4 = MI_INIT;
- return memvec_init(&icc->instructions, 0, sizeof(struct maxint));
+ return mi_cmp(key1, key2) == 0;
+}
+
+static uint32_t
+icc_addr_hasher(const void *key, size_t size)
+{
+ return mi_cast_ul(key);
}
void
-icc_free(struct icc *icc)
+icc_init(struct icc *icc)
{
- struct maxint *mi;
- int i;
+ int rc;
+
+ icc->state = ICC_RUN;
+
+ mi_init(&icc->rip);
+ mi_setv(&icc->rip, 0, MI_POS);
+
+ mi_init(&icc->base);
+ mi_setv(&icc->base, 0, MI_POS);
- mi_free(&icc->base);
- mi_free(&icc->in);
- mi_free(&icc->out);
- mi_free(&icc->r1);
- mi_free(&icc->r2);
- mi_free(&icc->r3);
- mi_free(&icc->r4);
+ mi_init(&icc->in);
+ mi_init(&icc->out);
+ mi_init(&icc->read_addr);
+ mi_init(&icc->write_addr);
- for (i = 0; i < memvec_len(&icc->instructions); i++)
- mi_free(memvec_get(&icc->instructions, i));
- memvec_free(&icc->instructions);
+ mi_init(&icc->r1);
+ mi_init(&icc->r2);
+ mi_init(&icc->r3);
+ mi_init(&icc->r4);
+ mi_init(&icc->tmp);
+
+ icc->abort_on_err = true;
+
+ icc->line_terminated = true;
+
+ rc = hashmap_init(&icc->instructions, 256, icc_addr_hasher,
+ icc_hashmap_cmp, &stdlib_strict_heap_allocator);
+ assert(!rc);
}
void
-icc_copy(struct icc *dst, struct icc *src)
+icc_deinit(struct icc *icc)
{
- dst->instp = src->instp;
- dst->status = src->status;
- dst->base = src->base;
- dst->in = MI_INIT;
- mi_set(&dst->in, &src->in);
- dst->out = MI_INIT;
- mi_set(&dst->out, &src->out);
- memvec_copy(&dst->instructions, &src->instructions);
+ mi_deinit(&icc->rip);
+ mi_deinit(&icc->base);
+ mi_deinit(&icc->in);
+ mi_deinit(&icc->out);
+ mi_deinit(&icc->read_addr);
+ mi_deinit(&icc->write_addr);
+ mi_deinit(&icc->r1);
+ mi_deinit(&icc->r2);
+ mi_deinit(&icc->r3);
+ mi_deinit(&icc->r4);
+ mi_deinit(&icc->tmp);
+ hashmap_deinit(&icc->instructions);
}
-void *
-icc_inst_copy(struct icc *icc)
+void
+icc_copy(struct icc *dst, struct icc *src)
{
- return CHKP(memdup(icc->instructions.data, icc->instructions.len));
+ dst->state = src->state;
+ mi_set(&dst->rip, &src->rip);
+ mi_set(&dst->base, &src->base);
+ mi_set(&dst->in, &src->in);
+ mi_set(&dst->out, &src->out);
+ hashmap_copy(&dst->instructions, &src->instructions);
}
void
-icc_reset(struct icc *icc, void *instcopy)
+icc_reset(struct icc *icc, struct hashmap *inst)
{
- icc->status = ICC_OK;
- icc->instp = 0;
+ int rc;
+
+ icc->state = ICC_RUN;
+ mi_setv(&icc->rip, 0, MI_POS);
mi_setv(&icc->base, 0, MI_POS);
- mi_setv(&icc->in, 0, MI_POS);
- mi_setv(&icc->out, 0, MI_POS);
- if (instcopy)
- memcpy(icc->instructions.data, instcopy, icc->instructions.len);
+ if (inst) {
+ rc = hashmap_copy(&icc->instructions, inst);
+ assert(!rc);
+ }
}
-int
+void
icc_parse_inst(struct icc *icc, const char *str, size_t len)
{
- const char *line = str, *nline, *end = str + len;
- const char *endptr = NULL;
- struct maxint val;
+ struct maxint *key, *val;
+ const char *pos, *end;
+ char buf[256];
size_t linelen;
+ int64_t v;
+ int *slot;
+ int rc, rip;
+
+ pos = str;
+ end = str + len;
+ rip = 0;
+ while (readtok(buf, sizeof(buf), ',', &pos, end)) {
+ v = parsei64(buf);
- do {
- nline = ntoken(line, end, &linelen, ",\n");
- val = MI_INIT;
- mi_parse(&val, line, &endptr, "0123456789");
- if (endptr && !memchr(",\n", *endptr, 3))
- goto fail;
- if (!memvec_add(&icc->instructions, &val))
- goto fail;
- line = nline;
- } while (nline);
+ key = malloc(sizeof(struct maxint));
+ assert(key != NULL);
- return OK;
+ val = malloc(sizeof(struct maxint));
+ assert(val != NULL);
-fail:
- mi_free(&val);
- return FAIL;
+ mi_init(key);
+ mi_setv(key, rip, MI_POS);
+
+ mi_init(val);
+ mi_setv(val, ABS(v), v >= 0 ? MI_POS : MI_NEG);
+
+ rc = hashmap_set(&icc->instructions, NULL,
+ key, sizeof(struct maxint),
+ val, sizeof(struct maxint));
+ assert(!rc);
+
+ rip += 1;
+ }
}
-void
-icc_debug_op(struct icc *icc, const char *opstr, int n, int dst)
+const char *
+icc_literal_str(struct icc *icc, struct maxint *addr, size_t zfill)
+{
+ static char buf[64];
+
+ mi_dec(addr, buf, sizeof(buf), zfill);
+
+ return buf;
+}
+
+const char *
+icc_value_str(struct icc *icc, struct maxint *addr, size_t zfill)
+{
+ static char buf[62];
+ struct maxint *val;
+ int rc;
+
+ rc = icc_read(icc, addr, &val);
+ if (rc) {
+ snprintf(buf, sizeof(buf), "???");
+ } else {
+ mi_dec(val, buf, sizeof(buf), zfill);
+ }
+
+ return buf;
+}
+
+static void
+icc_debug_op_pre(struct icc *icc)
+{
+ int rc;
+
+ if (!aoc.debug) return;
+
+ fprintf(stderr, "%*s: ", 5, icc_literal_str(icc, &icc->rip, 0));
+ fprintf(stderr, "(%*s) ", 5, icc_value_str(icc, &icc->rip, 5));
+ icc->line_terminated = false;
+}
+
+static void
+icc_debug_op_main(struct icc *icc, struct maxint *tmp, const char *opstr, int n)
{
- inst_t inst;
- char *str;
- int i;
+ struct maxint *inst, *val;
+ int i, rc, instint;
- if (!icc->debug) return;
+ if (!aoc.debug) return;
- icc_get_inst(icc, icc->instp, &inst);
+ rc = icc_read(icc, &icc->rip, &inst);
+ assert(!rc);
- fprintf(stderr, "%04li: (%05lu) %s ", icc->instp, inst, opstr);
+ fprintf(stderr, "%s ", opstr);
+ icc->line_terminated = false;
- str = NULL;
+ mi_set(tmp, &icc->rip);
+ instint = mi_cast_ul(inst);
for (i = 1; i <= n; i++) {
if (i > 1) fprintf(stderr, ", ");
- icc_get_val(icc, icc->instp + i, &icc->r1);
- switch (icc_param_mode(inst, i)) {
+ mi_add(tmp, tmp, mi_tmp(1));
+ rc = icc_read(icc, tmp, &val);
+ if (rc) {
+ fprintf(stderr, "???");
+ continue;
+ }
+ switch (icc_param_mode(instint, i)) {
case ICC_PARAM_IMM:
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "%s", str);
+ fprintf(stderr, "%s", icc_literal_str(icc, val, 0));
break;
case ICC_PARAM_POS:
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "[%s]", str);
- if (i != dst) {
- icc_get_val(icc, mi_cast_ul(&icc->r1), &icc->r1);
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "=%s", str);
- }
+ fprintf(stderr, "[%s]=%s", icc_literal_str(icc, val, 0),
+ icc_value_str(icc, val, 0));
break;
case ICC_PARAM_REL:
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "[B%s%s=", *str == '-' ? "" : "+", str);
- mi_add(&icc->r1, &icc->base);
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "%s]", str);
- if (i != dst) {
- icc_get_val(icc, mi_cast_ul(&icc->r1), &icc->r1);
- str = mi_decstr(str, &icc->r1);
- fprintf(stderr, "=%s", str);
- }
+ mi_add(tmp, &icc->base, val);
+ fprintf(stderr, "[%s+", icc_literal_str(icc, &icc->base, 0));
+ fprintf(stderr, "%s", icc_literal_str(icc, val, 0));
+ fprintf(stderr, "=%s]=%s", icc_literal_str(icc, tmp, 0),
+ icc_value_str(icc, tmp, 0));
break;
default:
- die("ICC: Unknown parmeter mode\n");
+ assert(0);
}
}
- free(str);
+}
+
+static void
+icc_debug_op_post(struct icc *icc, struct maxint *addr)
+{
+ int rc;
+
+ if (!aoc.debug) return;
+
+ fprintf(stderr, " -> [%s]=%s\n", icc_literal_str(icc, addr, 0),
+ icc_value_str(icc, addr, 0));
+ icc->line_terminated = true;
+}
+static void
+icc_debug_op(struct icc *icc, struct maxint *tmp, const char *opstr, int n)
+{
+ int inst;
+ int rc;
+
+ if (!aoc.debug) return;
+
+ icc_debug_op_main(icc, tmp, opstr, n);
fprintf(stderr, "\n");
+ icc->line_terminated = true;
}
-void
+int
icc_inst_add(struct icc *icc)
{
- icc_debug_op(icc, "ADD", 3, 3);
+ struct maxint *dst;
+ int rc;
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
- icc_get_dest(icc, 3, &icc->r3);
+ icc_debug_op_main(icc, &icc->tmp, "ADD", 3);
- mi_add(&icc->r1, &icc->r2);
- icc_set_val(icc, mi_cast_ul(&icc->r3), &icc->r1);
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
+ rc = icc_get_dest(icc, &icc->tmp, 3, &icc->r3);
+ if (rc) return rc;
- icc->instp += 4;
- icc->status = ICC_OK;
+ mi_add(&icc->tmp, &icc->r1, &icc->r2);
+ rc = icc_write(icc, &icc->r3, &icc->tmp);
+ if (rc) return rc;
+
+ icc_debug_op_post(icc, dst);
+
+ mi_add(&icc->rip, &icc->rip, mi_tmp(4));
+ icc->state = ICC_RUN;
+
+ return 0;
}
-void
+int
icc_inst_mul(struct icc *icc)
{
- icc_debug_op(icc, "MUL", 3, 3);
+ int rc;
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
- icc_get_dest(icc, 3, &icc->r3);
+ icc_debug_op_main(icc, &icc->tmp, "MUL", 3);
- mi_mul(&icc->r1, &icc->r2);
- icc_set_val(icc, mi_cast_ul(&icc->r3), &icc->r1);
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
+ rc = icc_get_dest(icc, &icc->tmp, 3, &icc->r3);
+ if (rc) return rc;
- icc->instp += 4;
- icc->status = ICC_OK;
+ mi_mul(&icc->tmp, &icc->r1, &icc->r2);
+ rc = icc_write(icc, &icc->r3, &icc->tmp);
+ if (rc) return rc;
+
+ icc_debug_op_post(icc, &icc->r3);
+
+ mi_add(&icc->rip, &icc->rip, mi_tmp(4));
+ icc->state = ICC_RUN;
+
+ return 0;
}
-void
+int
icc_inst_store(struct icc *icc)
{
- if (icc->status != ICC_INPUT) {
- icc_debug_op(icc, "INPUT", 0, 0);
- icc->status = ICC_INPUT;
+ int rc;
+
+ if (icc->state != ICC_INPUT) {
+ icc_debug_op(icc, &icc->tmp, "INPUT", 0);
+ icc->state = ICC_INPUT;
} else {
- icc_debug_op(icc, "STORE", 1, 1);
- icc_get_dest(icc, 1, &icc->r1);
- icc_set_val(icc, mi_cast_ul(&icc->r1), &icc->in);
+ icc_debug_op_main(icc, &icc->tmp, "STORE", 1);
+
+ rc = icc_get_dest(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+
+ rc = icc_write(icc, &icc->r1, &icc->in);
+ if (rc) return rc;
+
+ icc_debug_op_post(icc, &icc->r1);
- icc->instp += 2;
- icc->status = ICC_OK;
+ mi_add(&icc->rip, &icc->rip, mi_tmp(2));
+ icc->state = ICC_RUN;
}
+
+ return 0;
}
-void
+int
icc_inst_load(struct icc *icc)
{
- if (icc->status != ICC_OUTPUT) {
- icc_debug_op(icc, "LOAD", 1, 0);
- icc_get_param(icc, 1, &icc->out);
+ int out, rc;
+
+ if (icc->state != ICC_OUTPUT) {
+ icc_debug_op(icc, &icc->tmp, "LOAD", 1);
+
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
- icc->status = ICC_OUTPUT;
- icc_debug_op(icc, "OUTPUT", 0, 0);
+ mi_set(&icc->out, &icc->r1);
+ icc->state = ICC_OUTPUT;
+
+ icc_debug_op(icc, &icc->tmp, "OUTPUT", 0);
} else {
- icc->instp += 2;
- icc->status = ICC_OK;
+ mi_add(&icc->rip, &icc->rip, mi_tmp(2));
+ icc->state = ICC_RUN;
}
+
+ return 0;
}
-void
+int
icc_inst_jmp_true(struct icc *icc)
{
- icc_debug_op(icc, "JMPT", 2, 0);
+ int cond, addr;
+ int rc;
+
+ icc_debug_op(icc, &icc->tmp, "JMPT", 2);
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
- if (!mi_zero(&icc->r1)) icc->instp = mi_cast_ul(&icc->r2);
- else icc->instp += 3;
+ if (!mi_zero(&icc->r1)) {
+ mi_set(&icc->rip, &icc->r2);
+ } else {
+ mi_add(&icc->rip, &icc->rip, mi_tmp(3));
+ }
- icc->status = ICC_OK;}
+ icc->state = ICC_RUN;
-void
+ return 0;
+}
+
+int
icc_inst_jmp_false(struct icc *icc)
{
- icc_debug_op(icc, "JMPF", 2, 0);
+ int cond, addr;
+ int rc;
+
+ icc_debug_op(icc, &icc->tmp, "JMPF", 2);
+
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
+ if (mi_zero(&icc->r1)) {
+ mi_set(&icc->rip, &icc->r2);
+ } else {
+ mi_add(&icc->rip, &icc->rip, mi_tmp(3));
+ }
- if (mi_zero(&icc->r1)) icc->instp = mi_cast_ul(&icc->r2);
- else icc->instp += 3;
+ icc->state = ICC_RUN;
- icc->status = ICC_OK;
+ return 0;
}
-void
+int
icc_inst_test_lt(struct icc *icc)
{
- icc_debug_op(icc, "TLT", 3, 3);
+ int rc;
+
+ icc_debug_op_main(icc, &icc->tmp, "TLT", 3);
+
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
+ rc = icc_get_dest(icc, &icc->tmp, 3, &icc->r3);
+ if (rc) return rc;
+
+ mi_setv(&icc->tmp, mi_cmp(&icc->r1, &icc->r2) == -1, MI_POS);
+ rc = icc_write(icc, &icc->r3, &icc->tmp);
+ if (rc) return rc;
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
- icc_get_dest(icc, 3, &icc->r3);
+ icc_debug_op_post(icc, &icc->r3);
- mi_setv(&icc->r4, mi_cmp(&icc->r1, &icc->r2) < 0, MI_POS);
- icc_set_val(icc, mi_cast_ul(&icc->r3), &icc->r4);
+ mi_add(&icc->rip, &icc->rip, mi_tmp(4));
+ icc->state = ICC_RUN;
- icc->instp += 4;
- icc->status = ICC_OK;
+ return 0;
}
-void
+int
icc_inst_test_eq(struct icc *icc)
{
- icc_debug_op(icc, "TEQ", 3, 3);
+ int rc;
+
+ icc_debug_op_main(icc, &icc->tmp, "TEQ", 3);
+
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
+ rc = icc_get_param(icc, &icc->tmp, 2, &icc->r2);
+ if (rc) return rc;
+ rc = icc_get_dest(icc, &icc->tmp, 3, &icc->r3);
+ if (rc) return rc;
+
+ mi_setv(&icc->tmp, mi_cmp(&icc->r1, &icc->r2) == 0, MI_POS);
+ rc = icc_write(icc, &icc->r3, &icc->tmp);
+ if (rc) return rc;
- icc_get_param(icc, 1, &icc->r1);
- icc_get_param(icc, 2, &icc->r2);
- icc_get_dest(icc, 3, &icc->r3);
+ icc_debug_op_post(icc, &icc->r3);
- mi_setv(&icc->r4, mi_cmp(&icc->r1, &icc->r2) == 0, MI_POS);
- icc_set_val(icc, mi_cast_ul(&icc->r3), &icc->r4);
+ mi_add(&icc->rip, &icc->rip, mi_tmp(4));
+ icc->state = ICC_RUN;
- icc->instp += 4;
- icc->status = ICC_OK;
+ return 0;
}
-void
+int
icc_inst_base(struct icc *icc)
{
- icc_debug_op(icc, "BASE", 1, 0);
+ int off, rc;
+
+ icc_debug_op_main(icc, &icc->tmp, "BASE", 1);
- icc_get_param(icc, 1, &icc->r1);
- mi_add(&icc->base, &icc->r1);
+ rc = icc_get_param(icc, &icc->tmp, 1, &icc->r1);
+ if (rc) return rc;
- icc->instp += 2;
- icc->status = ICC_OK;
+ mi_add(&icc->base, &icc->base, &icc->r1);
+ mi_add(&icc->rip, &icc->rip, mi_tmp(2));
+ icc->state = ICC_RUN;
+
+ if (aoc.debug) {
+ fprintf(stderr, " -> BASE:%s\n",
+ icc_literal_str(icc, &icc->base, 0));
+ icc->line_terminated = true;
+ }
+
+ return 0;
}
-void
+int
icc_inst_halt(struct icc *icc)
{
- icc_debug_op(icc, "HALT", 0, 0);
+ icc_debug_op(icc, &icc->tmp, "HALT", 0);
+
+ icc->state = ICC_HALT;
- icc->status = ICC_HALT;
+ return 0;
}
-void
+int
icc_step_inst(struct icc *icc)
{
- inst_t inst;
+ struct maxint *inst;
+ int rc;
+
+ icc_debug_op_pre(icc);
- icc_get_inst(icc, icc->instp, &inst);
- inst %= 100;
+ rc = icc_read(icc, &icc->rip, &inst);
+ if (rc) return rc;
- switch (inst) {
+ switch (mi_cast_ul(inst) % 100) {
case ICC_INST_ADD:
- icc_inst_add(icc);
+ rc = icc_inst_add(icc);
break;
case ICC_INST_MULT:
- icc_inst_mul(icc);
+ rc = icc_inst_mul(icc);
break;
case ICC_INST_STORE:
- icc_inst_store(icc);
+ rc = icc_inst_store(icc);
break;
case ICC_INST_LOAD:
- icc_inst_load(icc);
+ rc = icc_inst_load(icc);
break;
case ICC_INST_JMPT:
- icc_inst_jmp_true(icc);
+ rc = icc_inst_jmp_true(icc);
break;
case ICC_INST_JMPF:
- icc_inst_jmp_false(icc);
+ rc = icc_inst_jmp_false(icc);
break;
case ICC_INST_TLT:
- icc_inst_test_lt(icc);
+ rc = icc_inst_test_lt(icc);
break;
case ICC_INST_TEQ:
- icc_inst_test_eq(icc);
+ rc = icc_inst_test_eq(icc);
break;
case ICC_INST_BASE:
- icc_inst_base(icc);
+ rc = icc_inst_base(icc);
break;
case ICC_INST_HALT:
- icc_inst_halt(icc);
+ rc = icc_inst_halt(icc);
break;
default:
- die("ICC: Unknown instruction: '%i'\n", inst);
+ rc = ICC_INV_INST;
+ break;
+ }
+
+ if (aoc.debug) {
+ if (!icc->line_terminated) {
+ fprintf(stderr, "\n");
+ icc->line_terminated = true;
+ }
+ if (rc != ICC_OK)
+ fprintf(stderr, " -- error: %s --\n", icc_err[rc]);
}
+
+ return rc;
}
-void
-icc_set_val(struct icc *icc, size_t addr, struct maxint *val)
+struct hashmap_link *
+icc_write_any(struct icc *icc, struct maxint *addr, struct maxint *value)
{
- struct maxint *v, blank;
- size_t i, len;
+ struct hashmap_link *link;
+ struct maxint *key, *val;
- len = memvec_len(&icc->instructions);
- if (addr >= len) {
- blank = MI_INIT;
- memvec_resize(&icc->instructions, addr + 1);
- for (i = len; i <= addr; i++)
- memvec_set(&icc->instructions, i, &blank);
- }
- v = memvec_get(&icc->instructions, addr);
- mi_set(v, val);
+ key = malloc(sizeof(struct maxint));
+ assert(key != NULL);
+ mi_init(key);
+ mi_set(key, addr);
+
+ val = malloc(sizeof(struct maxint));
+ assert(val != NULL);
+ mi_init(val);
+ mi_set(val, value);
+
+ assert(!hashmap_set(&icc->instructions, &link,
+ key, sizeof(struct maxint),
+ val, sizeof(struct maxint)));
+
+ return link;
}
-void
-icc_get_val(struct icc *icc, size_t addr, struct maxint *out)
+int
+icc_write(struct icc *icc, struct maxint *addr, struct maxint *val)
{
- struct maxint *src;
+ struct hashmap_link *link;
+
+ link = hashmap_get(&icc->instructions, addr, sizeof(struct maxint));
+ if (!link) {
+ if (addr->sign != MI_POS) {
+ mi_set(&icc->read_addr, addr);
+ assert(!icc->abort_on_err);
+ return ICC_OOB_READ;
+ }
- if (addr >= memvec_len(&icc->instructions)) {
- mi_setv(out, 0, MI_POS);
+ icc_write_any(icc, addr, val);
} else {
- src = memvec_get(&icc->instructions, addr);
- mi_set(out, src);
+ mi_set(link->value, val);
}
+
+ return 0;
}
-void
-icc_get_inst(struct icc *icc, size_t addr, inst_t *out)
+int
+icc_read(struct icc *icc, struct maxint *addr, struct maxint **out)
{
- struct maxint *src;
+ struct hashmap_link *link;
+
+ link = hashmap_get(&icc->instructions, addr, sizeof(struct maxint));
+ if (!link) {
+ if (addr->sign != MI_POS) {
+ mi_set(&icc->read_addr, addr);
+ assert(!icc->abort_on_err);
+ return ICC_OOB_READ;
+ }
+
+ link = icc_write_any(icc, addr, mi_tmp(0));
+ }
+ *out = link->value;
- src = memvec_get(&icc->instructions, addr);
- *out = mi_cast_ul(src);
+ return 0;
}
int
-icc_param_mode(inst_t inst, int param)
+icc_param_mode(int inst, int param)
{
int div, i;
div = 100;
for (i = 1; i < param; i++) div *= 10;
- switch ((inst / div) % 10) {
- case 0:
- return ICC_PARAM_POS;
- case 1:
- return ICC_PARAM_IMM;
- case 2:
- return ICC_PARAM_REL;
- }
-
- die("ICC: Invalid param mode %i\n");
- return -1;
+ return (inst / div) % 10;
}
-void
-icc_get_param(struct icc *icc, int param, struct maxint *out)
+int
+icc_get_param(struct icc *icc, struct maxint *tmp, int param, struct maxint *out)
{
- inst_t inst;
+ struct maxint *inst, *val, *val2;
+ int rc;
+
+ /* TODO: make out double pointer and optimize out mi_set */
+
+ rc = icc_read(icc, &icc->rip, &inst);
+ if (rc) return rc;
+
+ mi_setv(tmp, ABS(param), param >= 0 ? MI_POS : MI_NEG);
+ mi_add(tmp, tmp, &icc->rip);
+ rc = icc_read(icc, tmp, &val);
+ if (rc) return rc;
- icc_get_inst(icc, icc->instp, &inst);
- switch (icc_param_mode(inst, param)) {
+ assert(mi_lastset(inst) == 0);
+ switch (icc_param_mode(mi_cast_ul(inst), param)) {
case ICC_PARAM_IMM:
- icc_get_val(icc, icc->instp + param, out);
+ mi_set(out, val);
break;
case ICC_PARAM_POS:
- icc_get_val(icc, icc->instp + param, out);
- icc_get_val(icc, mi_cast_ul(out), out);
+ rc = icc_read(icc, val, &val2);
+ if (rc) return rc;
+ mi_set(out, val2);
break;
case ICC_PARAM_REL:
- icc_get_val(icc, icc->instp + param, out);
- mi_add(out, &icc->base);
- icc_get_val(icc, mi_cast_ul(out), out);
+ mi_add(tmp, &icc->base, val);
+ rc = icc_read(icc, tmp, &val2);
+ mi_set(out, val2);
break;
default:
- die("ICC: Invalid parmeter mode\n");
+ assert(0);
};
+
+ return 0;
}
-void
-icc_get_dest(struct icc *icc, int param, struct maxint *out)
+int
+icc_get_dest(struct icc *icc, struct maxint *tmp, int param, struct maxint *out)
{
- inst_t inst;
+ struct maxint *inst, *val;
+ int rc;
+
+ rc = icc_read(icc, &icc->rip, &inst);
+ if (rc) return rc;
+
+ mi_setv(tmp, ABS(param), param >= 0 ? MI_POS : MI_NEG);
+ mi_add(tmp, tmp, &icc->rip);
+ rc = icc_read(icc, tmp, &val);
+ if (rc) return rc;
- icc_get_inst(icc, icc->instp, &inst);
- switch (icc_param_mode(inst, param)) {
+ switch (icc_param_mode(mi_cast_ul(inst), param)) {
case ICC_PARAM_POS:
- icc_get_val(icc, icc->instp + param, out);
+ mi_set(out, val);
break;
case ICC_PARAM_REL:
- icc_get_val(icc, icc->instp + param, out);
- mi_add(out, &icc->base);
+ mi_add(out, &icc->base, val);
break;
default:
- die("ICC: Invalid destination parmeter mode\n");
- };
+ assert(0);
+ }
+
+ return 0;
}
void
-icc_set_debug(struct icc *icc, int debug)
+icc_debug_print(struct icc *icc, struct maxint *addr)
{
- icc->debug = debug;
+ if (!aoc.debug) return;
+
+ fprintf(stderr, "[%s] = %s\n", icc_literal_str(icc, addr, 0),
+ icc_value_str(icc, addr, 0));
}
diff --git a/common/iccmp.h b/common/iccmp.h
@@ -1,19 +1,27 @@
#pragma once
-#include "memvec.h"
+#include "dvec.h"
+#include "hashmap.h"
#include "maxint.h"
enum {
- ICC_OK,
+ ICC_RUN,
ICC_INPUT,
ICC_OUTPUT,
ICC_HALT
};
enum {
- ICC_PARAM_IMM,
- ICC_PARAM_POS,
- ICC_PARAM_REL
+ ICC_OK,
+ ICC_INV_INST,
+ ICC_OOB_WRITE,
+ ICC_OOB_READ,
+};
+
+enum {
+ ICC_PARAM_POS = 0,
+ ICC_PARAM_IMM = 1,
+ ICC_PARAM_REL = 2
};
enum {
@@ -30,36 +38,43 @@ enum {
ICC_INST_HALT = 99
};
-typedef uint64_t inst_t;
-
struct icc {
- int status, debug;
+ int state;
struct maxint in, out;
- struct maxint base;
+
+ struct maxint read_addr;
+ struct maxint write_addr;
+ bool abort_on_err;
/* general purpose registers */
- struct maxint r1, r2, r3, r4;
+ struct maxint r1, r2, r3, r4, tmp;
- size_t instp;
- struct memvec instructions;
+ bool line_terminated;
+
+ struct maxint rip, base;
+ struct hashmap instructions;
};
-int icc_init(struct icc *icc);
-void icc_free(struct icc *icc);
+extern const char *icc_err[];
+
+void icc_init(struct icc *icc);
+void icc_deinit(struct icc *icc);
void icc_copy(struct icc *dst, struct icc *src);
+void icc_reset(struct icc *icc, struct hashmap *inst);
-void * icc_inst_copy(struct icc *icc);
-void icc_reset(struct icc *icc, void *instcopy);
+void icc_parse_inst(struct icc *icc, const char *str, size_t len);
+int icc_step_inst(struct icc *icc);
-int icc_parse_inst(struct icc *icc, const char *str, size_t len);
-void icc_step_inst(struct icc *icc);
+struct hashmap_link *icc_write_any(struct icc *icc,
+ struct maxint *addr, struct maxint *in);
+int icc_write(struct icc *icc, struct maxint *addr, struct maxint *in);
+int icc_read(struct icc *icc, struct maxint *addr, struct maxint **out);
-void icc_set_val(struct icc *icc, size_t addr, struct maxint *in);
-void icc_get_val(struct icc *icc, size_t addr, struct maxint *out);
-void icc_get_inst(struct icc *icc, size_t addr, inst_t *out);
+const char *icc_literal_str(struct icc *icc, struct maxint *addr, size_t zfill);
+const char *icc_value_str(struct icc *icc, struct maxint *addr, size_t zfill);
-int icc_param_mode(inst_t inst, int param);
-void icc_get_param(struct icc *icc, int param, struct maxint *out);
-void icc_get_dest(struct icc *icc, int param, struct maxint *out);
+int icc_param_mode(int inst, int param);
+int icc_get_param(struct icc *icc, struct maxint *tmp, int param, struct maxint *out);
+int icc_get_dest(struct icc *icc, struct maxint *tmp, int param, struct maxint *out);
-void icc_set_debug(struct icc *icc, int debug);
+void icc_debug_print(struct icc *icc, struct maxint *addr);