--- /dev/null
+/*
+ * operation codes with description
+ * register size is 2 bytes
+ *
+ * nop, 1 byte length - instruction - no operation
+ *
+ * inc, 3 byte length - instruction + dest register + source register - increment dest register by source register
+ * dec, 3 byte length - instruction + dest register + source register - decrement dest register by source register
+ *
+ * lod, 4 byte length - instruction + dest register + source address - load 2 bytes from memory to register
+ * ldl, 4 byte length - instruction + dest register + number literal - load 2 bytes from instruction to register
+ * sav, 4 byte length - instruction + dest address + source register - save 2 bytes from register to memory
+ * swp, 4 byte length - instruction + address + register - swap 2 bytes between register and memory
+ *
+ * jmp, 2 byte length - instruction + register - jump to address in memory
+ * jez, 4 byte length - instruction + cond register + address - conditional jump to address in memory, if untrue acts as nop
+ *
+ * hlt, 1 byte length - instruction - halts execution
+ *
+ * pts, 2 byte length - instruction + source register - puts a value on the stack
+ * pfs, 2 byte length - instruction + dest register - pulls a value from the stack
+ * stack is 256 values long, 16 bit values
+ *
+ * TODO: figure out input/output
+ *
+ * wex, 2 byte length - instruction + source register - write 2 bytes to external output(stdout)
+ * rex, 2 byte length - instruction + dest register - read from external(stdin) - blocks execution until 2 bytes are read
+ *
+ * all instructions are padded to 4 bytes
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+extern uint16_t regs[256];
+extern uint16_t mem[65536];
+
+extern uint16_t stack[256];
+extern uint8_t stack_pointer;
+
+extern uint16_t current_instruction; // what location is currently being executed
+extern bool halted; // is the execution halted?
+extern uint8_t halted_reason;
+
+void nop(uint8_t unused_1, uint8_t unused_2, uint8_t unused_3)
+{
+ current_instruction += 2;
+ return;
+}
+
+
+
+void inc(uint8_t dest_reg, uint8_t source_reg, uint8_t unused_1)
+{
+ regs[dest_reg] = regs[dest_reg] + regs[source_reg];
+ current_instruction += 2;
+ return;
+}
+
+void dec(uint8_t dest_reg, uint8_t source_reg, uint8_t unused_1)
+{
+ regs[dest_reg] = regs[dest_reg] - regs[source_reg];
+ current_instruction += 2;
+ return;
+}
+
+
+// loads addressed byte and the next byte into register
+void lod(uint8_t dest_reg, uint8_t source_addr_1, uint8_t source_addr_2)
+{
+ uint16_t source_addr = (uint16_t)source_addr_1 << 8 | source_addr_2;
+ regs[dest_reg] = mem[source_addr];
+ current_instruction += 2;
+ return;
+}
+
+void ldl(uint8_t dest_reg, uint8_t num_literal_1, uint8_t num_literal_2)
+{
+ uint16_t num_literal = (uint16_t)num_literal_1 << 8 | num_literal_2;
+ regs[dest_reg] = num_literal;
+ current_instruction += 2;
+ return;
+}
+
+void sav(uint8_t dest_addr_1, uint8_t dest_addr_2, uint8_t source_reg)
+{
+ uint16_t dest_addr = (uint16_t)dest_addr_1 << 8 | dest_addr_2;
+ mem[dest_addr] = regs[source_reg];
+ current_instruction += 2;
+ return;
+}
+
+void swp(uint8_t addr_1, uint8_t addr_2, uint8_t reg)
+{
+ uint16_t addr = (uint16_t)addr_1 << 8 | addr_2;
+ uint16_t temp_storage = regs[reg];
+ regs[reg] = mem[addr];
+ mem[addr] = regs[reg];
+ current_instruction += 2;
+ return;
+}
+
+
+
+void jmp(uint8_t addr_1, uint8_t addr_2, uint8_t unused_1)
+{
+ uint16_t addr = (uint16_t)addr_1 << 8 | addr_2;
+ current_instruction = addr;
+ return;
+}
+
+void jez(uint8_t reg, uint8_t addr_1, uint8_t addr_2)
+{
+ if(regs[reg] == 0)
+ {
+ uint16_t addr = (uint16_t)addr_1 << 8 | addr_2;
+ current_instruction = addr;
+ }
+ else
+ {
+ current_instruction += 2;
+ }
+ return;
+}
+
+
+
+void hlt(uint8_t unused_1, uint8_t unused_2, uint8_t unused_3)
+{
+ halted = true;
+ halted_reason = 1;
+ return;
+}
+
+
+
+void pts(uint8_t source_reg, uint8_t unused_1, uint8_t unused_2)
+{
+ if(stack_pointer == 255)
+ {
+ halted = true; // stack has overflowed, halt execution
+ halted_reason = 2;
+ }
+ else
+ {
+ stack[stack_pointer++] = regs[source_reg];
+ }
+ return;
+}
+
+void pfs(uint8_t dest_reg, uint8_t unused_1, uint8_t unused_2)
+{
+ if(stack_pointer == 0)
+ {
+ halted = true; // stack has underflowed, halt execution
+ halted_reason = 3;
+ }
+ else
+ {
+ regs[dest_reg] = stack[--stack_pointer];
+ }
+ return;
+}
+
+void (*opcodes[16]) (uint8_t, uint8_t, uint8_t) = {nop, inc, dec, lod, ldl, sav, swp, jmp, jez, hlt, pts, pfs};
+char opcodes_names[16][3] = {"nop", "inc", "dec", "lod", "ldl", "sav", "swp", "jmp", "jez", "hlt", "pts", "pfs"};