#include #include #include #include #include #include typedef struct { uint8_t opcode; uint32_t a, b, c; } Instruction; Instruction instructions[1024]; enum { ADDR, ADDI, MULR, MULI, BANR, BANI, BORR, BORI, SETR, SETI, GTIR, GTRI, GTRR, EQIR, EQRI, EQRR, IP, }; const char *names[] = { "addr", "addi", "mulr", "muli", "banr", "bani", "borr", "bori", "setr", "seti", "gtir", "gtri", "gtrr", "eqir", "eqri", "eqrr", "#ip", }; int instruction_read(Instruction *i, FILE *file) { char mnemonic[64] = {0}; size_t count = fscanf(file, "%s %u %u %u", mnemonic, &i->a, &i->b, &i->c); if (count != 4 && count != 2) return 0; for (int opcode = 0; opcode <= IP; opcode++) { if (strcmp(names[opcode], mnemonic) == 0) { i->opcode = opcode; return 1; } } printf("Unknown mnemonic '%s'\n", mnemonic); return 0; } void instruction_execute(const Instruction* instructions, uint32_t* r, uint32_t* ip_r) { const Instruction i = instructions[r[*ip_r]]; #ifdef DEBUG const char *name = names[i.opcode]; printf( "ip=%2u [%10u, %10u, %10u, %10u, %10u, %10u] %4s %2u %2u %2u ", r[*ip_r], r[0], r[1], r[2], r[3], r[4], r[5], name, i.a, i.b, i.c ); #endif switch (i.opcode) { // Addition case ADDR: r[i.c] = r[i.a] + r[i.b]; break; case ADDI: r[i.c] = r[i.a] + i.b; break; // Multiplication case MULR: r[i.c] = r[i.a] * r[i.b]; break; case MULI: r[i.c] = r[i.a] * i.b; break; // Bitwise AND case BANR: r[i.c] = (r[i.a] & r[i.b]); break; case BANI: r[i.c] = (r[i.a] & i.b); break; // Bitwise OR case BORR: r[i.c] = (r[i.a] | r[i.b]); break; case BORI: r[i.c] = (r[i.a] | i.b); break; // Assignment case SETR: r[i.c] = r[i.a]; break; case SETI: r[i.c] = i.a; break; // Greater-than testing case GTIR: r[i.c] = (i.a > r[i.b]); break; case GTRI: r[i.c] = (r[i.a] > i.b); break; case GTRR: r[i.c] = (r[i.a] > r[i.b]); break; // Equality testing case EQIR: r[i.c] = (i.a == r[i.b]); break; case EQRI: r[i.c] = (r[i.a] == i.b); break; case EQRR: r[i.c] = (r[i.a] == r[i.b]); break; default: assert(0); } #ifdef DEBUG printf("[%10u, %10u, %10u, %10u, %10u, %10u]\r", r[0], r[1], r[2], r[3], r[4], r[5]); #endif getchar(); r[*ip_r] += 1; } int main(int argc, char **argv) { if (argc != 2) { printf("Usage: %s [input]\n", argv[0]); return EXIT_FAILURE; } FILE *file = fopen(argv[1], "r"); #ifdef DEBUG puts("================="); puts(" READING INPUT"); puts("================="); #endif uint32_t registers[6] = {1, 0}; uint32_t ip_reg = 0; size_t instr_count = 0; for (instr_count = 0; instr_count < 1024 && instruction_read(&instructions[instr_count], file); instr_count++) { const Instruction instr = instructions[instr_count]; if (instr.opcode == IP) { // Assuming that an #ip can only occur once here ip_reg = instr.a; instr_count -= 1; } #ifdef DEBUG printf("opcode: %2d (%s), a: %d, b: %d, c: %d\n", instr.opcode, names[instr.opcode], instr.a, instr.b, instr.c); #endif } fclose(file); #ifdef DEBUG puts(""); puts("======================="); puts(" STARTING SIMULATION"); puts("======================="); #endif while (registers[ip_reg] < instr_count) { instruction_execute(instructions, registers, &ip_reg); } printf("%d\n", registers[0]); return EXIT_SUCCESS; }