Add initial opcodes file
authorbylex <mbilek06@gmail.com>
Wed, 25 Sep 2024 06:24:18 +0000 (08:24 +0200)
committerbylex <mbilek06@gmail.com>
Wed, 25 Sep 2024 06:24:18 +0000 (08:24 +0200)
opcodes.h [new file with mode: 0644]

diff --git a/opcodes.h b/opcodes.h
new file mode 100644 (file)
index 0000000..1142153
--- /dev/null
+++ b/opcodes.h
@@ -0,0 +1,166 @@
+/* 
+ * 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"};