Reduct  v4.1.3-1-gd06c383
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 Invalid constant value.
40 */
41#define REDUCT_CONST_INVALID ((reduct_const_t) - 1)
42
43/**
44 * @brief Register type.
45 */
46typedef uint16_t reduct_reg_t;
47
48/**
49 * @brief Invalid register value.
50 */
51#define REDUCT_REGISTER_INVALID ((reduct_reg_t) - 1)
52
53/**
54 * @brief Instruction type.
55 * @typedef reduct_inst_t
56 */
57typedef uint32_t reduct_inst_t;
58
59/**
60 * @brief Check if an instruction reads from a specific register.
61 *
62 * @param _inst The instruction.
63 * @param _reg The register index.
64 */
65#define REDUCT_INST_READS_REG(_inst, _reg) \
66 ((REDUCT_OPCODE_READS_A(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_A(_inst)) || \
67 (REDUCT_OPCODE_READS_B(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_B(_inst)) || \
68 (REDUCT_OPCODE_READS_C(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_C(_inst)) || \
69 (REDUCT_OPCODE_READS_RANGE(REDUCT_INST_GET_OP(_inst)) && (_reg) >= REDUCT_INST_GET_A(_inst) && \
70 (_reg) < REDUCT_INST_GET_A(_inst) + REDUCT_INST_GET_B(_inst)))
71
72/**
73 * @brief Check if an instruction writes to a specific register.
74 *
75 * @param _inst The instruction.
76 * @param _reg The register index.
77 */
78#define REDUCT_INST_WRITES_REG(_inst, _reg) \
79 (REDUCT_OPCODE_HAS_TARGET(REDUCT_INST_GET_OP(_inst)) && (_reg) == REDUCT_INST_GET_A(_inst))
80
81#define REDUCT_INST_WIDTH_OPCODE 8U ///< Opcode width in bits.
82#define REDUCT_INST_WIDTH_A 8U ///< A operand width in bits.
83#define REDUCT_INST_WIDTH_B 8U ///< B operand width in bits.
84#define REDUCT_INST_WIDTH_C 8U ///< C operand width in bits.
85#define REDUCT_INST_WIDTH_SAX (REDUCT_INST_WIDTH_A + REDUCT_INST_WIDTH_B) ///< SAx operand width in bits.
86
87/**
88 * @brief The max number of registers per function frame.
89 */
90#define REDUCT_REGISTER_MAX (1U << REDUCT_INST_WIDTH_A)
91/**
92 * @brief The max number of constants per function.
93 */
94#define REDUCT_CONSTANT_MAX (1U << REDUCT_INST_WIDTH_C)
95
96#define REDUCT_INST_POS_OPCODE 0U ///< Opcode position in bits.
97#define REDUCT_INST_POS_A (REDUCT_INST_POS_OPCODE + REDUCT_INST_WIDTH_OPCODE) ///< A operand position in bits.
98#define REDUCT_INST_POS_B (REDUCT_INST_POS_A + REDUCT_INST_WIDTH_A) ///< B operand position in bits.
99#define REDUCT_INST_POS_C (REDUCT_INST_POS_B + REDUCT_INST_WIDTH_B) ///< C operand position in bits.
100#define REDUCT_INST_POS_SAX (REDUCT_INST_POS_A) ///< SAx operand position in bits.
101
102#define REDUCT_INST_MASK_OPCODE ((1U << REDUCT_INST_WIDTH_OPCODE) - 1U) ///< Opcode mask.
103#define REDUCT_INST_MASK_A ((1U << REDUCT_INST_WIDTH_A) - 1U) ///< A operand mask.
104#define REDUCT_INST_MASK_B ((1U << REDUCT_INST_WIDTH_B) - 1U) ///< B operand mask.
105#define REDUCT_INST_MASK_C ((1U << REDUCT_INST_WIDTH_C) - 1U) ///< C operand mask.
106#define REDUCT_INST_MASK_SAX ((1U << REDUCT_INST_WIDTH_SAX) - 1U) ///< SAx operand mask.
107
108/**
109 * @brief Create an instruction with opcode, A, B, and C operands.
110 *
111 * @param _op Opcode operand.
112 * @param _a A operand.
113 * @param _b B operand.
114 * @param _c C operand.
115 */
116#define REDUCT_INST_MAKE_ABC(_op, _a, _b, _c) \
117 ((((reduct_inst_t)(_op)) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE | \
118 (((reduct_inst_t)(_a)) & REDUCT_INST_MASK_A) << REDUCT_INST_POS_A | \
119 (((reduct_inst_t)(_b)) & REDUCT_INST_MASK_B) << REDUCT_INST_POS_B | \
120 (((reduct_inst_t)(_c)) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C)
121
122/**
123 * @brief Create an instruction with opcode and SAx operand, and C operand.
124 *
125 * @param _op Opcode operand.
126 * @param _sax SAx operand.
127 * @param _c C operand.
128 */
129#define REDUCT_INST_MAKE_SAXC(_op, _sax, _c) \
130 ((((reduct_inst_t)(_op)) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE | \
131 (((reduct_inst_t)(_sax)) & REDUCT_INST_MASK_SAX) << REDUCT_INST_POS_A | \
132 (((reduct_inst_t)(_c)) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C)
133
134/**
135 * @brief Get the opcode from an instruction.
136 *
137 * @param _inst Instruction.
138 */
139#define REDUCT_INST_GET_OP(_inst) (((_inst) >> REDUCT_INST_POS_OPCODE) & REDUCT_INST_MASK_OPCODE)
140
141/**
142 * @brief Get the A operand from an instruction.
143 *
144 * @param _inst Instruction.
145 */
146#define REDUCT_INST_GET_A(_inst) (((_inst) >> REDUCT_INST_POS_A) & REDUCT_INST_MASK_A)
147
148/**
149 * @brief Get the B operand from an instruction.
150 *
151 * @param _inst Instruction.
152 */
153#define REDUCT_INST_GET_B(_inst) (((_inst) >> REDUCT_INST_POS_B) & REDUCT_INST_MASK_B)
154
155/**
156 * @brief Get the C operand from an instruction.
157 *
158 * @param _inst Instruction.
159 */
160#define REDUCT_INST_GET_C(_inst) (((_inst) >> REDUCT_INST_POS_C) & REDUCT_INST_MASK_C)
161
162/**
163 * @brief Get the SAX operand from an instruction.
164 *
165 * @param _inst Instruction.
166 */
167#define REDUCT_INST_GET_SAX(_inst) ((int32_t)(int16_t)(((_inst) >> REDUCT_INST_POS_SAX) & REDUCT_INST_MASK_SAX))
168
169/**
170 * @brief Set the opcode in an instruction.
171 *
172 * @param _inst Instruction.
173 * @param _op Opcode value.
174 */
175#define REDUCT_INST_SET_OP(_inst, _op) \
176 (((_inst) & ~(REDUCT_INST_MASK_OPCODE << REDUCT_INST_POS_OPCODE)) | \
177 (((_op) & REDUCT_INST_MASK_OPCODE) << REDUCT_INST_POS_OPCODE))
178
179/**
180 * @brief Set the A operand in an instruction.
181 *
182 * @param _inst Instruction.
183 * @param _a A operand value.
184 */
185#define REDUCT_INST_SET_A(_inst, _a) \
186 (((_inst) & ~(REDUCT_INST_MASK_A << REDUCT_INST_POS_A)) | (((_a) & REDUCT_INST_MASK_A) << REDUCT_INST_POS_A))
187
188/**
189 * @brief Set the B operand in an instruction.
190 *
191 * @param _inst Instruction.
192 * @param _b B operand value.
193 */
194#define REDUCT_INST_SET_B(_inst, _b) \
195 (((_inst) & ~(REDUCT_INST_MASK_B << REDUCT_INST_POS_B)) | (((_b) & REDUCT_INST_MASK_B) << REDUCT_INST_POS_B))
196
197/**
198 * @brief Set the C operand in an instruction.
199 *
200 * @param _inst Instruction.
201 * @param _c C operand value.
202 */
203#define REDUCT_INST_SET_C(_inst, _c) \
204 (((_inst) & ~(REDUCT_INST_MASK_C << REDUCT_INST_POS_C)) | (((_c) & REDUCT_INST_MASK_C) << REDUCT_INST_POS_C))
205
206/**
207 * @brief Set the SAX operand in an instruction.
208 *
209 * @param _inst Instruction.
210 * @param _sax SAX operand value.
211 */
212#define REDUCT_INST_SET_SAX(_inst, _sax) \
213 (((_inst) & ~(REDUCT_INST_MASK_SAX << REDUCT_INST_POS_A)) | (((_sax) & REDUCT_INST_MASK_SAX) << REDUCT_INST_POS_A))
214
215#endif
uint16_t reduct_const_t
Constant index type.
Definition inst.h:36
uint16_t reduct_reg_t
Register type.
Definition inst.h:46
uint32_t reduct_inst_t
Instruction type.
Definition inst.h:57
Bytecode opcodes and properties.