aboutsummaryrefslogtreecommitdiff
path: root/tools/stack_machine_instruction.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/stack_machine_instruction.h')
-rw-r--r--tools/stack_machine_instruction.h148
1 files changed, 148 insertions, 0 deletions
diff --git a/tools/stack_machine_instruction.h b/tools/stack_machine_instruction.h
new file mode 100644
index 0000000..5fd20fc
--- /dev/null
+++ b/tools/stack_machine_instruction.h
@@ -0,0 +1,148 @@
+#include <stdbool.h>
+
+/*
+ * TODO: this enum is to be removed; it it only still here as a cheat sheet
+ * for use when defining missing inline functions for those instructions
+ */
+enum instruction_code {
+ STORE,
+ STORE_P,
+ STOREB,
+ STOREB_P,
+ STOREW,
+ STOREW_P,
+ LOAD,
+ LOAD_P,
+ LOADBZX,
+ LOADBZX_P,
+ LOADBSX,
+ LOADBSX_P,
+ LOADWZX,
+ LOADWZX_P,
+ LOADWSX,
+ LOADWSX_P,
+ HALT,
+ NOP,
+ SWAP,
+ SET_SP,
+ JUMP,
+ TEE,
+ GET_FRAME,
+ CONST,
+ CALL,
+ ADD,
+ SUB,
+ DIV,
+ MUL,
+ DROP,
+ RET,
+ COND_JUMP
+};
+
+#define DATA_NONE 0
+#define DATA_KNOWN 1
+#define DATA_KNOWN_21_BITS 2
+#define DATA_KNOWN_6_BITS 3
+#define DATA_UNKNOWN 4
+
+struct instruction_data {
+ char info;
+ union {
+ uint32_t im;
+ struct instruction **ptr;
+ } data;
+};
+
+struct instruction {
+ struct instruction *prev, *next;
+ uint32_t address;
+ bool address_assigned;
+ uint16_t encoding;
+ struct instruction_data data;
+};
+
+#define NO_DATA ((struct instruction_data) { \
+ .info = DATA_NONE \
+ })
+
+#define POW(n) (((int64_t) 1) << (n))
+
+inline static uint8_t im_instruction_size(int32_t im)
+{
+ if (im < POW(6) && im >= -POW(6))
+ return 2;
+ else if (im < POW(21) && im >= -POW(21))
+ return 4;
+ else
+ return 6;
+}
+
+inline static struct instruction_data im(uint32_t im)
+{
+ struct instruction_data data;
+
+ data.data.im = im;
+
+ uint8_t size = im_instruction_size(im);
+
+ if (size == 2)
+ data.info = DATA_KNOWN_6_BITS;
+ else if (size == 4)
+ data.info = DATA_KNOWN_21_BITS;
+ else
+ data.info = DATA_KNOWN;
+
+ return data;
+}
+
+inline static struct instruction_data ptr(struct instruction **val) {
+ struct instruction_data data;
+
+ data.info = DATA_UNKNOWN;
+ data.data.ptr = val;
+
+ return data;
+}
+
+int add_instruction(struct instruction **expr, uint16_t encoding,
+ struct instruction_data data);
+
+/* Define stack machine instructions, that take immediate operands */
+#define X(instr, encoding) \
+ inline static int i_##instr(struct instruction_data data, \
+ struct instruction **expr) \
+ { \
+ return add_instruction(expr, encoding, data); \
+ }
+
+/* Define stack machine instructions, that *don't* take immediate operands */
+#define Y(instr, encoding) \
+ inline static int i_##instr(struct instruction **expr) \
+ { \
+ return add_instruction(expr, encoding, NO_DATA); \
+ }
+
+X(store, 0x7E00) /* 0111_1110_0xxx_xxxx */
+X(store_p, 0x6E00) /* 0110_1110_0xxx_xxxx */
+X(storeb_p, 0x6C00) /* 0110_1100_0xxx_xxxx */
+X(storew_p, 0x6D00) /* 0110_1101_0xxx_xxxx */
+X(load, 0x5E00) /* 0101_1110_0xxx_xxxx */
+X(load_p, 0x4E00) /* 0100_1110_0xxx_xxxx */
+X(loadbzx_p, 0x4C00) /* 0100_1100_0xxx_xxxx */
+X(loadbsx_p, 0x4C80) /* 0100_1100_1xxx_xxxx */
+X(loadwzx_p, 0x4D00) /* 0100_1101_0xxx_xxxx */
+X(loadwsx_p, 0x4D80) /* 0100_1101_1xxx_xxxx */
+Y(swap, 0x0002) /* 0000_0000_0000_0010 */
+X(set_sp, 0x4000) /* 0100_0000_0xxx_xxxx */
+X(jump, 0x4080) /* 0100_0000_1xxx_xxxx */
+Y(tee, 0x1000) /* 0001_0000_0000_0000 */
+Y(get_frame, 0x1001) /* 0001_0000_0000_0001 */
+X(const, 0x5000) /* 0101_0000_0xxx_xxxx */
+X(call, 0x5080) /* 0101_0000_1xxx_xxxx */
+Y(sub, 0x3001) /* 0011_0000_0000_0001 */
+Y(drop, 0x3004) /* 0011_0000_0000_0100 */
+Y(ret, 0x3080) /* 0011_0000_1000_0000 */
+Y(halt, 0x0000) /* 0000_0000_0000_0000 */
+
+#undef X
+#undef Y