aboutsummaryrefslogtreecommitdiff
path: root/tools/stack_machine_instruction.h
blob: 529ffae6220b4e5039ff71b835399d11c8f32a78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <stdbool.h>

#include "wasm_compile.h"

#define DATA_NONE            0
#define DATA_KNOWN           1
#define DATA_KNOWN_21_BITS   2
#define DATA_KNOWN_6_BITS    3
#define DATA_INSTR_ADDR      4
#define DATA_ADDR_AFTER      5

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;
	const char *name;
};

#define NO_DATA ((struct instruction_data) {			\
			.info = DATA_NONE			\
		})

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_INSTR_ADDR;
	data.data.ptr = val;

	return data;
}

inline static struct instruction_data ptr_after(struct instruction **val) {
	struct instruction_data data;

	data.info = DATA_ADDR_AFTER;
	data.data.ptr = val;

	return data;
}

int add_instruction(struct instruction **expr, uint16_t encoding,
		    struct instruction_data data, const char *name);

/* 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, #instr);	\
	}

/* 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, #instr); \
	}

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(nop,         0x0001) /* 0000_0000_0000_0001 */
Y(swap,        0x0002) /* 0000_0000_0000_0010 */
X(set_sp,      0x4000) /* 0100_0000_0xxx_xxxx */
X(jump,        0x4080) /* 0100_0000_1xxx_xxxx */
X(add_sp,      0x4100) /* 0100_0001_0xxx_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(add,         0x3000) /* 0011_0000_0000_0000 */
Y(sub,         0x3001) /* 0011_0000_0000_0001 */
Y(div,         0x3002) /* 0011_0000_0000_0010 */
Y(mul,         0x3003) /* 0011_0000_0000_0011 */
Y(drop,        0x3004) /* 0011_0000_0000_0100 */
Y(eq,          0x3007) /* 0011_0000_0000_0111 */
Y(lt,          0x3008) /* 0011_0000_0000_1000 */
Y(ult,         0x3009) /* 0011_0000_0000_1001 */
Y(le,          0x300A) /* 0011_0000_0000_1010 */
Y(ule,         0x300B) /* 0011_0000_0000_1011 */
Y(gt,          0x300C) /* 0011_0000_0000_1100 */
Y(ugt,         0x300D) /* 0011_0000_0000_1101 */
Y(ge,          0x300E) /* 0011_0000_0000_1110 */
Y(uge,         0x300F) /* 0011_0000_0000_1111 */
Y(rem,         0x3010) /* 0011_0000_0001_0000 */
Y(ret,         0x3080) /* 0011_0000_1000_0000 */
X(cond_jump,   0x7080) /* 0111_0000_1xxx_xxxx */
X(cond_jump_n, 0x7100) /* 0111_0001_0xxx_xxxx */
Y(halt,        0x0000) /* 0000_0000_0000_0000 */

#undef X
#undef Y