diff options
Diffstat (limited to 'tools/stack_machine_instruction.h')
-rw-r--r-- | tools/stack_machine_instruction.h | 148 |
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 |