mid-kid
6 years ago
3 changed files with 247 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||||
|
CFLAGS := -Wall -Wextra -std=c17 -D_GNU_SOURCE |
||||
|
|
||||
|
LIBS := glib-2.0 |
||||
|
CFLAGS += $(shell pkg-config --cflags $(LIBS)) |
||||
|
LDLIBS := $(shell pkg-config --libs $(LIBS)) |
||||
|
|
||||
|
.PHONY: all |
||||
|
all: main |
||||
|
|
||||
|
.PHONY: clean |
||||
|
clean: |
||||
|
rm -f main |
@ -0,0 +1,37 @@ |
|||||
|
#ip 3 |
||||
|
addi 3 16 3 |
||||
|
seti 1 9 5 |
||||
|
seti 1 1 4 |
||||
|
mulr 5 4 2 |
||||
|
eqrr 2 1 2 |
||||
|
addr 2 3 3 |
||||
|
addi 3 1 3 |
||||
|
addr 5 0 0 |
||||
|
addi 4 1 4 |
||||
|
gtrr 4 1 2 |
||||
|
addr 3 2 3 |
||||
|
seti 2 3 3 |
||||
|
addi 5 1 5 |
||||
|
gtrr 5 1 2 |
||||
|
addr 2 3 3 |
||||
|
seti 1 4 3 |
||||
|
mulr 3 3 3 |
||||
|
addi 1 2 1 |
||||
|
mulr 1 1 1 |
||||
|
mulr 3 1 1 |
||||
|
muli 1 11 1 |
||||
|
addi 2 2 2 |
||||
|
mulr 2 3 2 |
||||
|
addi 2 20 2 |
||||
|
addr 1 2 1 |
||||
|
addr 3 0 3 |
||||
|
seti 0 4 3 |
||||
|
setr 3 9 2 |
||||
|
mulr 2 3 2 |
||||
|
addr 3 2 2 |
||||
|
mulr 3 2 2 |
||||
|
muli 2 14 2 |
||||
|
mulr 2 3 2 |
||||
|
addr 1 2 1 |
||||
|
seti 0 6 0 |
||||
|
seti 0 0 3 |
@ -0,0 +1,198 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <stdio.h> |
||||
|
|
||||
|
#include <glib.h> |
||||
|
|
||||
|
#define REGS 6 |
||||
|
|
||||
|
enum instr_id { |
||||
|
INSTR_ADDR, |
||||
|
INSTR_ADDI, |
||||
|
INSTR_MULR, |
||||
|
INSTR_MULI, |
||||
|
INSTR_BANR, |
||||
|
INSTR_BANI, |
||||
|
INSTR_BORR, |
||||
|
INSTR_BORI, |
||||
|
INSTR_SETR, |
||||
|
INSTR_SETI, |
||||
|
INSTR_GTIR, |
||||
|
INSTR_GTRI, |
||||
|
INSTR_GTRR, |
||||
|
INSTR_EQIR, |
||||
|
INSTR_EQRI, |
||||
|
INSTR_EQRR, |
||||
|
INSTR_ID_COUNT |
||||
|
}; |
||||
|
|
||||
|
struct instr { |
||||
|
enum instr_id i; |
||||
|
int a; |
||||
|
int b; |
||||
|
int c; |
||||
|
}; |
||||
|
|
||||
|
const char *instr_str[] = { |
||||
|
"addr", |
||||
|
"addi", |
||||
|
"mulr", |
||||
|
"muli", |
||||
|
"banr", |
||||
|
"bani", |
||||
|
"borr", |
||||
|
"bori", |
||||
|
"setr", |
||||
|
"seti", |
||||
|
"gtir", |
||||
|
"gtri", |
||||
|
"gtrr", |
||||
|
"eqir", |
||||
|
"eqri", |
||||
|
"eqrr" |
||||
|
}; |
||||
|
|
||||
|
void instr_interpret(int *r, struct instr *i) |
||||
|
{ |
||||
|
switch (i->i) { |
||||
|
case INSTR_ADDR: |
||||
|
case INSTR_MULR: |
||||
|
case INSTR_BANR: |
||||
|
case INSTR_BORR: |
||||
|
case INSTR_GTRR: |
||||
|
case INSTR_EQRR: |
||||
|
if (i->b >= REGS) return; |
||||
|
// fallthrough
|
||||
|
case INSTR_ADDI: |
||||
|
case INSTR_MULI: |
||||
|
case INSTR_BANI: |
||||
|
case INSTR_BORI: |
||||
|
case INSTR_SETR: |
||||
|
case INSTR_GTRI: |
||||
|
case INSTR_EQRI: |
||||
|
if (i->a >= REGS) return; |
||||
|
// fallthrough
|
||||
|
case INSTR_SETI: |
||||
|
if (i->c >= REGS) return; |
||||
|
break; |
||||
|
|
||||
|
case INSTR_GTIR: |
||||
|
case INSTR_EQIR: |
||||
|
if (i->b >= REGS) return; |
||||
|
if (i->c >= REGS) return; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
switch (i->i) { |
||||
|
case INSTR_ADDR: r[i->c] = r[i->a] + r[i->b]; break; |
||||
|
case INSTR_ADDI: r[i->c] = r[i->a] + i->b; break; |
||||
|
case INSTR_MULR: r[i->c] = r[i->a] * r[i->b]; break; |
||||
|
case INSTR_MULI: r[i->c] = r[i->a] * i->b; break; |
||||
|
case INSTR_BANR: r[i->c] = r[i->a] & r[i->b]; break; |
||||
|
case INSTR_BANI: r[i->c] = r[i->a] & i->b; break; |
||||
|
case INSTR_BORR: r[i->c] = r[i->a] | r[i->b]; break; |
||||
|
case INSTR_BORI: r[i->c] = r[i->a] | i->b; break; |
||||
|
case INSTR_SETR: r[i->c] = r[i->a]; break; |
||||
|
case INSTR_SETI: r[i->c] = i->a; break; |
||||
|
case INSTR_GTIR: r[i->c] = (i->a > r[i->b]) ? 1 : 0; break; |
||||
|
case INSTR_GTRI: r[i->c] = (r[i->a] > i->b) ? 1 : 0; break; |
||||
|
case INSTR_GTRR: r[i->c] = (r[i->a] > r[i->b]) ? 1 : 0; break; |
||||
|
case INSTR_EQIR: r[i->c] = (i->a == r[i->b]) ? 1 : 0; break; |
||||
|
case INSTR_EQRI: r[i->c] = (r[i->a] == i->b) ? 1 : 0; break; |
||||
|
case INSTR_EQRR: r[i->c] = (r[i->a] == r[i->b]) ? 1 : 0; break; |
||||
|
default: break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
struct instr *parse_instructions(const char *fname, int *len, int *ip) |
||||
|
{ |
||||
|
FILE *f = fopen(fname, "r"); |
||||
|
if (!f) { |
||||
|
perror(fname); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
GArray *array = g_array_new(FALSE, FALSE, sizeof(struct instr)); |
||||
|
|
||||
|
char *line = NULL; |
||||
|
size_t line_len = 0; |
||||
|
while (getline(&line, &line_len, f) != -1) { |
||||
|
char *args = strchr(line, ' '); |
||||
|
if (!args) continue; |
||||
|
*args++ = '\0'; |
||||
|
|
||||
|
if (strcmp(line, "#ip") == 0) { |
||||
|
*ip = strtol(args, NULL, 0); |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
struct instr instr = {0}; |
||||
|
|
||||
|
for (int i = 0; i < INSTR_ID_COUNT; i++) { |
||||
|
if (strcmp(line, instr_str[i]) == 0) { |
||||
|
instr.i = i; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
sscanf(args, "%d %d %d", &instr.a, &instr.b, &instr.c); |
||||
|
g_array_append_val(array, instr); |
||||
|
} |
||||
|
|
||||
|
free(line); |
||||
|
fclose(f); |
||||
|
|
||||
|
*len = array->len; |
||||
|
return (struct instr *)g_array_free(array, FALSE); |
||||
|
} |
||||
|
|
||||
|
void print_regs(int *regs, FILE *f) |
||||
|
{ |
||||
|
putc('[', f); |
||||
|
for (int i = 0; i < REGS - 1; i++) { |
||||
|
fprintf(f, "%d, ", regs[i]); |
||||
|
} |
||||
|
fprintf(f, "%d]", regs[REGS - 1]); |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) |
||||
|
{ |
||||
|
int debug = 0; |
||||
|
if (argc > 1 && strcmp(argv[1], "-debug") == 0) debug = 1; |
||||
|
|
||||
|
int ip = 0; |
||||
|
int instructions_len = 0; |
||||
|
struct instr *instructions = parse_instructions("input", &instructions_len, &ip); |
||||
|
if (!instructions) return 1; |
||||
|
if (ip >= REGS) ip = 0; |
||||
|
|
||||
|
int *regs = g_new0(int, REGS); |
||||
|
while (regs[ip] >= 0 && regs[ip] < instructions_len) { |
||||
|
struct instr *instr = &instructions[regs[ip]]; |
||||
|
|
||||
|
if (debug) { |
||||
|
fprintf(stderr, "ip=%d ", regs[ip]); |
||||
|
print_regs(regs, stderr); |
||||
|
fprintf(stderr, " %s %d %d %d ", |
||||
|
instr_str[instr->i], instr->a, instr->b, instr->c); |
||||
|
} |
||||
|
|
||||
|
instr_interpret(regs, instr); |
||||
|
|
||||
|
if (debug) { |
||||
|
print_regs(regs, stderr); |
||||
|
putc('\n', stderr); |
||||
|
} |
||||
|
|
||||
|
regs[ip]++; |
||||
|
} |
||||
|
|
||||
|
print_regs(regs, stdout); |
||||
|
putchar('\n'); |
||||
|
|
||||
|
free(regs); |
||||
|
free(instructions); |
||||
|
return 0; |
||||
|
} |
Loading…
Reference in new issue