==> src/opcodes.c <==1/* The instruction table: the MVP and the proposals we run as rows; SIMD and atomics by rule
2 * (their immediates only). */
3#include "wasm/opcodes.h"
4
5#include <stddef.h>
6
7#define R(code, nm, im, feat, sg, mb) [code] = {code, nm, im, feat, sg, mb}
8#define N(code, nm, sg) R(code, nm, WASM_IMM_NONE, 0, sg, 0)
9#define L(code, nm, sg, mb) R(code, nm, WASM_IMM_MEMARG, 0, sg, mb)
10#define REF WASM_F_REFERENCE_TYPES
11#define BULK WASM_F_BULK_MEMORY
12#define SAT WASM_F_SAT_FLOAT_TO_INT
13
14static const wasm_opinfo main_ops[256] = {
15 R(0x00, "Unreachable", WASM_IMM_NONE, 0, NULL, 0),
16 R(0x01, "Nop", WASM_IMM_NONE, 0, NULL, 0),
17 R(0x02, "Block", WASM_IMM_BLOCK, 0, NULL, 0),
18 R(0x03, "Loop", WASM_IMM_BLOCK, 0, NULL, 0),
19 R(0x04, "If", WASM_IMM_BLOCK, 0, NULL, 0),
20 R(0x05, "Else", WASM_IMM_NONE, 0, NULL, 0),
21 R(0x0b, "End", WASM_IMM_NONE, 0, NULL, 0),
22 R(0x0c, "Br", WASM_IMM_LABEL, 0, NULL, 0),
23 R(0x0d, "BrIf", WASM_IMM_LABEL, 0, NULL, 0),
24 R(0x0e, "BrTable", WASM_IMM_BR_TABLE, 0, NULL, 0),
25 R(0x0f, "Return", WASM_IMM_NONE, 0, NULL, 0),
26 R(0x10, "Call", WASM_IMM_FUNC, 0, NULL, 0),
27 R(0x11, "CallIndirect", WASM_IMM_CALL_INDIRECT, 0, NULL, 0),
28 R(0x1a, "Drop", WASM_IMM_NONE, 0, NULL, 0),
29 R(0x1b, "Select", WASM_IMM_NONE, 0, NULL, 0),
30 R(0x1c, "TypedSelect", WASM_IMM_SELECT_T, REF, NULL, 0),
31 R(0x20, "LocalGet", WASM_IMM_LOCAL, 0, NULL, 0),
32 R(0x21, "LocalSet", WASM_IMM_LOCAL, 0, NULL, 0),
33 R(0x22, "LocalTee", WASM_IMM_LOCAL, 0, NULL, 0),
34 R(0x23, "GlobalGet", WASM_IMM_GLOBAL, 0, NULL, 0),
35 R(0x24, "GlobalSet", WASM_IMM_GLOBAL, 0, NULL, 0),
36 R(0x25, "TableGet", WASM_IMM_TABLE, REF, NULL, 0),
37 R(0x26, "TableSet", WASM_IMM_TABLE, REF, NULL, 0),
38 L(0x28, "I32Load", "i>i", 4),
39 L(0x29, "I64Load", "i>l", 8),
40 L(0x2a, "F32Load", "i>f", 4),
41 L(0x2b, "F64Load", "i>d", 8),
42 L(0x2c, "I32Load8S", "i>i", 1),
43 L(0x2d, "I32Load8U", "i>i", 1),
44 L(0x2e, "I32Load16S", "i>i", 2),
45 L(0x2f, "I32Load16U", "i>i", 2),
46 L(0x30, "I64Load8S", "i>l", 1),
47 L(0x31, "I64Load8U", "i>l", 1),
48 L(0x32, "I64Load16S", "i>l", 2),
49 L(0x33, "I64Load16U", "i>l", 2),
50 L(0x34, "I64Load32S", "i>l", 4),
51 L(0x35, "I64Load32U", "i>l", 4),
52 L(0x36, "I32Store", "ii>", 4),
53 L(0x37, "I64Store", "il>", 8),
54 L(0x38, "F32Store", "if>", 4),
55 L(0x39, "F64Store", "id>", 8),
56 L(0x3a, "I32Store8", "ii>", 1),
57 L(0x3b, "I32Store16", "ii>", 2),
58 L(0x3c, "I64Store8", "il>", 1),
59 L(0x3d, "I64Store16", "il>", 2),
60 L(0x3e, "I64Store32", "il>", 4),
61 R(0x3f, "MemorySize", WASM_IMM_MEMIDX, 0, ">i", 0),
62 R(0x40, "MemoryGrow", WASM_IMM_MEMIDX, 0, "i>i", 0),
63 R(0x41, "I32Const", WASM_IMM_I32, 0, ">i", 0),
64 R(0x42, "I64Const", WASM_IMM_I64, 0, ">l", 0),
65 R(0x43, "F32Const", WASM_IMM_F32, 0, ">f", 0),
66 R(0x44, "F64Const", WASM_IMM_F64, 0, ">d", 0),
67 N(0x45, "I32Eqz", "i>i"),
68 N(0x46, "I32Eq", "ii>i"),
69 N(0x47, "I32Ne", "ii>i"),
70 N(0x48, "I32LtS", "ii>i"),
71 N(0x49, "I32LtU", "ii>i"),
72 N(0x4a, "I32GtS", "ii>i"),
73 N(0x4b, "I32GtU", "ii>i"),
74 N(0x4c, "I32LeS", "ii>i"),
75 N(0x4d, "I32LeU", "ii>i"),
76 N(0x4e, "I32GeS", "ii>i"),
77 N(0x4f, "I32GeU", "ii>i"),
78 N(0x50, "I64Eqz", "l>i"),
79 N(0x51, "I64Eq", "ll>i"),
80 N(0x52, "I64Ne", "ll>i"),
81 N(0x53, "I64LtS", "ll>i"),
82 N(0x54, "I64LtU", "ll>i"),
83 N(0x55, "I64GtS", "ll>i"),
84 N(0x56, "I64GtU", "ll>i"),
85 N(0x57, "I64LeS", "ll>i"),
86 N(0x58, "I64LeU", "ll>i"),
87 N(0x59, "I64GeS", "ll>i"),
88 N(0x5a, "I64GeU", "ll>i"),
89 N(0x5b, "F32Eq", "ff>i"),
90 N(0x5c, "F32Ne", "ff>i"),
91 N(0x5d, "F32Lt", "ff>i"),
92 N(0x5e, "F32Gt", "ff>i"),
93 N(0x5f, "F32Le", "ff>i"),
94 N(0x60, "F32Ge", "ff>i"),
95 N(0x61, "F64Eq", "dd>i"),
96 N(0x62, "F64Ne", "dd>i"),
97 N(0x63, "F64Lt", "dd>i"),
98 N(0x64, "F64Gt", "dd>i"),
99 N(0x65, "F64Le", "dd>i"),
100 N(0x66, "F64Ge", "dd>i"),
101 N(0x67, "I32Clz", "i>i"),
102 N(0x68, "I32Ctz", "i>i"),
103 N(0x69, "I32Popcnt", "i>i"),
104 N(0x6a, "I32Add", "ii>i"),
105 N(0x6b, "I32Sub", "ii>i"),
106 N(0x6c, "I32Mul", "ii>i"),
107 N(0x6d, "I32DivS", "ii>i"),
108 N(0x6e, "I32DivU", "ii>i"),
109 N(0x6f, "I32RemS", "ii>i"),
110 N(0x70, "I32RemU", "ii>i"),
111 N(0x71, "I32And", "ii>i"),
112 N(0x72, "I32Or", "ii>i"),
113 N(0x73, "I32Xor", "ii>i"),
114 N(0x74, "I32Shl", "ii>i"),
115 N(0x75, "I32ShrS", "ii>i"),
116 N(0x76, "I32ShrU", "ii>i"),
117 N(0x77, "I32Rotl", "ii>i"),
118 N(0x78, "I32Rotr", "ii>i"),
119 N(0x79, "I64Clz", "l>l"),
120 N(0x7a, "I64Ctz", "l>l"),
121 N(0x7b, "I64Popcnt", "l>l"),
122 N(0x7c, "I64Add", "ll>l"),
123 N(0x7d, "I64Sub", "ll>l"),
124 N(0x7e, "I64Mul", "ll>l"),
125 N(0x7f, "I64DivS", "ll>l"),
126 N(0x80, "I64DivU", "ll>l"),
127 N(0x81, "I64RemS", "ll>l"),
128 N(0x82, "I64RemU", "ll>l"),
129 N(0x83, "I64And", "ll>l"),
130 N(0x84, "I64Or", "ll>l"),
131 N(0x85, "I64Xor", "ll>l"),
132 N(0x86, "I64Shl", "ll>l"),
133 N(0x87, "I64ShrS", "ll>l"),
134 N(0x88, "I64ShrU", "ll>l"),
135 N(0x89, "I64Rotl", "ll>l"),
136 N(0x8a, "I64Rotr", "ll>l"),
137 N(0x8b, "F32Abs", "f>f"),
138 N(0x8c, "F32Neg", "f>f"),
139 N(0x8d, "F32Ceil", "f>f"),
140 N(0x8e, "F32Floor", "f>f"),
141 N(0x8f, "F32Trunc", "f>f"),
142 N(0x90, "F32Nearest", "f>f"),
143 N(0x91, "F32Sqrt", "f>f"),
144 N(0x92, "F32Add", "ff>f"),
145 N(0x93, "F32Sub", "ff>f"),
146 N(0x94, "F32Mul", "ff>f"),
147 N(0x95, "F32Div", "ff>f"),
148 N(0x96, "F32Min", "ff>f"),
149 N(0x97, "F32Max", "ff>f"),
150 N(0x98, "F32Copysign", "ff>f"),
151 N(0x99, "F64Abs", "d>d"),
152 N(0x9a, "F64Neg", "d>d"),
153 N(0x9b, "F64Ceil", "d>d"),
154 N(0x9c, "F64Floor", "d>d"),
155 N(0x9d, "F64Trunc", "d>d"),
156 N(0x9e, "F64Nearest", "d>d"),
157 N(0x9f, "F64Sqrt", "d>d"),
158 N(0xa0, "F64Add", "dd>d"),
159 N(0xa1, "F64Sub", "dd>d"),
160 N(0xa2, "F64Mul", "dd>d"),
161 N(0xa3, "F64Div", "dd>d"),
162 N(0xa4, "F64Min", "dd>d"),
163 N(0xa5, "F64Max", "dd>d"),
164 N(0xa6, "F64Copysign", "dd>d"),
165 N(0xa7, "I32WrapI64", "l>i"),
166 N(0xa8, "I32TruncF32S", "f>i"),
167 N(0xa9, "I32TruncF32U", "f>i"),
168 N(0xaa, "I32TruncF64S", "d>i"),
169 N(0xab, "I32TruncF64U", "d>i"),
170 N(0xac, "I64ExtendI32S", "i>l"),
171 N(0xad, "I64ExtendI32U", "i>l"),
172 N(0xae, "I64TruncF32S", "f>l"),
173 N(0xaf, "I64TruncF32U", "f>l"),
174 N(0xb0, "I64TruncF64S", "d>l"),
175 N(0xb1, "I64TruncF64U", "d>l"),
176 N(0xb2, "F32ConvertI32S", "i>f"),
177 N(0xb3, "F32ConvertI32U", "i>f"),
178 N(0xb4, "F32ConvertI64S", "l>f"),
179 N(0xb5, "F32ConvertI64U", "l>f"),
180 N(0xb6, "F32DemoteF64", "d>f"),
181 N(0xb7, "F64ConvertI32S", "i>d"),
182 N(0xb8, "F64ConvertI32U", "i>d"),
183 N(0xb9, "F64ConvertI64S", "l>d"),
184 N(0xba, "F64ConvertI64U", "l>d"),
185 N(0xbb, "F64PromoteF32", "f>d"),
186 N(0xbc, "I32ReinterpretF32", "f>i"),
187 N(0xbd, "I64ReinterpretF64", "d>l"),
188 N(0xbe, "F32ReinterpretI32", "i>f"),
189 N(0xbf, "F64ReinterpretI64", "l>d"),
190 R(0xc0, "I32Extend8S", WASM_IMM_NONE, WASM_F_SIGN_EXT, "i>i", 0),
191 R(0xc1, "I32Extend16S", WASM_IMM_NONE, WASM_F_SIGN_EXT, "i>i", 0),
192 R(0xc2, "I64Extend8S", WASM_IMM_NONE, WASM_F_SIGN_EXT, "l>l", 0),
193 R(0xc3, "I64Extend16S", WASM_IMM_NONE, WASM_F_SIGN_EXT, "l>l", 0),
194 R(0xc4, "I64Extend32S", WASM_IMM_NONE, WASM_F_SIGN_EXT, "l>l", 0),
195 R(0xd0, "RefNull", WASM_IMM_REFTYPE, REF, NULL, 0),
196 R(0xd1, "RefIsNull", WASM_IMM_NONE, REF, NULL, 0),
197 R(0xd2, "RefFunc", WASM_IMM_FUNC, REF, NULL, 0),
198};
199
200static const wasm_opinfo fc_ops[18] = {
201 {WASM_OP_FC(0), "I32TruncSatF32S", WASM_IMM_NONE, SAT, "f>i", 0},
202 {WASM_OP_FC(1), "I32TruncSatF32U", WASM_IMM_NONE, SAT, "f>i", 0},
203 {WASM_OP_FC(2), "I32TruncSatF64S", WASM_IMM_NONE, SAT, "d>i", 0},
204 {WASM_OP_FC(3), "I32TruncSatF64U", WASM_IMM_NONE, SAT, "d>i", 0},
205 {WASM_OP_FC(4), "I64TruncSatF32S", WASM_IMM_NONE, SAT, "f>l", 0},
206 {WASM_OP_FC(5), "I64TruncSatF32U", WASM_IMM_NONE, SAT, "f>l", 0},
207 {WASM_OP_FC(6), "I64TruncSatF64S", WASM_IMM_NONE, SAT, "d>l", 0},
208 {WASM_OP_FC(7), "I64TruncSatF64U", WASM_IMM_NONE, SAT, "d>l", 0},
209 {WASM_OP_FC(8), "MemoryInit", WASM_IMM_MEMORY_INIT, BULK, NULL, 0},
210 {WASM_OP_FC(9), "DataDrop", WASM_IMM_DATA, BULK, NULL, 0},
211 {WASM_OP_FC(10), "MemoryCopy", WASM_IMM_MEMORY_COPY, BULK, NULL, 0},
212 {WASM_OP_FC(11), "MemoryFill", WASM_IMM_MEMIDX, BULK, NULL, 0},
213 {WASM_OP_FC(12), "TableInit", WASM_IMM_TABLE_INIT, BULK, NULL, 0},
214 {WASM_OP_FC(13), "ElemDrop", WASM_IMM_ELEM, BULK, NULL, 0},
215 {WASM_OP_FC(14), "TableCopy", WASM_IMM_TABLE_COPY, BULK, NULL, 0},
216 {WASM_OP_FC(15), "TableGrow", WASM_IMM_TABLE, REF, NULL, 0},
217 {WASM_OP_FC(16), "TableSize", WASM_IMM_TABLE, REF, NULL, 0},
218 {WASM_OP_FC(17), "TableFill", WASM_IMM_TABLE, REF, NULL, 0},
219};
220
221/* SIMD opcodes 0x00-0xff that the final SIMD proposal leaves unassigned. */
222static bool simd_unassigned(uint32_t sub) {
223 static const uint8_t gaps[] = {0x9a, 0xa2, 0xa5, 0xa6, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xbb,
224 0xc2, 0xc5, 0xc6, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, 0xe2, 0xee};
225 for (size_t i = 0; i < sizeof gaps; i++)
226 if (gaps[i] == sub) return true;
227 return false;
228}
229
230static bool simd(uint32_t sub, wasm_opinfo *out) {
231 wasm_opinfo o = {WASM_OP_SIMD(sub), "Simd", WASM_IMM_NONE, WASM_F_SIMD, NULL, 0};
232 if (sub >= 0x100 && sub <= 0x113) {
233 o.name = "RelaxedSimd";
234 o.feature = WASM_F_RELAXED_SIMD;
235 } else if (sub > 0xff || simd_unassigned(sub)) {
236 return false;
237 } else if (sub <= 0x0b || sub == 0x5c || sub == 0x5d) {
238 o.imm = WASM_IMM_MEMARG;
239 } else if (sub == 0x0c) {
240 o.imm = WASM_IMM_V128;
241 } else if (sub == 0x0d) {
242 o.imm = WASM_IMM_SHUFFLE;
243 } else if (sub >= 0x15 && sub <= 0x22) {
244 o.imm = WASM_IMM_LANE;
245 } else if (sub >= 0x54 && sub <= 0x5b) {
246 o.imm = WASM_IMM_MEMARG_LANE;
247 }
248 *out = o;
249 return true;
250}
251
252static bool atomic(uint32_t sub, wasm_opinfo *out) {
253 wasm_opinfo o = {WASM_OP_ATOMIC(sub), "Atomic", WASM_IMM_MEMARG, WASM_F_THREADS, NULL, 0};
254 if (sub == 0x03) o.imm = WASM_IMM_ZERO_BYTE;
255 else if (sub > 0x02 && (sub < 0x10 || sub > 0x4e)) return false;
256 *out = o;
257 return true;
258}
259
260bool wasm_op_info(uint32_t op, wasm_opinfo *out) {
261 uint32_t prefix = op >> 16, sub = op & 0xffff;
262 if (prefix == 0) {
263 if (op > 0xff || !main_ops[op].name) return false;
264 *out = main_ops[op];
265 return true;
266 }
267 if (prefix == WASM_PREFIX_FC) {
268 if (sub >= sizeof fc_ops / sizeof fc_ops[0]) return false;
269 *out = fc_ops[sub];
270 return true;
271 }
272 if (prefix == WASM_PREFIX_SIMD) return simd(sub, out);
273 if (prefix == WASM_PREFIX_ATOMIC) return atomic(sub, out);
274 return false;
275}