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