Reduct  v4.0.5-1-g4851deb
A functional and immutable language.
Loading...
Searching...
No Matches
inst.h
Go to the documentation of this file.
1#ifndef REDUCT_INST_H
2#define REDUCT_INST_H 1
3
4#include <reduct/defs.h>
5#include <reduct/opcode.h>
6
7/**
8 * @file inst.h
9 * @brief Bytecode instruction format.
10 * @defgroup inst Instruction Format
11 *
12 * Instructions are 32-bit words with the following formats:
13 *
14 * - iABC: [ Opcode:8 | A:8 | B:8 | C:8 ]
15 * - iSAxC: [ Opcode:8 | sAx:16 | C:8 ]
16 *
17 * Fields:
18 * - A: Usually the target/destination register.
19 * - B: Usually the first operand (register).
20 * - C: Usually the second operand (register or constant).
21 * - sAx: Signed offsets for jumps.
22 *
23 * To determine if the C field is a register or a constant the `reduct_mode_t` flags are used to modify the opcode.
24 *
25 * @note The reason we avoid formats such as iABx, used within Lua, is that even if it increases the maximum constant
26 * capacity it means that operations such as `REDUCT_OPCODE_EQUAL` always need to act on registers, which introduces
27 * unnecessary `MOV` instructions to load constants into registers before they can be compared.
28 *
29 * @{
30 */
31
32/**
33 * @brief Constant index type.
34 * @typedef reduct_const_t
35 */
36typedef uint16_t reduct_const_t;
37
38/**
39 * @brief Register type.
40 */
41typedef uint16_t reduct_reg_t;
42
43/**
44 * @brief Invalid register value.
45 */
46#define REDUCT_REGISTER_INVALID ((reduct_reg_t) - 1)
47
48/**
49 * @brief Instruction type.
50 * @typedef reduct_inst_t
51 */
52typedef uint32_t reduct_inst_t;
53
54/**
55 * @brief Check if an instruction reads from a specific register.
56 *
57 * @param _inst The instruction.
58 * @param _reg The register index.
59 */
60#define REDUCT_INST_READS_REG(_inst, _reg) \
61 ((REDUCT_OPCODE_READS_A(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_A(_inst)) || \
62 (REDUCT_OPCODE_READS_B(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_B(_inst)) || \
63 (REDUCT_OPCODE_READS_C(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_C(_inst)) || \
64 (REDUCT_OPCODE_READS_RANGE(REDUCT_INST_GET_OP(_inst)) && (_reg) >= REDUCT_INST_GET_A(_inst) && \
65 (_reg) < REDUCT_INST_GET_A(_inst) + REDUCT_INST_GET_B(_inst)))
66
67/**
68 * @brief Check if an instruction writes to a specific register.
69 *
70 * @param _inst The instruction.
71 * @param _reg The register index.
72 */
73#define REDUCT_INST_WRITES_REG(_inst, _reg) \
74 (REDUCT_OPCODE_HAS_TARGET(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_A(_inst))
75
76#define REDUCT_INST_WIDTH_OPCODE 8U ///< Opcode width in bits.
77#define REDUCT_INST_WIDTH_A 8U ///< A operand width in bits.
78#define REDUCT_INST_WIDTH_B 8U ///< B operand width in bits.
79#define REDUCT_INST_WIDTH_C 8U ///< C operand width in bits.
80#define REDUCT_INST_WIDTH_SAX (REDUCT_INST_WIDTH_A + REDUCT_INST_WIDTH_B) ///< SAx operand width in bits.
81
82/**
83 * @brief The max number of registers per function frame.
84 */
85#define REDUCT_REGISTER_MAX (1U << REDUCT_INST_WIDTH_A)
86/**
87 * @brief The max number of constants per function.
88 */
89#define REDUCT_CONSTANT_MAX (1U << REDUCT_INST_WIDTH_C)
90
91#define REDUCT_INST_POS_OPCODE 0U ///< Opcode position in bits.
92#define REDUCT_INST_POS_A (REDUCT_INST_POS_OPCODE + REDUCT_INST_WIDTH_OPCODE) ///< A operand position in bits.
93#define REDUCT_INST_POS_B (REDUCT_INST_POS_A + REDUCT_INST_WIDTH_A) ///< B operand position in bits.
94#define REDUCT_INST_POS_C (REDUCT_INST_POS_B + REDUCT_INST_WIDTH_B) ///< C operand position in bits.
95#define REDUCT_INST_POS_SAX (REDUCT_INST_POS_A) ///< SAx operand position in bits.
96
97#define REDUCT_INST_MASK_OPCODE ((1U << REDUCT_INST_WIDTH_OPCODE) - 1U) ///< Opcode mask.
98#define REDUCT_INST_MASK_A ((1U << REDUCT_INST_WIDTH_A) - 1U) ///< A operand mask.
99#define REDUCT_INST_MASK_B ((1U << REDUCT_INST_WIDTH_B) - 1U) ///< B operand mask.
100#define REDUCT_INST_MASK_C ((1U << REDUCT_INST_WIDTH_C) - 1U) ///< C operand mask.
101#define REDUCT_INST_MASK_SAX ((1U << REDUCT_INST_WIDTH_SAX) - 1U) ///< SAx operand mask.
102
103/**
104 * @brief Create an instruction with opcode, A, B, and C operands.
105 *
106 * @param _op Opcode operand.
107 * @param _a A operand.
108 * @param _b B operand.
109 * @param _c C operand.
110 */
111#define REDUCT_INST_MAKE_ABC(_op, _a, _b, _c) \
112 ((((reduct_inst_t)(_op)) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE | \
113 (((reduct_inst_t)(_a)) & REDUCT_INST_MASK_A) << REDUCT_INST_POS_A | \
114 (((reduct_inst_t)(_b)) & REDUCT_INST_MASK_B) << REDUCT_INST_POS_B | \
115 (((reduct_inst_t)(_c)) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C)
116
117/**
118 * @brief Create an instruction with opcode and SAx operand, and C operand.
119 *
120 * @param _op Opcode operand.
121 * @param _sax SAx operand.
122 * @param _c C operand.
123 */
124#define REDUCT_INST_MAKE_SAXC(_op, _sax, _c) \
125 ((((reduct_inst_t)(_op)) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE | \
126 (((reduct_inst_t)(_sax)) & REDUCT_INST_MASK_SAX) << REDUCT_INST_POS_A | \
127 (((reduct_inst_t)(_c)) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C)
128
129/**
130 * @brief Get the opcode from an instruction.
131 *
132 * @param _inst Instruction.
133 */
134#define REDUCT_INST_GET_OP(_inst) (((_inst) >> REDUCT_INST_POS_OPCODE) & REDUCT_INST_MASK_OPCODE)
135
136/**
137 * @brief Get the A operand from an instruction.
138 *
139 * @param _inst Instruction.
140 */
141#define REDUCT_INST_GET_A(_inst) (((_inst) >> REDUCT_INST_POS_A) & REDUCT_INST_MASK_A)
142
143/**
144 * @brief Get the B operand from an instruction.
145 *
146 * @param _inst Instruction.
147 */
148#define REDUCT_INST_GET_B(_inst) (((_inst) >> REDUCT_INST_POS_B) & REDUCT_INST_MASK_B)
149
150/**
151 * @brief Get the C operand from an instruction.
152 *
153 * @param _inst Instruction.
154 */
155#define REDUCT_INST_GET_C(_inst) (((_inst) >> REDUCT_INST_POS_C) & REDUCT_INST_MASK_C)
156
157/**
158 * @brief Get the SAX operand from an instruction.
159 *
160 * @param _inst Instruction.
161 */
162#define REDUCT_INST_GET_SAX(_inst) ((int32_t)(int16_t)(((_inst) >> REDUCT_INST_POS_SAX) & REDUCT_INST_MASK_SAX))
163
164/**
165 * @brief Set the opcode in an instruction.
166 *
167 * @param _inst Instruction.
168 * @param _op Opcode value.
169 */
170#define REDUCT_INST_SET_OP(_inst, _op) \
171 (((_inst) & ~(REDUCT_INST_MASK_OPCODE << REDUCT_INST_POS_OPCODE)) | \
172 (((_op) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE))
173
174/**
175 * @brief Set the A operand in an instruction.
176 *
177 * @param _inst Instruction.
178 * @param _a A operand value.
179 */
180#define REDUCT_INST_SET_A(_inst, _a) \
181 (((_inst) & ~(REDUCT_INST_MASK_A << REDUCT_INST_POS_A)) | (((_a) & REDUCT_INST_MASK_A) << REDUCT_INST_POS_A))
182
183/**
184 * @brief Set the B operand in an instruction.
185 *
186 * @param _inst Instruction.
187 * @param _b B operand value.
188 */
189#define REDUCT_INST_SET_B(_inst, _b) \
190 (((_inst) & ~(REDUCT_INST_MASK_B << REDUCT_INST_POS_B)) | (((_b) & REDUCT_INST_MASK_B) << REDUCT_INST_POS_B))
191
192/**
193 * @brief Set the C operand in an instruction.
194 *
195 * @param _inst Instruction.
196 * @param _c C operand value.
197 */
198#define REDUCT_INST_SET_C(_inst, _c) \
199 (((_inst) & ~(REDUCT_INST_MASK_C << REDUCT_INST_POS_C)) | (((_c) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C))
200
201/**
202 * @brief Set the SAX operand in an instruction.
203 *
204 * @param _inst Instruction.
205 * @param _sax SAX operand value.
206 */
207#define REDUCT_INST_SET_SAX(_inst, _sax) \
208 (((_inst) & ~(REDUCT_INST_MASK_SAX << REDUCT_INST_POS_A)) | (((_sax) & REDUCT_INST_MASK_SAX) << REDUCT_INST_POS_A))
209
210#endif
uint16_t reduct_const_t
Constant index type.
Definition inst.h:36
uint16_t reduct_reg_t
Register type.
Definition inst.h:41
uint32_t reduct_inst_t
Instruction type.
Definition inst.h:52
Bytecode opcodes and properties.