aoc-2019-c

git clone https://git.sinitax.com/sinitax/aoc-2019-c
Log | Files | Refs | README | sfeed.txt

commit d21b0e5339a4a2b0a4c1fb7c384f8b3c54de0ca9
parent 7a1d03885ad1781ee45b4cad37a8124e8958cf6c
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun, 19 Mar 2023 00:29:39 +0100

Fixup day 9

Diffstat:
M06/main.c | 3++-
A09/info.mk | 4++++
M09/main.c | 43+++++++++++++++++++++----------------------
Mcommon/icc.h | 2--
Mcommon/iccmp.c | 759+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mcommon/iccmp.h | 65++++++++++++++++++++++++++++++++++++++++-------------------------
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);