synth_core/wasm_op.rs
1//! WebAssembly operation patterns — universal input IR for all backends
2//!
3//! Every backend (ARM, aWsm, wasker, w2c2) consumes `WasmOp` sequences.
4//! This enum lives in synth-core so backends can depend on it without
5//! pulling in ARM-specific synthesis types.
6
7use serde::{Deserialize, Serialize};
8
9/// WebAssembly operation patterns
10/// Note: Cannot derive Eq because f32/f64 don't implement Eq (NaN != NaN)
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub enum WasmOp {
13 // Arithmetic
14 I32Add,
15 I32Sub,
16 I32Mul,
17 I32DivS,
18 I32DivU,
19 I32RemS,
20 I32RemU,
21
22 // Bitwise
23 I32And,
24 I32Or,
25 I32Xor,
26 I32Shl,
27 I32ShrS,
28 I32ShrU,
29 I32Rotl, // Rotate left
30 I32Rotr, // Rotate right
31 I32Clz, // Count leading zeros
32 I32Ctz, // Count trailing zeros
33 I32Popcnt, // Population count (count 1 bits)
34
35 // Sign extension
36 I32Extend8S, // Sign-extend low 8 bits to 32 bits
37 I32Extend16S, // Sign-extend low 16 bits to 32 bits
38
39 // Comparison
40 I32Eqz, // Equal to zero (unary)
41 I32Eq,
42 I32Ne,
43 I32LtS,
44 I32LtU,
45 I32LeS,
46 I32LeU,
47 I32GtS,
48 I32GtU,
49 I32GeS,
50 I32GeU,
51
52 // Constants
53 I32Const(i32),
54
55 // Memory
56 I32Load { offset: u32, align: u32 },
57 I32Store { offset: u32, align: u32 },
58
59 // Sub-word loads (i32)
60 I32Load8S { offset: u32, align: u32 }, // byte load, sign-extend to i32
61 I32Load8U { offset: u32, align: u32 }, // byte load, zero-extend to i32
62 I32Load16S { offset: u32, align: u32 }, // halfword load, sign-extend to i32
63 I32Load16U { offset: u32, align: u32 }, // halfword load, zero-extend to i32
64
65 // Sub-word stores (i32)
66 I32Store8 { offset: u32, align: u32 }, // store low byte
67 I32Store16 { offset: u32, align: u32 }, // store low halfword
68
69 // Control flow
70 Block,
71 Loop,
72 Br(u32), // Branch to label
73 BrIf(u32), // Conditional branch
74 BrTable { targets: Vec<u32>, default: u32 },
75 Return,
76 Call(u32),
77 CallIndirect { type_index: u32, table_index: u32 },
78 LocalGet(u32),
79 LocalSet(u32),
80 LocalTee(u32),
81 GlobalGet(u32),
82 GlobalSet(u32),
83
84 // Memory management
85 MemorySize(u32), // returns current memory size in pages (memory index)
86 MemoryGrow(u32), // grow memory by N pages, returns previous size or -1 (memory index)
87
88 // Bulk memory (#374) — single linear memory (memory 0) only; the decoder
89 // loud-skips any non-zero memory index. Each pops (dst, src/val, len) = 3
90 // i32 operands and pushes nothing.
91 MemoryCopy, // memory.copy: copy `len` bytes from `src` to `dst` (memmove semantics)
92 MemoryFill, // memory.fill: set `len` bytes at `dst` to the low byte of `val`
93
94 // More ops
95 Drop,
96 Select,
97 If,
98 Else,
99 End,
100 Unreachable,
101 Nop,
102
103 // ========================================================================
104 // i64 Operations
105 // ========================================================================
106
107 // i64 Arithmetic
108 I64Add,
109 I64Sub,
110 I64Mul,
111 I64DivS,
112 I64DivU,
113 I64RemS,
114 I64RemU,
115
116 // i64 Bitwise
117 I64And,
118 I64Or,
119 I64Xor,
120 I64Shl,
121 I64ShrS,
122 I64ShrU,
123 I64Rotl,
124 I64Rotr,
125 I64Clz,
126 I64Ctz,
127 I64Popcnt,
128
129 // i64 Comparison
130 I64Eqz,
131 I64Eq,
132 I64Ne,
133 I64LtS,
134 I64LtU,
135 I64LeS,
136 I64LeU,
137 I64GtS,
138 I64GtU,
139 I64GeS,
140 I64GeU,
141
142 // i64 Constants and Memory
143 I64Const(i64),
144 I64Load { offset: u32, align: u32 },
145 I64Store { offset: u32, align: u32 },
146
147 // Sub-word loads (i64) — load sub-word, extend to i64
148 I64Load8S { offset: u32, align: u32 },
149 I64Load8U { offset: u32, align: u32 },
150 I64Load16S { offset: u32, align: u32 },
151 I64Load16U { offset: u32, align: u32 },
152 I64Load32S { offset: u32, align: u32 },
153 I64Load32U { offset: u32, align: u32 },
154
155 // Sub-word stores (i64) — store low N bits
156 I64Store8 { offset: u32, align: u32 },
157 I64Store16 { offset: u32, align: u32 },
158 I64Store32 { offset: u32, align: u32 },
159
160 // Conversion operations
161 I64ExtendI32S, // Sign-extend i32 to i64
162 I64ExtendI32U, // Zero-extend i32 to i64
163 I32WrapI64, // Wrap i64 to i32 (truncate)
164
165 // i64 In-place sign extension
166 I64Extend8S, // Sign-extend low 8 bits to 64 bits
167 I64Extend16S, // Sign-extend low 16 bits to 64 bits
168 I64Extend32S, // Sign-extend low 32 bits to 64 bits
169
170 // ========================================================================
171 // f32 Operations
172 // ========================================================================
173
174 // f32 Arithmetic
175 F32Add,
176 F32Sub,
177 F32Mul,
178 F32Div,
179
180 // f32 Comparisons
181 F32Eq,
182 F32Ne,
183 F32Lt,
184 F32Le,
185 F32Gt,
186 F32Ge,
187
188 // f32 Math Functions
189 F32Abs,
190 F32Neg,
191 F32Ceil,
192 F32Floor,
193 F32Trunc,
194 F32Nearest,
195 F32Sqrt,
196 F32Min,
197 F32Max,
198 F32Copysign,
199
200 // f32 Constants and Memory
201 F32Const(f32),
202 F32Load { offset: u32, align: u32 },
203 F32Store { offset: u32, align: u32 },
204
205 // f32 Conversions
206 F32ConvertI32S, // Convert signed i32 to f32
207 F32ConvertI32U, // Convert unsigned i32 to f32
208 F32ConvertI64S, // Convert signed i64 to f32
209 F32ConvertI64U, // Convert unsigned i64 to f32
210 F32DemoteF64, // Convert f64 to f32
211 F32ReinterpretI32, // Reinterpret i32 bits as f32
212 I32ReinterpretF32, // Reinterpret f32 bits as i32
213 I32TruncF32S, // Truncate f32 to signed i32
214 I32TruncF32U, // Truncate f32 to unsigned i32
215
216 // ========================================================================
217 // f64 Operations
218 // ========================================================================
219
220 // f64 Arithmetic
221 F64Add,
222 F64Sub,
223 F64Mul,
224 F64Div,
225
226 // f64 Comparisons
227 F64Eq,
228 F64Ne,
229 F64Lt,
230 F64Le,
231 F64Gt,
232 F64Ge,
233
234 // f64 Math Functions
235 F64Abs,
236 F64Neg,
237 F64Ceil,
238 F64Floor,
239 F64Trunc,
240 F64Nearest,
241 F64Sqrt,
242 F64Min,
243 F64Max,
244 F64Copysign,
245
246 // f64 Constants and Memory
247 F64Const(f64),
248 F64Load { offset: u32, align: u32 },
249 F64Store { offset: u32, align: u32 },
250
251 // f64 Conversions
252 F64ConvertI32S, // Convert signed i32 to f64
253 F64ConvertI32U, // Convert unsigned i32 to f64
254 F64ConvertI64S, // Convert signed i64 to f64
255 F64ConvertI64U, // Convert unsigned i64 to f64
256 F64PromoteF32, // Convert f32 to f64
257 F64ReinterpretI64, // Reinterpret i64 bits as f64
258 I64ReinterpretF64, // Reinterpret f64 bits as i64
259 I64TruncF64S, // Truncate f64 to signed i64
260 I64TruncF64U, // Truncate f64 to unsigned i64
261 I32TruncF64S, // Truncate f64 to signed i32
262 I32TruncF64U, // Truncate f64 to unsigned i32
263
264 // ========================================================================
265 // v128 SIMD Operations (WASM SIMD proposal)
266 // ========================================================================
267 // Targets ARM Cortex-M55 Helium MVE (M-Profile Vector Extension)
268
269 // v128 Constants and Memory
270 V128Const([u8; 16]), // 128-bit constant
271 V128Load { offset: u32, align: u32 }, // v128.load
272 V128Store { offset: u32, align: u32 }, // v128.store
273
274 // v128 Bitwise operations
275 V128And, // v128.and
276 V128Or, // v128.or
277 V128Xor, // v128.xor
278 V128Not, // v128.not
279 V128AndNot, // v128.andnot
280
281 // i8x16 integer SIMD
282 I8x16Add, // i8x16.add
283 I8x16Sub, // i8x16.sub
284 I8x16Neg, // i8x16.neg
285 I8x16Eq, // i8x16.eq
286 I8x16Ne, // i8x16.ne
287 I8x16LtS, // i8x16.lt_s
288 I8x16LtU, // i8x16.lt_u
289 I8x16GtS, // i8x16.gt_s
290 I8x16GtU, // i8x16.gt_u
291 I8x16LeS, // i8x16.le_s
292 I8x16LeU, // i8x16.le_u
293 I8x16GeS, // i8x16.ge_s
294 I8x16GeU, // i8x16.ge_u
295 I8x16Splat, // i8x16.splat
296 I8x16ExtractLaneS(u8), // i8x16.extract_lane_s
297 I8x16ExtractLaneU(u8), // i8x16.extract_lane_u
298 I8x16ReplaceLane(u8), // i8x16.replace_lane
299 I8x16Shuffle([u8; 16]), // i8x16.shuffle
300 I8x16Swizzle, // i8x16.swizzle
301
302 // i16x8 integer SIMD
303 I16x8Add, // i16x8.add
304 I16x8Sub, // i16x8.sub
305 I16x8Mul, // i16x8.mul
306 I16x8Neg, // i16x8.neg
307 I16x8Eq, // i16x8.eq
308 I16x8Ne, // i16x8.ne
309 I16x8LtS, // i16x8.lt_s
310 I16x8LtU, // i16x8.lt_u
311 I16x8GtS, // i16x8.gt_s
312 I16x8GtU, // i16x8.gt_u
313 I16x8LeS, // i16x8.le_s
314 I16x8LeU, // i16x8.le_u
315 I16x8GeS, // i16x8.ge_s
316 I16x8GeU, // i16x8.ge_u
317 I16x8Splat, // i16x8.splat
318 I16x8ExtractLaneS(u8), // i16x8.extract_lane_s
319 I16x8ExtractLaneU(u8), // i16x8.extract_lane_u
320 I16x8ReplaceLane(u8), // i16x8.replace_lane
321
322 // i32x4 integer SIMD
323 I32x4Add, // i32x4.add
324 I32x4Sub, // i32x4.sub
325 I32x4Mul, // i32x4.mul
326 I32x4Neg, // i32x4.neg
327 I32x4Eq, // i32x4.eq
328 I32x4Ne, // i32x4.ne
329 I32x4LtS, // i32x4.lt_s
330 I32x4LtU, // i32x4.lt_u
331 I32x4GtS, // i32x4.gt_s
332 I32x4GtU, // i32x4.gt_u
333 I32x4LeS, // i32x4.le_s
334 I32x4LeU, // i32x4.le_u
335 I32x4GeS, // i32x4.ge_s
336 I32x4GeU, // i32x4.ge_u
337 I32x4Splat, // i32x4.splat
338 I32x4ExtractLane(u8), // i32x4.extract_lane
339 I32x4ReplaceLane(u8), // i32x4.replace_lane
340
341 // i64x2 integer SIMD
342 I64x2Add, // i64x2.add
343 I64x2Sub, // i64x2.sub
344 I64x2Mul, // i64x2.mul
345 I64x2Neg, // i64x2.neg
346 I64x2Eq, // i64x2.eq
347 I64x2Ne, // i64x2.ne
348 I64x2LtS, // i64x2.lt_s
349 I64x2GtS, // i64x2.gt_s
350 I64x2LeS, // i64x2.le_s
351 I64x2GeS, // i64x2.ge_s
352 I64x2Splat, // i64x2.splat
353 I64x2ExtractLane(u8), // i64x2.extract_lane
354 I64x2ReplaceLane(u8), // i64x2.replace_lane
355
356 // f32x4 floating-point SIMD
357 F32x4Add, // f32x4.add
358 F32x4Sub, // f32x4.sub
359 F32x4Mul, // f32x4.mul
360 F32x4Div, // f32x4.div
361 F32x4Abs, // f32x4.abs
362 F32x4Neg, // f32x4.neg
363 F32x4Sqrt, // f32x4.sqrt
364 F32x4Eq, // f32x4.eq
365 F32x4Ne, // f32x4.ne
366 F32x4Lt, // f32x4.lt
367 F32x4Le, // f32x4.le
368 F32x4Gt, // f32x4.gt
369 F32x4Ge, // f32x4.ge
370 F32x4Splat, // f32x4.splat
371 F32x4ExtractLane(u8), // f32x4.extract_lane
372 F32x4ReplaceLane(u8), // f32x4.replace_lane
373}