Skip to main content

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}