1use crate::abi::RetArea;
8use crate::codegen::{
9 Callee, CodeGen, CodeGenError, ConditionalBranch, ControlStackFrame, Emission, FnCall,
10 UnconditionalBranch, control_index,
11};
12use crate::masm::{
13 AtomicWaitKind, DivKind, Extend, ExtractLaneKind, FloatCmpKind, IntCmpKind, LoadKind,
14 MacroAssembler, MulWideKind, OperandSize, RegImm, RemKind, ReplaceLaneKind, RmwOp,
15 RoundingMode, SPOffset, ShiftKind, Signed, SplatKind, SplatLoadKind, StoreKind, TruncKind,
16 V128AbsKind, V128AddKind, V128ConvertKind, V128ExtAddKind, V128ExtMulKind, V128ExtendKind,
17 V128LoadExtendKind, V128MaxKind, V128MinKind, V128MulKind, V128NarrowKind, V128NegKind,
18 V128SubKind, V128TruncKind, VectorCompareKind, VectorEqualityKind, Zero,
19};
20use crate::reg::{Reg, writable};
21use crate::stack::{TypedReg, Val};
22use crate::{Result, bail, format_err};
23use regalloc2::RegClass;
24use smallvec::{SmallVec, smallvec};
25use wasmparser::{
26 BlockType, BrTable, HeapType, Ieee32, Ieee64, MemArg, V128, ValType, VisitOperator,
27 VisitSimdOperator,
28};
29use wasmtime_cranelift::TRAP_INDIRECT_CALL_TO_NULL;
30use wasmtime_environ::{
31 DataIndex, ElemIndex, FuncIndex, GlobalIndex, MemoryIndex, TableIndex, TypeIndex, WasmHeapType,
32 WasmValType,
33};
34
35macro_rules! def_unsupported {
42 ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident $ann:tt)*) => {
43 $(
44 def_unsupported!(
45 emit
46 $op
47
48 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
49 $($(let _ = $arg;)*)?
50
51 Err(format_err!(CodeGenError::unimplemented_wasm_instruction()))
52 }
53 );
54 )*
55 };
56
57 (emit I32Const $($rest:tt)*) => {};
58 (emit I64Const $($rest:tt)*) => {};
59 (emit F32Const $($rest:tt)*) => {};
60 (emit F64Const $($rest:tt)*) => {};
61 (emit V128Const $($rest:tt)*) => {};
62 (emit F32Add $($rest:tt)*) => {};
63 (emit F64Add $($rest:tt)*) => {};
64 (emit F32Sub $($rest:tt)*) => {};
65 (emit F64Sub $($rest:tt)*) => {};
66 (emit F32Mul $($rest:tt)*) => {};
67 (emit F64Mul $($rest:tt)*) => {};
68 (emit F32Div $($rest:tt)*) => {};
69 (emit F64Div $($rest:tt)*) => {};
70 (emit F32Min $($rest:tt)*) => {};
71 (emit F64Min $($rest:tt)*) => {};
72 (emit F32Max $($rest:tt)*) => {};
73 (emit F64Max $($rest:tt)*) => {};
74 (emit F32Copysign $($rest:tt)*) => {};
75 (emit F64Copysign $($rest:tt)*) => {};
76 (emit F32Abs $($rest:tt)*) => {};
77 (emit F64Abs $($rest:tt)*) => {};
78 (emit F32Neg $($rest:tt)*) => {};
79 (emit F64Neg $($rest:tt)*) => {};
80 (emit F32Floor $($rest:tt)*) => {};
81 (emit F64Floor $($rest:tt)*) => {};
82 (emit F32Ceil $($rest:tt)*) => {};
83 (emit F64Ceil $($rest:tt)*) => {};
84 (emit F32Nearest $($rest:tt)*) => {};
85 (emit F64Nearest $($rest:tt)*) => {};
86 (emit F32Trunc $($rest:tt)*) => {};
87 (emit F64Trunc $($rest:tt)*) => {};
88 (emit F32Sqrt $($rest:tt)*) => {};
89 (emit F64Sqrt $($rest:tt)*) => {};
90 (emit F32Eq $($rest:tt)*) => {};
91 (emit F64Eq $($rest:tt)*) => {};
92 (emit F32Ne $($rest:tt)*) => {};
93 (emit F64Ne $($rest:tt)*) => {};
94 (emit F32Lt $($rest:tt)*) => {};
95 (emit F64Lt $($rest:tt)*) => {};
96 (emit F32Gt $($rest:tt)*) => {};
97 (emit F64Gt $($rest:tt)*) => {};
98 (emit F32Le $($rest:tt)*) => {};
99 (emit F64Le $($rest:tt)*) => {};
100 (emit F32Ge $($rest:tt)*) => {};
101 (emit F64Ge $($rest:tt)*) => {};
102 (emit F32ConvertI32S $($rest:tt)*) => {};
103 (emit F32ConvertI32U $($rest:tt)*) => {};
104 (emit F32ConvertI64S $($rest:tt)*) => {};
105 (emit F32ConvertI64U $($rest:tt)*) => {};
106 (emit F64ConvertI32S $($rest:tt)*) => {};
107 (emit F64ConvertI32U $($rest:tt)*) => {};
108 (emit F64ConvertI64S $($rest:tt)*) => {};
109 (emit F64ConvertI64U $($rest:tt)*) => {};
110 (emit F32ReinterpretI32 $($rest:tt)*) => {};
111 (emit F64ReinterpretI64 $($rest:tt)*) => {};
112 (emit F32DemoteF64 $($rest:tt)*) => {};
113 (emit F64PromoteF32 $($rest:tt)*) => {};
114 (emit I32Add $($rest:tt)*) => {};
115 (emit I64Add $($rest:tt)*) => {};
116 (emit I32Sub $($rest:tt)*) => {};
117 (emit I32Mul $($rest:tt)*) => {};
118 (emit I32DivS $($rest:tt)*) => {};
119 (emit I32DivU $($rest:tt)*) => {};
120 (emit I64DivS $($rest:tt)*) => {};
121 (emit I64DivU $($rest:tt)*) => {};
122 (emit I64RemU $($rest:tt)*) => {};
123 (emit I64RemS $($rest:tt)*) => {};
124 (emit I32RemU $($rest:tt)*) => {};
125 (emit I32RemS $($rest:tt)*) => {};
126 (emit I64Mul $($rest:tt)*) => {};
127 (emit I64Sub $($rest:tt)*) => {};
128 (emit I32Eq $($rest:tt)*) => {};
129 (emit I64Eq $($rest:tt)*) => {};
130 (emit I32Ne $($rest:tt)*) => {};
131 (emit I64Ne $($rest:tt)*) => {};
132 (emit I32LtS $($rest:tt)*) => {};
133 (emit I64LtS $($rest:tt)*) => {};
134 (emit I32LtU $($rest:tt)*) => {};
135 (emit I64LtU $($rest:tt)*) => {};
136 (emit I32LeS $($rest:tt)*) => {};
137 (emit I64LeS $($rest:tt)*) => {};
138 (emit I32LeU $($rest:tt)*) => {};
139 (emit I64LeU $($rest:tt)*) => {};
140 (emit I32GtS $($rest:tt)*) => {};
141 (emit I64GtS $($rest:tt)*) => {};
142 (emit I32GtU $($rest:tt)*) => {};
143 (emit I64GtU $($rest:tt)*) => {};
144 (emit I32GeS $($rest:tt)*) => {};
145 (emit I64GeS $($rest:tt)*) => {};
146 (emit I32GeU $($rest:tt)*) => {};
147 (emit I64GeU $($rest:tt)*) => {};
148 (emit I32Eqz $($rest:tt)*) => {};
149 (emit I64Eqz $($rest:tt)*) => {};
150 (emit I32And $($rest:tt)*) => {};
151 (emit I64And $($rest:tt)*) => {};
152 (emit I32Or $($rest:tt)*) => {};
153 (emit I64Or $($rest:tt)*) => {};
154 (emit I32Xor $($rest:tt)*) => {};
155 (emit I64Xor $($rest:tt)*) => {};
156 (emit I32Shl $($rest:tt)*) => {};
157 (emit I64Shl $($rest:tt)*) => {};
158 (emit I32ShrS $($rest:tt)*) => {};
159 (emit I64ShrS $($rest:tt)*) => {};
160 (emit I32ShrU $($rest:tt)*) => {};
161 (emit I64ShrU $($rest:tt)*) => {};
162 (emit I32Rotl $($rest:tt)*) => {};
163 (emit I64Rotl $($rest:tt)*) => {};
164 (emit I32Rotr $($rest:tt)*) => {};
165 (emit I64Rotr $($rest:tt)*) => {};
166 (emit I32Clz $($rest:tt)*) => {};
167 (emit I64Clz $($rest:tt)*) => {};
168 (emit I32Ctz $($rest:tt)*) => {};
169 (emit I64Ctz $($rest:tt)*) => {};
170 (emit I32Popcnt $($rest:tt)*) => {};
171 (emit I64Popcnt $($rest:tt)*) => {};
172 (emit I32WrapI64 $($rest:tt)*) => {};
173 (emit I64ExtendI32S $($rest:tt)*) => {};
174 (emit I64ExtendI32U $($rest:tt)*) => {};
175 (emit I32Extend8S $($rest:tt)*) => {};
176 (emit I32Extend16S $($rest:tt)*) => {};
177 (emit I64Extend8S $($rest:tt)*) => {};
178 (emit I64Extend16S $($rest:tt)*) => {};
179 (emit I64Extend32S $($rest:tt)*) => {};
180 (emit I32TruncF32S $($rest:tt)*) => {};
181 (emit I32TruncF32U $($rest:tt)*) => {};
182 (emit I32TruncF64S $($rest:tt)*) => {};
183 (emit I32TruncF64U $($rest:tt)*) => {};
184 (emit I64TruncF32S $($rest:tt)*) => {};
185 (emit I64TruncF32U $($rest:tt)*) => {};
186 (emit I64TruncF64S $($rest:tt)*) => {};
187 (emit I64TruncF64U $($rest:tt)*) => {};
188 (emit I32ReinterpretF32 $($rest:tt)*) => {};
189 (emit I64ReinterpretF64 $($rest:tt)*) => {};
190 (emit LocalGet $($rest:tt)*) => {};
191 (emit LocalSet $($rest:tt)*) => {};
192 (emit Call $($rest:tt)*) => {};
193 (emit End $($rest:tt)*) => {};
194 (emit Nop $($rest:tt)*) => {};
195 (emit If $($rest:tt)*) => {};
196 (emit Else $($rest:tt)*) => {};
197 (emit Block $($rest:tt)*) => {};
198 (emit Loop $($rest:tt)*) => {};
199 (emit Br $($rest:tt)*) => {};
200 (emit BrIf $($rest:tt)*) => {};
201 (emit Return $($rest:tt)*) => {};
202 (emit Unreachable $($rest:tt)*) => {};
203 (emit LocalTee $($rest:tt)*) => {};
204 (emit GlobalGet $($rest:tt)*) => {};
205 (emit GlobalSet $($rest:tt)*) => {};
206 (emit Select $($rest:tt)*) => {};
207 (emit TypedSelect $($rest:tt)*) => {};
208 (emit RefNull $($rest:tt)*) => {};
209 (emit RefIsNull $($rest:tt)*) => {};
210 (emit RefFunc $($rest:tt)*) => {};
211 (emit Drop $($rest:tt)*) => {};
212 (emit BrTable $($rest:tt)*) => {};
213 (emit CallIndirect $($rest:tt)*) => {};
214 (emit TableInit $($rest:tt)*) => {};
215 (emit TableCopy $($rest:tt)*) => {};
216 (emit TableGet $($rest:tt)*) => {};
217 (emit TableSet $($rest:tt)*) => {};
218 (emit TableGrow $($rest:tt)*) => {};
219 (emit TableSize $($rest:tt)*) => {};
220 (emit TableFill $($rest:tt)*) => {};
221 (emit ElemDrop $($rest:tt)*) => {};
222 (emit MemoryInit $($rest:tt)*) => {};
223 (emit MemoryCopy $($rest:tt)*) => {};
224 (emit DataDrop $($rest:tt)*) => {};
225 (emit MemoryFill $($rest:tt)*) => {};
226 (emit MemorySize $($rest:tt)*) => {};
227 (emit MemoryGrow $($rest:tt)*) => {};
228 (emit I32Load $($rest:tt)*) => {};
229 (emit I32Load8S $($rest:tt)*) => {};
230 (emit I32Load8U $($rest:tt)*) => {};
231 (emit I32Load16S $($rest:tt)*) => {};
232 (emit I32Load16U $($rest:tt)*) => {};
233 (emit I64Load8S $($rest:tt)*) => {};
234 (emit I64Load8U $($rest:tt)*) => {};
235 (emit I64Load16S $($rest:tt)*) => {};
236 (emit I64Load16U $($rest:tt)*) => {};
237 (emit I64Load32S $($rest:tt)*) => {};
238 (emit I64Load32U $($rest:tt)*) => {};
239 (emit I64Load $($rest:tt)*) => {};
240 (emit I32Store $($rest:tt)*) => {};
241 (emit I32Store8 $($rest:tt)*) => {};
242 (emit I32Store16 $($rest:tt)*) => {};
243 (emit I64Store $($rest:tt)*) => {};
244 (emit I64Store8 $($rest:tt)*) => {};
245 (emit I64Store16 $($rest:tt)*) => {};
246 (emit I64Store32 $($rest:tt)*) => {};
247 (emit F32Load $($rest:tt)*) => {};
248 (emit F32Store $($rest:tt)*) => {};
249 (emit F64Load $($rest:tt)*) => {};
250 (emit F64Store $($rest:tt)*) => {};
251 (emit I32TruncSatF32S $($rest:tt)*) => {};
252 (emit I32TruncSatF32U $($rest:tt)*) => {};
253 (emit I32TruncSatF64S $($rest:tt)*) => {};
254 (emit I32TruncSatF64U $($rest:tt)*) => {};
255 (emit I64TruncSatF32S $($rest:tt)*) => {};
256 (emit I64TruncSatF32U $($rest:tt)*) => {};
257 (emit I64TruncSatF64S $($rest:tt)*) => {};
258 (emit I64TruncSatF64U $($rest:tt)*) => {};
259 (emit V128Load $($rest:tt)*) => {};
260 (emit V128Store $($rest:tt)*) => {};
261 (emit I64Add128 $($rest:tt)*) => {};
262 (emit I64Sub128 $($rest:tt)*) => {};
263 (emit I64MulWideS $($rest:tt)*) => {};
264 (emit I64MulWideU $($rest:tt)*) => {};
265 (emit I32AtomicLoad8U $($rest:tt)*) => {};
266 (emit I32AtomicLoad16U $($rest:tt)*) => {};
267 (emit I32AtomicLoad $($rest:tt)*) => {};
268 (emit I64AtomicLoad8U $($rest:tt)*) => {};
269 (emit I64AtomicLoad16U $($rest:tt)*) => {};
270 (emit I64AtomicLoad32U $($rest:tt)*) => {};
271 (emit I64AtomicLoad $($rest:tt)*) => {};
272 (emit V128Load8x8S $($rest:tt)*) => {};
273 (emit V128Load8x8U $($rest:tt)*) => {};
274 (emit V128Load16x4S $($rest:tt)*) => {};
275 (emit V128Load16x4U $($rest:tt)*) => {};
276 (emit V128Load32x2S $($rest:tt)*) => {};
277 (emit V128Load32x2U $($rest:tt)*) => {};
278 (emit V128Load8Splat $($rest:tt)*) => {};
279 (emit V128Load16Splat $($rest:tt)*) => {};
280 (emit V128Load32Splat $($rest:tt)*) => {};
281 (emit V128Load64Splat $($rest:tt)*) => {};
282 (emit I8x16Splat $($rest:tt)*) => {};
283 (emit I16x8Splat $($rest:tt)*) => {};
284 (emit I32x4Splat $($rest:tt)*) => {};
285 (emit I64x2Splat $($rest:tt)*) => {};
286 (emit F32x4Splat $($rest:tt)*) => {};
287 (emit F64x2Splat $($rest:tt)*) => {};
288 (emit I32AtomicStore8 $($rest:tt)*) => {};
289 (emit I32AtomicStore16 $($rest:tt)*) => {};
290 (emit I32AtomicStore $($rest:tt)*) => {};
291 (emit I64AtomicStore8 $($rest:tt)*) => {};
292 (emit I64AtomicStore16 $($rest:tt)*) => {};
293 (emit I64AtomicStore32 $($rest:tt)*) => {};
294 (emit I64AtomicStore $($rest:tt)*) => {};
295 (emit I32AtomicRmw8AddU $($rest:tt)*) => {};
296 (emit I32AtomicRmw16AddU $($rest:tt)*) => {};
297 (emit I32AtomicRmwAdd $($rest:tt)*) => {};
298 (emit I64AtomicRmw8AddU $($rest:tt)*) => {};
299 (emit I64AtomicRmw16AddU $($rest:tt)*) => {};
300 (emit I64AtomicRmw32AddU $($rest:tt)*) => {};
301 (emit I64AtomicRmwAdd $($rest:tt)*) => {};
302 (emit I8x16Shuffle $($rest:tt)*) => {};
303 (emit I8x16Swizzle $($rest:tt)*) => {};
304 (emit I32AtomicRmw8SubU $($rest:tt)*) => {};
305 (emit I32AtomicRmw16SubU $($rest:tt)*) => {};
306 (emit I32AtomicRmwSub $($rest:tt)*) => {};
307 (emit I64AtomicRmw8SubU $($rest:tt)*) => {};
308 (emit I64AtomicRmw16SubU $($rest:tt)*) => {};
309 (emit I64AtomicRmw32SubU $($rest:tt)*) => {};
310 (emit I64AtomicRmwSub $($rest:tt)*) => {};
311 (emit I32AtomicRmw8XchgU $($rest:tt)*) => {};
312 (emit I32AtomicRmw16XchgU $($rest:tt)*) => {};
313 (emit I32AtomicRmwXchg $($rest:tt)*) => {};
314 (emit I64AtomicRmw8XchgU $($rest:tt)*) => {};
315 (emit I64AtomicRmw16XchgU $($rest:tt)*) => {};
316 (emit I64AtomicRmw32XchgU $($rest:tt)*) => {};
317 (emit I64AtomicRmwXchg $($rest:tt)*) => {};
318 (emit I8x16ExtractLaneS $($rest:tt)*) => {};
319 (emit I8x16ExtractLaneU $($rest:tt)*) => {};
320 (emit I16x8ExtractLaneS $($rest:tt)*) => {};
321 (emit I16x8ExtractLaneU $($rest:tt)*) => {};
322 (emit I32x4ExtractLane $($rest:tt)*) => {};
323 (emit I64x2ExtractLane $($rest:tt)*) => {};
324 (emit F32x4ExtractLane $($rest:tt)*) => {};
325 (emit F64x2ExtractLane $($rest:tt)*) => {};
326 (emit I32AtomicRmw8AndU $($rest:tt)*) => {};
327 (emit I32AtomicRmw16AndU $($rest:tt)*) => {};
328 (emit I32AtomicRmwAnd $($rest:tt)*) => {};
329 (emit I64AtomicRmw8AndU $($rest:tt)*) => {};
330 (emit I64AtomicRmw16AndU $($rest:tt)*) => {};
331 (emit I64AtomicRmw32AndU $($rest:tt)*) => {};
332 (emit I64AtomicRmwAnd $($rest:tt)*) => {};
333 (emit I32AtomicRmw8OrU $($rest:tt)*) => {};
334 (emit I32AtomicRmw16OrU $($rest:tt)*) => {};
335 (emit I32AtomicRmwOr $($rest:tt)*) => {};
336 (emit I64AtomicRmw8OrU $($rest:tt)*) => {};
337 (emit I64AtomicRmw16OrU $($rest:tt)*) => {};
338 (emit I64AtomicRmw32OrU $($rest:tt)*) => {};
339 (emit I64AtomicRmwOr $($rest:tt)*) => {};
340 (emit I32AtomicRmw8XorU $($rest:tt)*) => {};
341 (emit I32AtomicRmw16XorU $($rest:tt)*) => {};
342 (emit I32AtomicRmwXor $($rest:tt)*) => {};
343 (emit I64AtomicRmw8XorU $($rest:tt)*) => {};
344 (emit I64AtomicRmw16XorU $($rest:tt)*) => {};
345 (emit I64AtomicRmw32XorU $($rest:tt)*) => {};
346 (emit I64AtomicRmwXor $($rest:tt)*) => {};
347 (emit I8x16ReplaceLane $($rest:tt)*) => {};
348 (emit I16x8ReplaceLane $($rest:tt)*) => {};
349 (emit I32x4ReplaceLane $($rest:tt)*) => {};
350 (emit I64x2ReplaceLane $($rest:tt)*) => {};
351 (emit F32x4ReplaceLane $($rest:tt)*) => {};
352 (emit F64x2ReplaceLane $($rest:tt)*) => {};
353 (emit I32AtomicRmw8CmpxchgU $($rest:tt)*) => {};
354 (emit I32AtomicRmw16CmpxchgU $($rest:tt)*) => {};
355 (emit I32AtomicRmwCmpxchg $($rest:tt)*) => {};
356 (emit I64AtomicRmw8CmpxchgU $($rest:tt)*) => {};
357 (emit I64AtomicRmw16CmpxchgU $($rest:tt)*) => {};
358 (emit I64AtomicRmw32CmpxchgU $($rest:tt)*) => {};
359 (emit I64AtomicRmwCmpxchg $($rest:tt)*) => {};
360 (emit I8x16Eq $($rest:tt)*) => {};
361 (emit I16x8Eq $($rest:tt)*) => {};
362 (emit I32x4Eq $($rest:tt)*) => {};
363 (emit I64x2Eq $($rest:tt)*) => {};
364 (emit F32x4Eq $($rest:tt)*) => {};
365 (emit F64x2Eq $($rest:tt)*) => {};
366 (emit I8x16Ne $($rest:tt)*) => {};
367 (emit I16x8Ne $($rest:tt)*) => {};
368 (emit I32x4Ne $($rest:tt)*) => {};
369 (emit I64x2Ne $($rest:tt)*) => {};
370 (emit F32x4Ne $($rest:tt)*) => {};
371 (emit F64x2Ne $($rest:tt)*) => {};
372 (emit I8x16LtS $($rest:tt)*) => {};
373 (emit I8x16LtU $($rest:tt)*) => {};
374 (emit I16x8LtS $($rest:tt)*) => {};
375 (emit I16x8LtU $($rest:tt)*) => {};
376 (emit I32x4LtS $($rest:tt)*) => {};
377 (emit I32x4LtU $($rest:tt)*) => {};
378 (emit I64x2LtS $($rest:tt)*) => {};
379 (emit F32x4Lt $($rest:tt)*) => {};
380 (emit F64x2Lt $($rest:tt)*) => {};
381 (emit I8x16LeS $($rest:tt)*) => {};
382 (emit I8x16LeU $($rest:tt)*) => {};
383 (emit I16x8LeS $($rest:tt)*) => {};
384 (emit I16x8LeU $($rest:tt)*) => {};
385 (emit I32x4LeS $($rest:tt)*) => {};
386 (emit I32x4LeU $($rest:tt)*) => {};
387 (emit I64x2LeS $($rest:tt)*) => {};
388 (emit F32x4Le $($rest:tt)*) => {};
389 (emit F64x2Le $($rest:tt)*) => {};
390 (emit I8x16GtS $($rest:tt)*) => {};
391 (emit I8x16GtU $($rest:tt)*) => {};
392 (emit I16x8GtS $($rest:tt)*) => {};
393 (emit I16x8GtU $($rest:tt)*) => {};
394 (emit I32x4GtS $($rest:tt)*) => {};
395 (emit I32x4GtU $($rest:tt)*) => {};
396 (emit I64x2GtS $($rest:tt)*) => {};
397 (emit F32x4Gt $($rest:tt)*) => {};
398 (emit F64x2Gt $($rest:tt)*) => {};
399 (emit I8x16GeS $($rest:tt)*) => {};
400 (emit I8x16GeU $($rest:tt)*) => {};
401 (emit I16x8GeS $($rest:tt)*) => {};
402 (emit I16x8GeU $($rest:tt)*) => {};
403 (emit I32x4GeS $($rest:tt)*) => {};
404 (emit I32x4GeU $($rest:tt)*) => {};
405 (emit I64x2GeS $($rest:tt)*) => {};
406 (emit F32x4Ge $($rest:tt)*) => {};
407 (emit F64x2Ge $($rest:tt)*) => {};
408 (emit MemoryAtomicWait32 $($rest:tt)*) => {};
409 (emit MemoryAtomicWait64 $($rest:tt)*) => {};
410 (emit MemoryAtomicNotify $($rest:tt)*) => {};
411 (emit AtomicFence $($rest:tt)*) => {};
412 (emit V128Not $($rest:tt)*) => {};
413 (emit V128And $($rest:tt)*) => {};
414 (emit V128AndNot $($rest:tt)*) => {};
415 (emit V128Or $($rest:tt)*) => {};
416 (emit V128Xor $($rest:tt)*) => {};
417 (emit V128Bitselect $($rest:tt)*) => {};
418 (emit V128AnyTrue $($rest:tt)*) => {};
419 (emit V128Load8Lane $($rest:tt)*) => {};
420 (emit V128Load16Lane $($rest:tt)*) => {};
421 (emit V128Load32Lane $($rest:tt)*) => {};
422 (emit V128Load64Lane $($rest:tt)*) => {};
423 (emit V128Store8Lane $($rest:tt)*) => {};
424 (emit V128Store16Lane $($rest:tt)*) => {};
425 (emit V128Store32Lane $($rest:tt)*) => {};
426 (emit V128Store64Lane $($rest:tt)*) => {};
427 (emit F32x4ConvertI32x4S $($rest:tt)*) => {};
428 (emit F32x4ConvertI32x4U $($rest:tt)*) => {};
429 (emit F64x2ConvertLowI32x4S $($rest:tt)*) => {};
430 (emit F64x2ConvertLowI32x4U $($rest:tt)*) => {};
431 (emit I8x16NarrowI16x8S $($rest:tt)*) => {};
432 (emit I8x16NarrowI16x8U $($rest:tt)*) => {};
433 (emit I16x8NarrowI32x4S $($rest:tt)*) => {};
434 (emit I16x8NarrowI32x4U $($rest:tt)*) => {};
435 (emit F32x4DemoteF64x2Zero $($rest:tt)*) => {};
436 (emit F64x2PromoteLowF32x4 $($rest:tt)*) => {};
437 (emit I16x8ExtendLowI8x16S $($rest:tt)*) => {};
438 (emit I16x8ExtendHighI8x16S $($rest:tt)*) => {};
439 (emit I16x8ExtendLowI8x16U $($rest:tt)*) => {};
440 (emit I16x8ExtendHighI8x16U $($rest:tt)*) => {};
441 (emit I32x4ExtendLowI16x8S $($rest:tt)*) => {};
442 (emit I32x4ExtendHighI16x8S $($rest:tt)*) => {};
443 (emit I32x4ExtendLowI16x8U $($rest:tt)*) => {};
444 (emit I32x4ExtendHighI16x8U $($rest:tt)*) => {};
445 (emit I64x2ExtendLowI32x4S $($rest:tt)*) => {};
446 (emit I64x2ExtendHighI32x4S $($rest:tt)*) => {};
447 (emit I64x2ExtendLowI32x4U $($rest:tt)*) => {};
448 (emit I64x2ExtendHighI32x4U $($rest:tt)*) => {};
449 (emit I8x16Add $($rest:tt)*) => {};
450 (emit I16x8Add $($rest:tt)*) => {};
451 (emit I32x4Add $($rest:tt)*) => {};
452 (emit I64x2Add $($rest:tt)*) => {};
453 (emit I8x16Sub $($rest:tt)*) => {};
454 (emit I16x8Sub $($rest:tt)*) => {};
455 (emit I32x4Sub $($rest:tt)*) => {};
456 (emit I64x2Sub $($rest:tt)*) => {};
457 (emit I16x8Mul $($rest:tt)*) => {};
458 (emit I32x4Mul $($rest:tt)*) => {};
459 (emit I64x2Mul $($rest:tt)*) => {};
460 (emit I8x16AddSatS $($rest:tt)*) => {};
461 (emit I16x8AddSatS $($rest:tt)*) => {};
462 (emit I8x16AddSatU $($rest:tt)*) => {};
463 (emit I16x8AddSatU $($rest:tt)*) => {};
464 (emit I8x16SubSatS $($rest:tt)*) => {};
465 (emit I16x8SubSatS $($rest:tt)*) => {};
466 (emit I8x16SubSatU $($rest:tt)*) => {};
467 (emit I16x8SubSatU $($rest:tt)*) => {};
468 (emit I8x16Abs $($rest:tt)*) => {};
469 (emit I16x8Abs $($rest:tt)*) => {};
470 (emit I32x4Abs $($rest:tt)*) => {};
471 (emit I64x2Abs $($rest:tt)*) => {};
472 (emit F32x4Abs $($rest:tt)*) => {};
473 (emit F64x2Abs $($rest:tt)*) => {};
474 (emit I8x16Neg $($rest:tt)*) => {};
475 (emit I16x8Neg $($rest:tt)*) => {};
476 (emit I32x4Neg $($rest:tt)*) => {};
477 (emit I64x2Neg $($rest:tt)*) => {};
478 (emit I8x16Shl $($rest:tt)*) => {};
479 (emit I16x8Shl $($rest:tt)*) => {};
480 (emit I32x4Shl $($rest:tt)*) => {};
481 (emit I64x2Shl $($rest:tt)*) => {};
482 (emit I8x16ShrU $($rest:tt)*) => {};
483 (emit I16x8ShrU $($rest:tt)*) => {};
484 (emit I32x4ShrU $($rest:tt)*) => {};
485 (emit I64x2ShrU $($rest:tt)*) => {};
486 (emit I8x16ShrS $($rest:tt)*) => {};
487 (emit I16x8ShrS $($rest:tt)*) => {};
488 (emit I32x4ShrS $($rest:tt)*) => {};
489 (emit I64x2ShrS $($rest:tt)*) => {};
490 (emit I16x8Q15MulrSatS $($rest:tt)*) => {};
491 (emit I8x16AllTrue $($rest:tt)*) => {};
492 (emit I16x8AllTrue $($rest:tt)*) => {};
493 (emit I32x4AllTrue $($rest:tt)*) => {};
494 (emit I64x2AllTrue $($rest:tt)*) => {};
495 (emit I8x16Bitmask $($rest:tt)*) => {};
496 (emit I16x8Bitmask $($rest:tt)*) => {};
497 (emit I32x4Bitmask $($rest:tt)*) => {};
498 (emit I64x2Bitmask $($rest:tt)*) => {};
499 (emit I32x4TruncSatF32x4S $($rest:tt)*) => {};
500 (emit I32x4TruncSatF32x4U $($rest:tt)*) => {};
501 (emit I32x4TruncSatF64x2SZero $($rest:tt)*) => {};
502 (emit I32x4TruncSatF64x2UZero $($rest:tt)*) => {};
503 (emit I8x16MinU $($rest:tt)*) => {};
504 (emit I16x8MinU $($rest:tt)*) => {};
505 (emit I32x4MinU $($rest:tt)*) => {};
506 (emit I8x16MinS $($rest:tt)*) => {};
507 (emit I16x8MinS $($rest:tt)*) => {};
508 (emit I32x4MinS $($rest:tt)*) => {};
509 (emit I8x16MaxU $($rest:tt)*) => {};
510 (emit I16x8MaxU $($rest:tt)*) => {};
511 (emit I32x4MaxU $($rest:tt)*) => {};
512 (emit I8x16MaxS $($rest:tt)*) => {};
513 (emit I16x8MaxS $($rest:tt)*) => {};
514 (emit I32x4MaxS $($rest:tt)*) => {};
515 (emit I16x8ExtMulLowI8x16S $($rest:tt)*) => {};
516 (emit I32x4ExtMulLowI16x8S $($rest:tt)*) => {};
517 (emit I64x2ExtMulLowI32x4S $($rest:tt)*) => {};
518 (emit I16x8ExtMulHighI8x16S $($rest:tt)*) => {};
519 (emit I32x4ExtMulHighI16x8S $($rest:tt)*) => {};
520 (emit I64x2ExtMulHighI32x4S $($rest:tt)*) => {};
521 (emit I16x8ExtMulLowI8x16U $($rest:tt)*) => {};
522 (emit I32x4ExtMulLowI16x8U $($rest:tt)*) => {};
523 (emit I64x2ExtMulLowI32x4U $($rest:tt)*) => {};
524 (emit I16x8ExtMulHighI8x16U $($rest:tt)*) => {};
525 (emit I32x4ExtMulHighI16x8U $($rest:tt)*) => {};
526 (emit I64x2ExtMulHighI32x4U $($rest:tt)*) => {};
527 (emit I16x8ExtAddPairwiseI8x16U $($rest:tt)*) => {};
528 (emit I16x8ExtAddPairwiseI8x16S $($rest:tt)*) => {};
529 (emit I32x4ExtAddPairwiseI16x8U $($rest:tt)*) => {};
530 (emit I32x4ExtAddPairwiseI16x8S $($rest:tt)*) => {};
531 (emit I32x4DotI16x8S $($rest:tt)*) => {};
532 (emit I8x16Popcnt $($rest:tt)*) => {};
533 (emit I8x16AvgrU $($rest:tt)*) => {};
534 (emit I16x8AvgrU $($rest:tt)*) => {};
535 (emit F32x4Add $($rest:tt)*) => {};
536 (emit F64x2Add $($rest:tt)*) => {};
537 (emit F32x4Sub $($rest:tt)*) => {};
538 (emit F64x2Sub $($rest:tt)*) => {};
539 (emit F32x4Mul $($rest:tt)*) => {};
540 (emit F64x2Mul $($rest:tt)*) => {};
541 (emit F32x4Div $($rest:tt)*) => {};
542 (emit F64x2Div $($rest:tt)*) => {};
543 (emit F32x4Neg $($rest:tt)*) => {};
544 (emit F64x2Neg $($rest:tt)*) => {};
545 (emit F32x4Sqrt $($rest:tt)*) => {};
546 (emit F64x2Sqrt $($rest:tt)*) => {};
547 (emit F32x4Ceil $($rest:tt)*) => {};
548 (emit F64x2Ceil $($rest:tt)*) => {};
549 (emit F32x4Floor $($rest:tt)*) => {};
550 (emit F64x2Floor $($rest:tt)*) => {};
551 (emit F32x4Nearest $($rest:tt)*) => {};
552 (emit F64x2Nearest $($rest:tt)*) => {};
553 (emit F32x4Trunc $($rest:tt)*) => {};
554 (emit F64x2Trunc $($rest:tt)*) => {};
555 (emit V128Load32Zero $($rest:tt)*) => {};
556 (emit V128Load64Zero $($rest:tt)*) => {};
557 (emit F32x4PMin $($rest:tt)*) => {};
558 (emit F64x2PMin $($rest:tt)*) => {};
559 (emit F32x4PMax $($rest:tt)*) => {};
560 (emit F64x2PMax $($rest:tt)*) => {};
561 (emit F32x4Min $($rest:tt)*) => {};
562 (emit F64x2Min $($rest:tt)*) => {};
563 (emit F32x4Max $($rest:tt)*) => {};
564 (emit F64x2Max $($rest:tt)*) => {};
565
566 (emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
567}
568
569impl<'a, 'translation, 'data, M> VisitOperator<'a> for CodeGen<'a, 'translation, 'data, M, Emission>
570where
571 M: MacroAssembler,
572{
573 type Output = Result<()>;
574
575 fn visit_i32_const(&mut self, val: i32) -> Self::Output {
576 self.context.stack.push(Val::i32(val));
577
578 Ok(())
579 }
580
581 fn visit_i64_const(&mut self, val: i64) -> Self::Output {
582 self.context.stack.push(Val::i64(val));
583 Ok(())
584 }
585
586 fn visit_f32_const(&mut self, val: Ieee32) -> Self::Output {
587 self.context.stack.push(Val::f32(val));
588 Ok(())
589 }
590
591 fn visit_f64_const(&mut self, val: Ieee64) -> Self::Output {
592 self.context.stack.push(Val::f64(val));
593 Ok(())
594 }
595
596 fn visit_f32_add(&mut self) -> Self::Output {
597 self.context.binop(
598 self.masm,
599 OperandSize::S32,
600 &mut |masm: &mut M, dst, src, size| {
601 masm.float_add(writable!(dst), dst, src, size)?;
602 masm.maybe_canonicalize_nan(writable!(dst), size)?;
603 Ok(TypedReg::f32(dst))
604 },
605 )
606 }
607
608 fn visit_f64_add(&mut self) -> Self::Output {
609 self.context.binop(
610 self.masm,
611 OperandSize::S64,
612 &mut |masm: &mut M, dst, src, size| {
613 masm.float_add(writable!(dst), dst, src, size)?;
614 masm.maybe_canonicalize_nan(writable!(dst), size)?;
615 Ok(TypedReg::f64(dst))
616 },
617 )
618 }
619
620 fn visit_f32_sub(&mut self) -> Self::Output {
621 self.context.binop(
622 self.masm,
623 OperandSize::S32,
624 &mut |masm: &mut M, dst, src, size| {
625 masm.float_sub(writable!(dst), dst, src, size)?;
626 masm.maybe_canonicalize_nan(writable!(dst), size)?;
627 Ok(TypedReg::f32(dst))
628 },
629 )
630 }
631
632 fn visit_f64_sub(&mut self) -> Self::Output {
633 self.context.binop(
634 self.masm,
635 OperandSize::S64,
636 &mut |masm: &mut M, dst, src, size| {
637 masm.float_sub(writable!(dst), dst, src, size)?;
638 masm.maybe_canonicalize_nan(writable!(dst), size)?;
639 Ok(TypedReg::f64(dst))
640 },
641 )
642 }
643
644 fn visit_f32_mul(&mut self) -> Self::Output {
645 self.context.binop(
646 self.masm,
647 OperandSize::S32,
648 &mut |masm: &mut M, dst, src, size| {
649 masm.float_mul(writable!(dst), dst, src, size)?;
650 masm.maybe_canonicalize_nan(writable!(dst), size)?;
651 Ok(TypedReg::f32(dst))
652 },
653 )
654 }
655
656 fn visit_f64_mul(&mut self) -> Self::Output {
657 self.context.binop(
658 self.masm,
659 OperandSize::S64,
660 &mut |masm: &mut M, dst, src, size| {
661 masm.float_mul(writable!(dst), dst, src, size)?;
662 masm.maybe_canonicalize_nan(writable!(dst), size)?;
663 Ok(TypedReg::f64(dst))
664 },
665 )
666 }
667
668 fn visit_f32_div(&mut self) -> Self::Output {
669 self.context.binop(
670 self.masm,
671 OperandSize::S32,
672 &mut |masm: &mut M, dst, src, size| {
673 masm.float_div(writable!(dst), dst, src, size)?;
674 masm.maybe_canonicalize_nan(writable!(dst), size)?;
675 Ok(TypedReg::f32(dst))
676 },
677 )
678 }
679
680 fn visit_f64_div(&mut self) -> Self::Output {
681 self.context.binop(
682 self.masm,
683 OperandSize::S64,
684 &mut |masm: &mut M, dst, src, size| {
685 masm.float_div(writable!(dst), dst, src, size)?;
686 masm.maybe_canonicalize_nan(writable!(dst), size)?;
687 Ok(TypedReg::f64(dst))
688 },
689 )
690 }
691
692 fn visit_f32_min(&mut self) -> Self::Output {
693 self.context.binop(
694 self.masm,
695 OperandSize::S32,
696 &mut |masm: &mut M, dst, src, size| {
697 masm.float_min(writable!(dst), dst, src, size)?;
698 masm.maybe_canonicalize_nan(writable!(dst), size)?;
699 Ok(TypedReg::f32(dst))
700 },
701 )
702 }
703
704 fn visit_f64_min(&mut self) -> Self::Output {
705 self.context.binop(
706 self.masm,
707 OperandSize::S64,
708 &mut |masm: &mut M, dst, src, size| {
709 masm.float_min(writable!(dst), dst, src, size)?;
710 masm.maybe_canonicalize_nan(writable!(dst), size)?;
711 Ok(TypedReg::f64(dst))
712 },
713 )
714 }
715
716 fn visit_f32_max(&mut self) -> Self::Output {
717 self.context.binop(
718 self.masm,
719 OperandSize::S32,
720 &mut |masm: &mut M, dst, src, size| {
721 masm.float_max(writable!(dst), dst, src, size)?;
722 masm.maybe_canonicalize_nan(writable!(dst), size)?;
723 Ok(TypedReg::f32(dst))
724 },
725 )
726 }
727
728 fn visit_f64_max(&mut self) -> Self::Output {
729 self.context.binop(
730 self.masm,
731 OperandSize::S64,
732 &mut |masm: &mut M, dst, src, size| {
733 masm.float_max(writable!(dst), dst, src, size)?;
734 masm.maybe_canonicalize_nan(writable!(dst), size)?;
735 Ok(TypedReg::f64(dst))
736 },
737 )
738 }
739
740 fn visit_f32_copysign(&mut self) -> Self::Output {
741 self.context.binop(
742 self.masm,
743 OperandSize::S32,
744 &mut |masm: &mut M, dst, src, size| {
745 masm.float_copysign(writable!(dst), dst, src, size)?;
746 Ok(TypedReg::f32(dst))
747 },
748 )
749 }
750
751 fn visit_f64_copysign(&mut self) -> Self::Output {
752 self.context.binop(
753 self.masm,
754 OperandSize::S64,
755 &mut |masm: &mut M, dst, src, size| {
756 masm.float_copysign(writable!(dst), dst, src, size)?;
757 Ok(TypedReg::f64(dst))
758 },
759 )
760 }
761
762 fn visit_f32_abs(&mut self) -> Self::Output {
763 self.context.unop(self.masm, |masm, reg| {
764 masm.float_abs(writable!(reg), OperandSize::S32)?;
765 Ok(TypedReg::f32(reg))
766 })
767 }
768
769 fn visit_f64_abs(&mut self) -> Self::Output {
770 self.context.unop(self.masm, |masm, reg| {
771 masm.float_abs(writable!(reg), OperandSize::S64)?;
772 Ok(TypedReg::f64(reg))
773 })
774 }
775
776 fn visit_f32_neg(&mut self) -> Self::Output {
777 self.context.unop(self.masm, |masm, reg| {
778 masm.float_neg(writable!(reg), OperandSize::S32)?;
779 Ok(TypedReg::f32(reg))
780 })
781 }
782
783 fn visit_f64_neg(&mut self) -> Self::Output {
784 self.context.unop(self.masm, |masm, reg| {
785 masm.float_neg(writable!(reg), OperandSize::S64)?;
786 Ok(TypedReg::f64(reg))
787 })
788 }
789
790 fn visit_f32_floor(&mut self) -> Self::Output {
791 self.masm.float_round(
792 RoundingMode::Down,
793 &mut self.env,
794 &mut self.context,
795 OperandSize::S32,
796 |env, cx, masm| {
797 let builtin = env.builtins.floor_f32::<M::ABI>()?;
798 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
799 },
800 )?;
801 let result = self.context.pop_to_reg(self.masm, None)?;
802 self.masm
803 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S32)?;
804 self.context.stack.push(result.into());
805 Ok(())
806 }
807
808 fn visit_f64_floor(&mut self) -> Self::Output {
809 self.masm.float_round(
810 RoundingMode::Down,
811 &mut self.env,
812 &mut self.context,
813 OperandSize::S64,
814 |env, cx, masm| {
815 let builtin = env.builtins.floor_f64::<M::ABI>()?;
816 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
817 },
818 )?;
819 let result = self.context.pop_to_reg(self.masm, None)?;
820 self.masm
821 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S64)?;
822 self.context.stack.push(result.into());
823 Ok(())
824 }
825
826 fn visit_f32_ceil(&mut self) -> Self::Output {
827 self.masm.float_round(
828 RoundingMode::Up,
829 &mut self.env,
830 &mut self.context,
831 OperandSize::S32,
832 |env, cx, masm| {
833 let builtin = env.builtins.ceil_f32::<M::ABI>()?;
834 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
835 },
836 )?;
837 let result = self.context.pop_to_reg(self.masm, None)?;
838 self.masm
839 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S32)?;
840 self.context.stack.push(result.into());
841 Ok(())
842 }
843
844 fn visit_f64_ceil(&mut self) -> Self::Output {
845 self.masm.float_round(
846 RoundingMode::Up,
847 &mut self.env,
848 &mut self.context,
849 OperandSize::S64,
850 |env, cx, masm| {
851 let builtin = env.builtins.ceil_f64::<M::ABI>()?;
852 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
853 },
854 )?;
855 let result = self.context.pop_to_reg(self.masm, None)?;
856 self.masm
857 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S64)?;
858 self.context.stack.push(result.into());
859 Ok(())
860 }
861
862 fn visit_f32_nearest(&mut self) -> Self::Output {
863 self.masm.float_round(
864 RoundingMode::Nearest,
865 &mut self.env,
866 &mut self.context,
867 OperandSize::S32,
868 |env, cx, masm| {
869 let builtin = env.builtins.nearest_f32::<M::ABI>()?;
870 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
871 },
872 )?;
873 let result = self.context.pop_to_reg(self.masm, None)?;
874 self.masm
875 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S32)?;
876 self.context.stack.push(result.into());
877 Ok(())
878 }
879
880 fn visit_f64_nearest(&mut self) -> Self::Output {
881 self.masm.float_round(
882 RoundingMode::Nearest,
883 &mut self.env,
884 &mut self.context,
885 OperandSize::S64,
886 |env, cx, masm| {
887 let builtin = env.builtins.nearest_f64::<M::ABI>()?;
888 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
889 },
890 )?;
891 let result = self.context.pop_to_reg(self.masm, None)?;
892 self.masm
893 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S64)?;
894 self.context.stack.push(result.into());
895 Ok(())
896 }
897
898 fn visit_f32_trunc(&mut self) -> Self::Output {
899 self.masm.float_round(
900 RoundingMode::Zero,
901 &mut self.env,
902 &mut self.context,
903 OperandSize::S32,
904 |env, cx, masm| {
905 let builtin = env.builtins.trunc_f32::<M::ABI>()?;
906 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
907 },
908 )?;
909 let result = self.context.pop_to_reg(self.masm, None)?;
910 self.masm
911 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S32)?;
912 self.context.stack.push(result.into());
913 Ok(())
914 }
915
916 fn visit_f64_trunc(&mut self) -> Self::Output {
917 self.masm.float_round(
918 RoundingMode::Zero,
919 &mut self.env,
920 &mut self.context,
921 OperandSize::S64,
922 |env, cx, masm| {
923 let builtin = env.builtins.trunc_f64::<M::ABI>()?;
924 FnCall::emit::<M>(env, masm, cx, Callee::Builtin(builtin))
925 },
926 )?;
927 let result = self.context.pop_to_reg(self.masm, None)?;
928 self.masm
929 .maybe_canonicalize_nan(writable!(result.into()), OperandSize::S64)?;
930 self.context.stack.push(result.into());
931 Ok(())
932 }
933
934 fn visit_f32_sqrt(&mut self) -> Self::Output {
935 self.context.unop(self.masm, |masm, reg| {
936 masm.float_sqrt(writable!(reg), reg, OperandSize::S32)?;
937 masm.maybe_canonicalize_nan(writable!(reg), OperandSize::S32)?;
938 Ok(TypedReg::f32(reg))
939 })
940 }
941
942 fn visit_f64_sqrt(&mut self) -> Self::Output {
943 self.context.unop(self.masm, |masm, reg| {
944 masm.float_sqrt(writable!(reg), reg, OperandSize::S64)?;
945 masm.maybe_canonicalize_nan(writable!(reg), OperandSize::S64)?;
946 Ok(TypedReg::f64(reg))
947 })
948 }
949
950 fn visit_f32_eq(&mut self) -> Self::Output {
951 self.context.float_cmp_op(
952 self.masm,
953 OperandSize::S32,
954 &mut |masm: &mut M, dst, src1, src2, size| {
955 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Eq, size)
956 },
957 )
958 }
959
960 fn visit_f64_eq(&mut self) -> Self::Output {
961 self.context.float_cmp_op(
962 self.masm,
963 OperandSize::S64,
964 &mut |masm: &mut M, dst, src1, src2, size| {
965 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Eq, size)
966 },
967 )
968 }
969
970 fn visit_f32_ne(&mut self) -> Self::Output {
971 self.context.float_cmp_op(
972 self.masm,
973 OperandSize::S32,
974 &mut |masm: &mut M, dst, src1, src2, size| {
975 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ne, size)
976 },
977 )
978 }
979
980 fn visit_f64_ne(&mut self) -> Self::Output {
981 self.context.float_cmp_op(
982 self.masm,
983 OperandSize::S64,
984 &mut |masm: &mut M, dst, src1, src2, size| {
985 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ne, size)
986 },
987 )
988 }
989
990 fn visit_f32_lt(&mut self) -> Self::Output {
991 self.context.float_cmp_op(
992 self.masm,
993 OperandSize::S32,
994 &mut |masm: &mut M, dst, src1, src2, size| {
995 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Lt, size)
996 },
997 )
998 }
999
1000 fn visit_f64_lt(&mut self) -> Self::Output {
1001 self.context.float_cmp_op(
1002 self.masm,
1003 OperandSize::S64,
1004 &mut |masm: &mut M, dst, src1, src2, size| {
1005 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Lt, size)
1006 },
1007 )
1008 }
1009
1010 fn visit_f32_gt(&mut self) -> Self::Output {
1011 self.context.float_cmp_op(
1012 self.masm,
1013 OperandSize::S32,
1014 &mut |masm: &mut M, dst, src1, src2, size| {
1015 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Gt, size)
1016 },
1017 )
1018 }
1019
1020 fn visit_f64_gt(&mut self) -> Self::Output {
1021 self.context.float_cmp_op(
1022 self.masm,
1023 OperandSize::S64,
1024 &mut |masm: &mut M, dst, src1, src2, size| {
1025 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Gt, size)
1026 },
1027 )
1028 }
1029
1030 fn visit_f32_le(&mut self) -> Self::Output {
1031 self.context.float_cmp_op(
1032 self.masm,
1033 OperandSize::S32,
1034 &mut |masm: &mut M, dst, src1, src2, size| {
1035 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Le, size)
1036 },
1037 )
1038 }
1039
1040 fn visit_f64_le(&mut self) -> Self::Output {
1041 self.context.float_cmp_op(
1042 self.masm,
1043 OperandSize::S64,
1044 &mut |masm: &mut M, dst, src1, src2, size| {
1045 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Le, size)
1046 },
1047 )
1048 }
1049
1050 fn visit_f32_ge(&mut self) -> Self::Output {
1051 self.context.float_cmp_op(
1052 self.masm,
1053 OperandSize::S32,
1054 &mut |masm: &mut M, dst, src1, src2, size| {
1055 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ge, size)
1056 },
1057 )
1058 }
1059
1060 fn visit_f64_ge(&mut self) -> Self::Output {
1061 self.context.float_cmp_op(
1062 self.masm,
1063 OperandSize::S64,
1064 &mut |masm: &mut M, dst, src1, src2, size| {
1065 masm.float_cmp_with_set(writable!(dst), src1, src2, FloatCmpKind::Ge, size)
1066 },
1067 )
1068 }
1069
1070 fn visit_f32_convert_i32_s(&mut self) -> Self::Output {
1071 self.context
1072 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, dst_size| {
1073 masm.signed_convert(writable!(dst), src, OperandSize::S32, dst_size)
1074 })
1075 }
1076
1077 fn visit_f32_convert_i32_u(&mut self) -> Self::Output {
1078 self.context.convert_op_with_tmp_reg(
1079 self.masm,
1080 WasmValType::F32,
1081 RegClass::Int,
1082 |masm, dst, src, tmp_gpr, dst_size| {
1083 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S32, dst_size)
1084 },
1085 )
1086 }
1087
1088 fn visit_f32_convert_i64_s(&mut self) -> Self::Output {
1089 self.context
1090 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, dst_size| {
1091 masm.signed_convert(writable!(dst), src, OperandSize::S64, dst_size)
1092 })
1093 }
1094
1095 fn visit_f32_convert_i64_u(&mut self) -> Self::Output {
1096 self.context.convert_op_with_tmp_reg(
1097 self.masm,
1098 WasmValType::F32,
1099 RegClass::Int,
1100 |masm, dst, src, tmp_gpr, dst_size| {
1101 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S64, dst_size)
1102 },
1103 )
1104 }
1105
1106 fn visit_f64_convert_i32_s(&mut self) -> Self::Output {
1107 self.context
1108 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, dst_size| {
1109 masm.signed_convert(writable!(dst), src, OperandSize::S32, dst_size)
1110 })
1111 }
1112
1113 fn visit_f64_convert_i32_u(&mut self) -> Self::Output {
1114 self.context.convert_op_with_tmp_reg(
1115 self.masm,
1116 WasmValType::F64,
1117 RegClass::Int,
1118 |masm, dst, src, tmp_gpr, dst_size| {
1119 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S32, dst_size)
1120 },
1121 )
1122 }
1123
1124 fn visit_f64_convert_i64_s(&mut self) -> Self::Output {
1125 self.context
1126 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, dst_size| {
1127 masm.signed_convert(writable!(dst), src, OperandSize::S64, dst_size)
1128 })
1129 }
1130
1131 fn visit_f64_convert_i64_u(&mut self) -> Self::Output {
1132 self.context.convert_op_with_tmp_reg(
1133 self.masm,
1134 WasmValType::F64,
1135 RegClass::Int,
1136 |masm, dst, src, tmp_gpr, dst_size| {
1137 masm.unsigned_convert(writable!(dst), src, tmp_gpr, OperandSize::S64, dst_size)
1138 },
1139 )
1140 }
1141
1142 fn visit_f32_reinterpret_i32(&mut self) -> Self::Output {
1143 self.context
1144 .convert_op(self.masm, WasmValType::F32, |masm, dst, src, size| {
1145 masm.reinterpret_int_as_float(writable!(dst), src, size)
1146 })
1147 }
1148
1149 fn visit_f64_reinterpret_i64(&mut self) -> Self::Output {
1150 self.context
1151 .convert_op(self.masm, WasmValType::F64, |masm, dst, src, size| {
1152 masm.reinterpret_int_as_float(writable!(dst), src, size)
1153 })
1154 }
1155
1156 fn visit_f32_demote_f64(&mut self) -> Self::Output {
1157 self.context.unop(self.masm, |masm, reg| {
1158 masm.demote(writable!(reg), reg)?;
1159 masm.maybe_canonicalize_nan(writable!(reg), OperandSize::S32)?;
1160 Ok(TypedReg::f32(reg))
1161 })
1162 }
1163
1164 fn visit_f64_promote_f32(&mut self) -> Self::Output {
1165 self.context.unop(self.masm, |masm, reg| {
1166 masm.promote(writable!(reg), reg)?;
1167 masm.maybe_canonicalize_nan(writable!(reg), OperandSize::S64)?;
1168 Ok(TypedReg::f64(reg))
1169 })
1170 }
1171
1172 fn visit_i32_add(&mut self) -> Self::Output {
1173 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1174 masm.add(writable!(dst), dst, src, size)?;
1175 Ok(TypedReg::i32(dst))
1176 })
1177 }
1178
1179 fn visit_i64_add(&mut self) -> Self::Output {
1180 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1181 masm.add(writable!(dst), dst, src, size)?;
1182 Ok(TypedReg::i64(dst))
1183 })
1184 }
1185
1186 fn visit_i32_sub(&mut self) -> Self::Output {
1187 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1188 masm.sub(writable!(dst), dst, src, size)?;
1189 Ok(TypedReg::i32(dst))
1190 })
1191 }
1192
1193 fn visit_i64_sub(&mut self) -> Self::Output {
1194 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1195 masm.sub(writable!(dst), dst, src, size)?;
1196 Ok(TypedReg::i64(dst))
1197 })
1198 }
1199
1200 fn visit_i32_mul(&mut self) -> Self::Output {
1201 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1202 masm.mul(writable!(dst), dst, src, size)?;
1203 Ok(TypedReg::i32(dst))
1204 })
1205 }
1206
1207 fn visit_i64_mul(&mut self) -> Self::Output {
1208 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1209 masm.mul(writable!(dst), dst, src, size)?;
1210 Ok(TypedReg::i64(dst))
1211 })
1212 }
1213
1214 fn visit_i32_div_s(&mut self) -> Self::Output {
1215 use DivKind::*;
1216 use OperandSize::*;
1217
1218 self.masm.div(&mut self.context, Signed, S32)
1219 }
1220
1221 fn visit_i32_div_u(&mut self) -> Self::Output {
1222 use DivKind::*;
1223 use OperandSize::*;
1224
1225 self.masm.div(&mut self.context, Unsigned, S32)
1226 }
1227
1228 fn visit_i64_div_s(&mut self) -> Self::Output {
1229 use DivKind::*;
1230 use OperandSize::*;
1231
1232 self.masm.div(&mut self.context, Signed, S64)
1233 }
1234
1235 fn visit_i64_div_u(&mut self) -> Self::Output {
1236 use DivKind::*;
1237 use OperandSize::*;
1238
1239 self.masm.div(&mut self.context, Unsigned, S64)
1240 }
1241
1242 fn visit_i32_rem_s(&mut self) -> Self::Output {
1243 use OperandSize::*;
1244 use RemKind::*;
1245
1246 self.masm.rem(&mut self.context, Signed, S32)
1247 }
1248
1249 fn visit_i32_rem_u(&mut self) -> Self::Output {
1250 use OperandSize::*;
1251 use RemKind::*;
1252
1253 self.masm.rem(&mut self.context, Unsigned, S32)
1254 }
1255
1256 fn visit_i64_rem_s(&mut self) -> Self::Output {
1257 use OperandSize::*;
1258 use RemKind::*;
1259
1260 self.masm.rem(&mut self.context, Signed, S64)
1261 }
1262
1263 fn visit_i64_rem_u(&mut self) -> Self::Output {
1264 use OperandSize::*;
1265 use RemKind::*;
1266
1267 self.masm.rem(&mut self.context, Unsigned, S64)
1268 }
1269
1270 fn visit_i32_eq(&mut self) -> Self::Output {
1271 self.cmp_i32s(IntCmpKind::Eq)
1272 }
1273
1274 fn visit_i64_eq(&mut self) -> Self::Output {
1275 self.cmp_i64s(IntCmpKind::Eq)
1276 }
1277
1278 fn visit_i32_ne(&mut self) -> Self::Output {
1279 self.cmp_i32s(IntCmpKind::Ne)
1280 }
1281
1282 fn visit_i64_ne(&mut self) -> Self::Output {
1283 self.cmp_i64s(IntCmpKind::Ne)
1284 }
1285
1286 fn visit_i32_lt_s(&mut self) -> Self::Output {
1287 self.cmp_i32s(IntCmpKind::LtS)
1288 }
1289
1290 fn visit_i64_lt_s(&mut self) -> Self::Output {
1291 self.cmp_i64s(IntCmpKind::LtS)
1292 }
1293
1294 fn visit_i32_lt_u(&mut self) -> Self::Output {
1295 self.cmp_i32s(IntCmpKind::LtU)
1296 }
1297
1298 fn visit_i64_lt_u(&mut self) -> Self::Output {
1299 self.cmp_i64s(IntCmpKind::LtU)
1300 }
1301
1302 fn visit_i32_le_s(&mut self) -> Self::Output {
1303 self.cmp_i32s(IntCmpKind::LeS)
1304 }
1305
1306 fn visit_i64_le_s(&mut self) -> Self::Output {
1307 self.cmp_i64s(IntCmpKind::LeS)
1308 }
1309
1310 fn visit_i32_le_u(&mut self) -> Self::Output {
1311 self.cmp_i32s(IntCmpKind::LeU)
1312 }
1313
1314 fn visit_i64_le_u(&mut self) -> Self::Output {
1315 self.cmp_i64s(IntCmpKind::LeU)
1316 }
1317
1318 fn visit_i32_gt_s(&mut self) -> Self::Output {
1319 self.cmp_i32s(IntCmpKind::GtS)
1320 }
1321
1322 fn visit_i64_gt_s(&mut self) -> Self::Output {
1323 self.cmp_i64s(IntCmpKind::GtS)
1324 }
1325
1326 fn visit_i32_gt_u(&mut self) -> Self::Output {
1327 self.cmp_i32s(IntCmpKind::GtU)
1328 }
1329
1330 fn visit_i64_gt_u(&mut self) -> Self::Output {
1331 self.cmp_i64s(IntCmpKind::GtU)
1332 }
1333
1334 fn visit_i32_ge_s(&mut self) -> Self::Output {
1335 self.cmp_i32s(IntCmpKind::GeS)
1336 }
1337
1338 fn visit_i64_ge_s(&mut self) -> Self::Output {
1339 self.cmp_i64s(IntCmpKind::GeS)
1340 }
1341
1342 fn visit_i32_ge_u(&mut self) -> Self::Output {
1343 self.cmp_i32s(IntCmpKind::GeU)
1344 }
1345
1346 fn visit_i64_ge_u(&mut self) -> Self::Output {
1347 self.cmp_i64s(IntCmpKind::GeU)
1348 }
1349
1350 fn visit_i32_eqz(&mut self) -> Self::Output {
1351 use OperandSize::*;
1352
1353 self.context.unop(self.masm, |masm, reg| {
1354 masm.cmp_with_set(writable!(reg), RegImm::i32(0), IntCmpKind::Eq, S32)?;
1355 Ok(TypedReg::i32(reg))
1356 })
1357 }
1358
1359 fn visit_i64_eqz(&mut self) -> Self::Output {
1360 use OperandSize::*;
1361
1362 self.context.unop(self.masm, |masm, reg| {
1363 masm.cmp_with_set(writable!(reg), RegImm::i64(0), IntCmpKind::Eq, S64)?;
1364 Ok(TypedReg::i32(reg)) })
1366 }
1367
1368 fn visit_i32_clz(&mut self) -> Self::Output {
1369 use OperandSize::*;
1370
1371 self.context.unop(self.masm, |masm, reg| {
1372 masm.clz(writable!(reg), reg, S32)?;
1373 Ok(TypedReg::i32(reg))
1374 })
1375 }
1376
1377 fn visit_i64_clz(&mut self) -> Self::Output {
1378 use OperandSize::*;
1379
1380 self.context.unop(self.masm, |masm, reg| {
1381 masm.clz(writable!(reg), reg, S64)?;
1382 Ok(TypedReg::i64(reg))
1383 })
1384 }
1385
1386 fn visit_i32_ctz(&mut self) -> Self::Output {
1387 use OperandSize::*;
1388
1389 self.context.unop(self.masm, |masm, reg| {
1390 masm.ctz(writable!(reg), reg, S32)?;
1391 Ok(TypedReg::i32(reg))
1392 })
1393 }
1394
1395 fn visit_i64_ctz(&mut self) -> Self::Output {
1396 use OperandSize::*;
1397
1398 self.context.unop(self.masm, |masm, reg| {
1399 masm.ctz(writable!(reg), reg, S64)?;
1400 Ok(TypedReg::i64(reg))
1401 })
1402 }
1403
1404 fn visit_i32_and(&mut self) -> Self::Output {
1405 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1406 masm.and(writable!(dst), dst, src, size)?;
1407 Ok(TypedReg::i32(dst))
1408 })
1409 }
1410
1411 fn visit_i64_and(&mut self) -> Self::Output {
1412 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1413 masm.and(writable!(dst), dst, src, size)?;
1414 Ok(TypedReg::i64(dst))
1415 })
1416 }
1417
1418 fn visit_i32_or(&mut self) -> Self::Output {
1419 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1420 masm.or(writable!(dst), dst, src, size)?;
1421 Ok(TypedReg::i32(dst))
1422 })
1423 }
1424
1425 fn visit_i64_or(&mut self) -> Self::Output {
1426 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1427 masm.or(writable!(dst), dst, src, size)?;
1428 Ok(TypedReg::i64(dst))
1429 })
1430 }
1431
1432 fn visit_i32_xor(&mut self) -> Self::Output {
1433 self.context.i32_binop(self.masm, |masm, dst, src, size| {
1434 masm.xor(writable!(dst), dst, src, size)?;
1435 Ok(TypedReg::i32(dst))
1436 })
1437 }
1438
1439 fn visit_i64_xor(&mut self) -> Self::Output {
1440 self.context.i64_binop(self.masm, |masm, dst, src, size| {
1441 masm.xor(writable!(dst), dst, src, size)?;
1442 Ok(TypedReg::i64(dst))
1443 })
1444 }
1445
1446 fn visit_i32_shl(&mut self) -> Self::Output {
1447 use ShiftKind::*;
1448
1449 self.context.i32_shift(self.masm, Shl)
1450 }
1451
1452 fn visit_i64_shl(&mut self) -> Self::Output {
1453 use ShiftKind::*;
1454
1455 self.context.i64_shift(self.masm, Shl)
1456 }
1457
1458 fn visit_i32_shr_s(&mut self) -> Self::Output {
1459 use ShiftKind::*;
1460
1461 self.context.i32_shift(self.masm, ShrS)
1462 }
1463
1464 fn visit_i64_shr_s(&mut self) -> Self::Output {
1465 use ShiftKind::*;
1466
1467 self.context.i64_shift(self.masm, ShrS)
1468 }
1469
1470 fn visit_i32_shr_u(&mut self) -> Self::Output {
1471 use ShiftKind::*;
1472
1473 self.context.i32_shift(self.masm, ShrU)
1474 }
1475
1476 fn visit_i64_shr_u(&mut self) -> Self::Output {
1477 use ShiftKind::*;
1478
1479 self.context.i64_shift(self.masm, ShrU)
1480 }
1481
1482 fn visit_i32_rotl(&mut self) -> Self::Output {
1483 use ShiftKind::*;
1484
1485 self.context.i32_shift(self.masm, Rotl)
1486 }
1487
1488 fn visit_i64_rotl(&mut self) -> Self::Output {
1489 use ShiftKind::*;
1490
1491 self.context.i64_shift(self.masm, Rotl)
1492 }
1493
1494 fn visit_i32_rotr(&mut self) -> Self::Output {
1495 use ShiftKind::*;
1496
1497 self.context.i32_shift(self.masm, Rotr)
1498 }
1499
1500 fn visit_i64_rotr(&mut self) -> Self::Output {
1501 use ShiftKind::*;
1502
1503 self.context.i64_shift(self.masm, Rotr)
1504 }
1505
1506 fn visit_end(&mut self) -> Self::Output {
1507 if !self.context.reachable {
1508 self.handle_unreachable_end()
1509 } else {
1510 let mut control = self.pop_control_frame()?;
1511 control.emit_end(self.masm, &mut self.context)
1512 }
1513 }
1514
1515 fn visit_i32_popcnt(&mut self) -> Self::Output {
1516 use OperandSize::*;
1517 self.masm.popcnt(&mut self.context, S32)
1518 }
1519
1520 fn visit_i64_popcnt(&mut self) -> Self::Output {
1521 use OperandSize::*;
1522
1523 self.masm.popcnt(&mut self.context, S64)
1524 }
1525
1526 fn visit_i32_wrap_i64(&mut self) -> Self::Output {
1527 self.context.unop(self.masm, |masm, reg| {
1528 masm.wrap(writable!(reg), reg)?;
1529 Ok(TypedReg::i32(reg))
1530 })
1531 }
1532
1533 fn visit_i64_extend_i32_s(&mut self) -> Self::Output {
1534 self.context.unop(self.masm, |masm, reg| {
1535 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend32.into())?;
1536 Ok(TypedReg::i64(reg))
1537 })
1538 }
1539
1540 fn visit_i64_extend_i32_u(&mut self) -> Self::Output {
1541 self.context.unop(self.masm, |masm, reg| {
1542 masm.extend(writable!(reg), reg, Extend::<Zero>::I64Extend32.into())?;
1543 Ok(TypedReg::i64(reg))
1544 })
1545 }
1546
1547 fn visit_i32_extend8_s(&mut self) -> Self::Output {
1548 self.context.unop(self.masm, |masm, reg| {
1549 masm.extend(writable!(reg), reg, Extend::<Signed>::I32Extend8.into())?;
1550 Ok(TypedReg::i32(reg))
1551 })
1552 }
1553
1554 fn visit_i32_extend16_s(&mut self) -> Self::Output {
1555 self.context.unop(self.masm, |masm, reg| {
1556 masm.extend(writable!(reg), reg, Extend::<Signed>::I32Extend16.into())?;
1557 Ok(TypedReg::i32(reg))
1558 })
1559 }
1560
1561 fn visit_i64_extend8_s(&mut self) -> Self::Output {
1562 self.context.unop(self.masm, |masm, reg| {
1563 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend8.into())?;
1564 Ok(TypedReg::i64(reg))
1565 })
1566 }
1567
1568 fn visit_i64_extend16_s(&mut self) -> Self::Output {
1569 self.context.unop(self.masm, |masm, reg| {
1570 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend16.into())?;
1571 Ok(TypedReg::i64(reg))
1572 })
1573 }
1574
1575 fn visit_i64_extend32_s(&mut self) -> Self::Output {
1576 self.context.unop(self.masm, |masm, reg| {
1577 masm.extend(writable!(reg), reg, Extend::<Signed>::I64Extend32.into())?;
1578 Ok(TypedReg::i64(reg))
1579 })
1580 }
1581
1582 fn visit_i32_trunc_f32_s(&mut self) -> Self::Output {
1583 use OperandSize::*;
1584
1585 self.context
1586 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
1587 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Unchecked)
1588 })
1589 }
1590
1591 fn visit_i32_trunc_f32_u(&mut self) -> Self::Output {
1592 use OperandSize::*;
1593
1594 self.masm
1595 .unsigned_truncate(&mut self.context, S32, S32, TruncKind::Unchecked)
1596 }
1597
1598 fn visit_i32_trunc_f64_s(&mut self) -> Self::Output {
1599 use OperandSize::*;
1600
1601 self.context
1602 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
1603 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Unchecked)
1604 })
1605 }
1606
1607 fn visit_i32_trunc_f64_u(&mut self) -> Self::Output {
1608 use OperandSize::*;
1609 self.masm
1610 .unsigned_truncate(&mut self.context, S64, S32, TruncKind::Unchecked)
1611 }
1612
1613 fn visit_i64_trunc_f32_s(&mut self) -> Self::Output {
1614 use OperandSize::*;
1615
1616 self.context
1617 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
1618 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Unchecked)
1619 })
1620 }
1621
1622 fn visit_i64_trunc_f32_u(&mut self) -> Self::Output {
1623 use OperandSize::*;
1624
1625 self.masm
1626 .unsigned_truncate(&mut self.context, S32, S64, TruncKind::Unchecked)
1627 }
1628
1629 fn visit_i64_trunc_f64_s(&mut self) -> Self::Output {
1630 use OperandSize::*;
1631
1632 self.context
1633 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
1634 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Unchecked)
1635 })
1636 }
1637
1638 fn visit_i64_trunc_f64_u(&mut self) -> Self::Output {
1639 use OperandSize::*;
1640
1641 self.masm
1642 .unsigned_truncate(&mut self.context, S64, S64, TruncKind::Unchecked)
1643 }
1644
1645 fn visit_i32_reinterpret_f32(&mut self) -> Self::Output {
1646 self.context
1647 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, size| {
1648 masm.reinterpret_float_as_int(writable!(dst), src, size)
1649 })
1650 }
1651
1652 fn visit_i64_reinterpret_f64(&mut self) -> Self::Output {
1653 self.context
1654 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, size| {
1655 masm.reinterpret_float_as_int(writable!(dst), src, size)
1656 })
1657 }
1658
1659 fn visit_local_get(&mut self, index: u32) -> Self::Output {
1660 use WasmValType::*;
1661 let context = &mut self.context;
1662 let slot = context.frame.get_wasm_local(index);
1663 match slot.ty {
1664 I32 | I64 | F32 | F64 | V128 => context.stack.push(Val::local(index, slot.ty)),
1665 Ref(rt) => match rt.heap_type {
1666 WasmHeapType::Func => context.stack.push(Val::local(index, slot.ty)),
1667 _ => bail!(CodeGenError::unsupported_wasm_type()),
1668 },
1669 }
1670
1671 Ok(())
1672 }
1673
1674 fn visit_local_set(&mut self, index: u32) -> Self::Output {
1675 let src = self.emit_set_local(index)?;
1676 self.context.free_reg(src);
1677 Ok(())
1678 }
1679
1680 fn visit_call(&mut self, index: u32) -> Self::Output {
1681 let callee = self.env.callee_from_index(FuncIndex::from_u32(index));
1682 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, callee)?;
1683 Ok(())
1684 }
1685
1686 fn visit_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output {
1687 self.context.spill(self.masm)?;
1694
1695 let type_index = TypeIndex::from_u32(type_index);
1696 let table_index = TableIndex::from_u32(table_index);
1697
1698 self.emit_table_get(table_index)?;
1699
1700 let funcref_ptr = self
1704 .context
1705 .stack
1706 .peek()
1707 .map(|v| v.unwrap_reg())
1708 .ok_or_else(|| CodeGenError::missing_values_in_stack())?;
1709 self.masm
1710 .trapz(funcref_ptr.into(), TRAP_INDIRECT_CALL_TO_NULL)?;
1711 self.emit_typecheck_funcref(funcref_ptr.into(), type_index)?;
1712
1713 let callee = self.env.funcref(type_index);
1714 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, callee)?;
1715 Ok(())
1716 }
1717
1718 fn visit_table_init(&mut self, elem: u32, table: u32) -> Self::Output {
1719 self.emit_table_init(ElemIndex::from_u32(elem), TableIndex::from_u32(table))
1720 }
1721
1722 fn visit_table_copy(&mut self, dst: u32, src: u32) -> Self::Output {
1723 self.emit_table_copy(TableIndex::from_u32(dst), TableIndex::from_u32(src))
1724 }
1725
1726 fn visit_table_get(&mut self, table: u32) -> Self::Output {
1727 let table_index = TableIndex::from_u32(table);
1728 self.emit_table_get(table_index)
1729 }
1730
1731 fn visit_table_grow(&mut self, table: u32) -> Self::Output {
1732 let table_index = TableIndex::from_u32(table);
1733 self.emit_table_grow(table_index)
1734 }
1735
1736 fn visit_table_size(&mut self, table: u32) -> Self::Output {
1737 let table_index = TableIndex::from_u32(table);
1738 let table_data = self.env.resolve_table_data(table_index);
1739 self.emit_compute_table_size(&table_data)
1740 }
1741
1742 fn visit_table_fill(&mut self, table: u32) -> Self::Output {
1743 let table_index = TableIndex::from_u32(table);
1744 self.emit_table_fill(table_index)
1745 }
1746
1747 fn visit_table_set(&mut self, table: u32) -> Self::Output {
1748 let table_index = TableIndex::from_u32(table);
1749 self.emit_table_set(table_index)
1750 }
1751
1752 fn visit_elem_drop(&mut self, index: u32) -> Self::Output {
1753 let index = ElemIndex::from_u32(index);
1754 self.emit_elem_drop(index)
1755 }
1756
1757 fn visit_memory_init(&mut self, data_index: u32, mem: u32) -> Self::Output {
1758 self.emit_memory_init(DataIndex::from_u32(data_index), MemoryIndex::from_u32(mem))
1759 }
1760
1761 fn visit_memory_copy(&mut self, dst_mem: u32, src_mem: u32) -> Self::Output {
1762 self.emit_memory_copy(
1763 MemoryIndex::from_u32(dst_mem),
1764 MemoryIndex::from_u32(src_mem),
1765 )
1766 }
1767
1768 fn visit_memory_fill(&mut self, mem: u32) -> Self::Output {
1769 self.emit_memory_fill(MemoryIndex::from_u32(mem))
1770 }
1771
1772 fn visit_memory_size(&mut self, mem: u32) -> Self::Output {
1773 let heap = self.env.resolve_heap(MemoryIndex::from_u32(mem));
1774 self.emit_compute_memory_size(&heap)
1775 }
1776
1777 fn visit_memory_grow(&mut self, mem: u32) -> Self::Output {
1778 let at = self.context.stack.ensure_index_at(1)?;
1779 let mem = MemoryIndex::from_u32(mem);
1780 let builtin = self.env.builtins.memory_grow::<M::ABI>()?;
1784 let builtin = self.prepare_builtin_defined_memory_arg(mem, at + 1, builtin)?;
1785
1786 let heap = self.env.resolve_heap(mem);
1787 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
1788
1789 match (self.env.ptr_type(), heap.index_type()) {
1793 (WasmValType::I64, WasmValType::I64) => Ok(()),
1794 (WasmValType::I64, WasmValType::I32) => {
1797 let top: Reg = self.context.pop_to_reg(self.masm, None)?.into();
1798 self.masm.wrap(writable!(top), top)?;
1799 self.context.stack.push(TypedReg::i32(top).into());
1800 Ok(())
1801 }
1802 _ => Err(format_err!(CodeGenError::unsupported_32_bit_platform())),
1803 }
1804 }
1805
1806 fn visit_data_drop(&mut self, data_index: u32) -> Self::Output {
1807 self.emit_data_drop(DataIndex::from_u32(data_index))
1808 }
1809
1810 fn visit_nop(&mut self) -> Self::Output {
1811 Ok(())
1812 }
1813
1814 fn visit_if(&mut self, blockty: BlockType) -> Self::Output {
1815 self.control_frames.push(ControlStackFrame::r#if(
1816 self.env.resolve_block_sig(blockty)?,
1817 self.masm,
1818 &mut self.context,
1819 )?);
1820
1821 Ok(())
1822 }
1823
1824 fn visit_else(&mut self) -> Self::Output {
1825 if !self.context.reachable {
1826 self.handle_unreachable_else()
1827 } else {
1828 let control = self
1829 .control_frames
1830 .last_mut()
1831 .ok_or_else(|| CodeGenError::control_frame_expected())?;
1832 control.emit_else(self.masm, &mut self.context)
1833 }
1834 }
1835
1836 fn visit_block(&mut self, blockty: BlockType) -> Self::Output {
1837 self.control_frames.push(ControlStackFrame::block(
1838 self.env.resolve_block_sig(blockty)?,
1839 self.masm,
1840 &mut self.context,
1841 )?);
1842
1843 Ok(())
1844 }
1845
1846 fn visit_loop(&mut self, blockty: BlockType) -> Self::Output {
1847 self.control_frames.push(ControlStackFrame::r#loop(
1848 self.env.resolve_block_sig(blockty)?,
1849 self.masm,
1850 &mut self.context,
1851 )?);
1852
1853 self.maybe_emit_epoch_check()?;
1854 self.maybe_emit_fuel_check()
1855 }
1856
1857 fn visit_br(&mut self, depth: u32) -> Self::Output {
1858 let index = control_index(depth, self.control_frames.len())?;
1859 let frame = &mut self.control_frames[index];
1860 self.context
1861 .br::<_, _, UnconditionalBranch>(frame, self.masm, |masm, cx, frame| {
1862 frame.pop_abi_results::<M, _>(cx, masm, |results, _, _| {
1863 Ok(results.ret_area().copied())
1864 })
1865 })
1866 }
1867
1868 fn visit_br_if(&mut self, depth: u32) -> Self::Output {
1869 let index = control_index(depth, self.control_frames.len())?;
1870 let frame = &mut self.control_frames[index];
1871 frame.set_as_target();
1872
1873 let top = {
1874 let top = self.context.without::<Result<TypedReg>, M, _>(
1875 frame.results::<M>()?.regs(),
1876 self.masm,
1877 |ctx, masm| ctx.pop_to_reg(masm, None),
1878 )??;
1879 self.context.spill(self.masm)?;
1884 frame.top_abi_results::<M, _>(
1885 &mut self.context,
1886 self.masm,
1887 |results, context, masm| {
1888 if results.on_stack() {
1895 let stack_consumed = context.stack.sizeof(results.stack_operands_len());
1896 let base = masm.sp_offset()?.as_u32() - stack_consumed;
1897 let offs = base + results.size();
1898 Ok(Some(RetArea::sp(SPOffset::from_u32(offs))))
1899 } else {
1900 Ok(None)
1901 }
1902 },
1903 )?;
1904 top
1905 };
1906
1907 let current_sp_offset = self.masm.sp_offset()?;
1909 let unbalanced = frame.unbalanced(self.masm)?;
1910 let (label, cmp) = if unbalanced {
1911 (self.masm.get_label()?, IntCmpKind::Eq)
1912 } else {
1913 (*frame.label(), IntCmpKind::Ne)
1914 };
1915
1916 self.masm
1917 .branch(cmp, top.reg, top.reg.into(), label, OperandSize::S32)?;
1918 self.context.free_reg(top);
1919
1920 if unbalanced {
1921 self.context
1922 .br::<_, _, ConditionalBranch>(frame, self.masm, |_, _, _| Ok(()))?;
1923
1924 self.masm.reset_stack_pointer(current_sp_offset)?;
1927 self.masm.bind(label)?;
1928 }
1929
1930 Ok(())
1931 }
1932
1933 fn visit_br_table(&mut self, targets: BrTable<'a>) -> Self::Output {
1934 let len = targets.len() + 1;
1936 let mut labels: SmallVec<[_; 5]> = smallvec![];
1940 for _ in 0..len {
1941 labels.push(self.masm.get_label()?);
1942 }
1943
1944 let mut innermost = targets.default();
1955 for target in targets.targets() {
1956 let target = target?;
1957 if target < innermost {
1958 innermost = target;
1959 }
1960 }
1961
1962 let innermost_index = control_index(innermost, self.control_frames.len())?;
1963 let innermost_frame = &mut self.control_frames[innermost_index];
1964 let innermost_result = innermost_frame.results::<M>()?;
1965
1966 let (index, tmp) = {
1967 let index_and_tmp = self.context.without::<Result<(TypedReg, _)>, M, _>(
1968 innermost_result.regs(),
1969 self.masm,
1970 |cx, masm| Ok((cx.pop_to_reg(masm, None)?, cx.any_gpr(masm)?)),
1971 )??;
1972
1973 innermost_frame.pop_abi_results::<M, _>(
1985 &mut self.context,
1986 self.masm,
1987 |results, _, _| Ok(results.ret_area().copied()),
1988 )?;
1989 index_and_tmp
1990 };
1991
1992 self.masm.jmp_table(&labels, index.into(), tmp)?;
1993 let current_sp = self.masm.sp_offset()?;
1998
1999 for (t, l) in targets
2000 .targets()
2001 .chain(std::iter::once(Ok(targets.default())))
2002 .zip(labels.iter())
2003 {
2004 let control_index = control_index(t?, self.control_frames.len())?;
2005 let frame = &mut self.control_frames[control_index];
2006 self.masm.reset_stack_pointer(current_sp)?;
2010
2011 self.masm.bind(*l)?;
2015 self.context
2018 .br::<_, _, UnconditionalBranch>(frame, self.masm, |_, _, _| Ok(()))?;
2019 }
2020 self.masm.reset_stack_pointer(current_sp)?;
2024 self.context.reachable = false;
2025 self.context.free_reg(index.reg);
2026 self.context.free_reg(tmp);
2027
2028 Ok(())
2029 }
2030
2031 fn visit_return(&mut self) -> Self::Output {
2032 let outermost = &mut self.control_frames[0];
2037 self.context
2038 .br::<_, _, UnconditionalBranch>(outermost, self.masm, |masm, cx, frame| {
2039 frame.pop_abi_results::<M, _>(cx, masm, |results, _, _| {
2040 Ok(results.ret_area().copied())
2041 })
2042 })
2043 }
2044
2045 fn visit_unreachable(&mut self) -> Self::Output {
2046 self.masm.unreachable()?;
2047 self.context.reachable = false;
2048 let outermost = &mut self.control_frames[0];
2051 outermost.set_as_target();
2052
2053 Ok(())
2054 }
2055
2056 fn visit_local_tee(&mut self, index: u32) -> Self::Output {
2057 let typed_reg = self.emit_set_local(index)?;
2058 self.context.stack.push(typed_reg.into());
2059
2060 Ok(())
2061 }
2062
2063 fn visit_global_get(&mut self, global_index: u32) -> Self::Output {
2064 let index = GlobalIndex::from_u32(global_index);
2065 let (ty, base, offset) = self.emit_get_global_addr(index)?;
2066 let addr = self.masm.address_at_reg(base, offset)?;
2067 let dst = self.context.reg_for_type(ty, self.masm)?;
2068 self.masm.load(addr, writable!(dst), ty.try_into()?)?;
2069 self.context.stack.push(Val::reg(dst, ty));
2070
2071 self.context.free_reg(base);
2072
2073 Ok(())
2074 }
2075
2076 fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
2077 let index = GlobalIndex::from_u32(global_index);
2078 let (ty, base, offset) = self.emit_get_global_addr(index)?;
2079 let addr = self.masm.address_at_reg(base, offset)?;
2080
2081 let typed_reg = self.context.pop_to_reg(self.masm, None)?;
2082 self.masm
2083 .store(typed_reg.reg.into(), addr, ty.try_into()?)?;
2084 self.context.free_reg(typed_reg.reg);
2085 self.context.free_reg(base);
2086
2087 Ok(())
2088 }
2089
2090 fn visit_drop(&mut self) -> Self::Output {
2091 self.context.drop_last(1, |regalloc, val| match val {
2092 Val::Reg(tr) => Ok(regalloc.free(tr.reg)),
2093 Val::Memory(m) => self.masm.free_stack(m.slot.size),
2094 _ => Ok(()),
2095 })
2096 }
2097
2098 fn visit_select(&mut self) -> Self::Output {
2099 let cond = self.context.pop_to_reg(self.masm, None)?;
2100 let val2 = self.context.pop_to_reg(self.masm, None)?;
2101 let val1 = self.context.pop_to_reg(self.masm, None)?;
2102 self.masm.cmp(cond.reg, RegImm::i32(0), OperandSize::S32)?;
2103 self.masm.cmov(
2106 writable!(val2.into()),
2107 val1.into(),
2108 IntCmpKind::Ne,
2109 val1.ty.try_into()?,
2110 )?;
2111 self.context.stack.push(val2.into());
2112 self.context.free_reg(val1.reg);
2113 self.context.free_reg(cond);
2114
2115 Ok(())
2116 }
2117
2118 fn visit_typed_select(&mut self, _ty: ValType) -> Self::Output {
2119 self.visit_select()
2120 }
2121
2122 fn visit_ref_null(&mut self, hty: HeapType) -> Self::Output {
2123 match hty {
2124 HeapType::FUNC => {
2125 let ptr_type = self.env.ptr_type();
2126 match ptr_type {
2127 WasmValType::I64 => self.context.stack.push(Val::i64(0)),
2128 WasmValType::I32 => self.context.stack.push(Val::i32(0)),
2129 _ => bail!(CodeGenError::unsupported_wasm_type()),
2130 }
2131 Ok(())
2132 }
2133 _ => Err(format_err!(CodeGenError::unsupported_wasm_type())),
2134 }
2135 }
2136
2137 fn visit_ref_is_null(&mut self) -> Self::Output {
2138 let (zero, size) = match self.env.ptr_type() {
2139 WasmValType::I64 => (RegImm::i64(0), OperandSize::S64),
2140 WasmValType::I32 => (RegImm::i32(0), OperandSize::S32),
2141 _ => bail!(CodeGenError::unsupported_wasm_type()),
2142 };
2143 self.context.unop(self.masm, |masm, reg| {
2144 masm.cmp_with_set(writable!(reg), zero, IntCmpKind::Eq, size)?;
2145 Ok(TypedReg::i32(reg))
2146 })
2147 }
2148
2149 fn visit_ref_func(&mut self, function_index: u32) -> Self::Output {
2150 let ref_func = self.env.builtins.ref_func::<M::ABI>()?;
2151 self.context.stack.extend([function_index.try_into()?]);
2152 FnCall::emit::<M>(
2153 &mut self.env,
2154 self.masm,
2155 &mut self.context,
2156 Callee::Builtin(ref_func),
2157 )
2158 }
2159
2160 fn visit_i32_load(&mut self, memarg: MemArg) -> Self::Output {
2161 self.emit_wasm_load(
2162 &memarg,
2163 WasmValType::I32,
2164 LoadKind::Operand(OperandSize::S32),
2165 )
2166 }
2167
2168 fn visit_i32_load8_s(&mut self, memarg: MemArg) -> Self::Output {
2169 self.emit_wasm_load(
2170 &memarg,
2171 WasmValType::I32,
2172 LoadKind::ScalarExtend(Extend::<Signed>::I32Extend8.into()),
2173 )
2174 }
2175
2176 fn visit_i32_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2177 self.emit_wasm_load(
2178 &memarg,
2179 WasmValType::I32,
2180 LoadKind::ScalarExtend(Extend::<Zero>::I32Extend8.into()),
2181 )
2182 }
2183
2184 fn visit_i32_load16_s(&mut self, memarg: MemArg) -> Self::Output {
2185 self.emit_wasm_load(
2186 &memarg,
2187 WasmValType::I32,
2188 LoadKind::ScalarExtend(Extend::<Signed>::I32Extend16.into()),
2189 )
2190 }
2191
2192 fn visit_i32_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2193 self.emit_wasm_load(
2194 &memarg,
2195 WasmValType::I32,
2196 LoadKind::ScalarExtend(Extend::<Zero>::I32Extend16.into()),
2197 )
2198 }
2199
2200 fn visit_i32_store(&mut self, memarg: MemArg) -> Self::Output {
2201 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2202 }
2203
2204 fn visit_i32_store8(&mut self, memarg: MemArg) -> Self::Output {
2205 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S8))
2206 }
2207
2208 fn visit_i32_store16(&mut self, memarg: MemArg) -> Self::Output {
2209 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S16))
2210 }
2211
2212 fn visit_i64_load8_s(&mut self, memarg: MemArg) -> Self::Output {
2213 self.emit_wasm_load(
2214 &memarg,
2215 WasmValType::I64,
2216 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend8.into()),
2217 )
2218 }
2219
2220 fn visit_i64_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2221 self.emit_wasm_load(
2222 &memarg,
2223 WasmValType::I64,
2224 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend8.into()),
2225 )
2226 }
2227
2228 fn visit_i64_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2229 self.emit_wasm_load(
2230 &memarg,
2231 WasmValType::I64,
2232 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend16.into()),
2233 )
2234 }
2235
2236 fn visit_i64_load16_s(&mut self, memarg: MemArg) -> Self::Output {
2237 self.emit_wasm_load(
2238 &memarg,
2239 WasmValType::I64,
2240 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend16.into()),
2241 )
2242 }
2243
2244 fn visit_i64_load32_u(&mut self, memarg: MemArg) -> Self::Output {
2245 self.emit_wasm_load(
2246 &memarg,
2247 WasmValType::I64,
2248 LoadKind::ScalarExtend(Extend::<Zero>::I64Extend32.into()),
2249 )
2250 }
2251
2252 fn visit_i64_load32_s(&mut self, memarg: MemArg) -> Self::Output {
2253 self.emit_wasm_load(
2254 &memarg,
2255 WasmValType::I64,
2256 LoadKind::ScalarExtend(Extend::<Signed>::I64Extend32.into()),
2257 )
2258 }
2259
2260 fn visit_i64_load(&mut self, memarg: MemArg) -> Self::Output {
2261 self.emit_wasm_load(
2262 &memarg,
2263 WasmValType::I64,
2264 LoadKind::Operand(OperandSize::S64),
2265 )
2266 }
2267
2268 fn visit_i64_store(&mut self, memarg: MemArg) -> Self::Output {
2269 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S64))
2270 }
2271
2272 fn visit_i64_store8(&mut self, memarg: MemArg) -> Self::Output {
2273 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S8))
2274 }
2275
2276 fn visit_i64_store16(&mut self, memarg: MemArg) -> Self::Output {
2277 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S16))
2278 }
2279
2280 fn visit_i64_store32(&mut self, memarg: MemArg) -> Self::Output {
2281 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2282 }
2283
2284 fn visit_f32_load(&mut self, memarg: MemArg) -> Self::Output {
2285 self.emit_wasm_load(
2286 &memarg,
2287 WasmValType::F32,
2288 LoadKind::Operand(OperandSize::S32),
2289 )
2290 }
2291
2292 fn visit_f32_store(&mut self, memarg: MemArg) -> Self::Output {
2293 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S32))
2294 }
2295
2296 fn visit_f64_load(&mut self, memarg: MemArg) -> Self::Output {
2297 self.emit_wasm_load(
2298 &memarg,
2299 WasmValType::F64,
2300 LoadKind::Operand(OperandSize::S64),
2301 )
2302 }
2303
2304 fn visit_f64_store(&mut self, memarg: MemArg) -> Self::Output {
2305 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S64))
2306 }
2307
2308 fn visit_i32_trunc_sat_f32_s(&mut self) -> Self::Output {
2309 use OperandSize::*;
2310
2311 self.context
2312 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
2313 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Checked)
2314 })
2315 }
2316
2317 fn visit_i32_trunc_sat_f32_u(&mut self) -> Self::Output {
2318 use OperandSize::*;
2319
2320 self.masm
2321 .unsigned_truncate(&mut self.context, S32, S32, TruncKind::Checked)
2322 }
2323
2324 fn visit_i32_trunc_sat_f64_s(&mut self) -> Self::Output {
2325 use OperandSize::*;
2326
2327 self.context
2328 .convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
2329 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Checked)
2330 })
2331 }
2332
2333 fn visit_i32_trunc_sat_f64_u(&mut self) -> Self::Output {
2334 use OperandSize::*;
2335
2336 self.masm
2337 .unsigned_truncate(&mut self.context, S64, S32, TruncKind::Checked)
2338 }
2339
2340 fn visit_i64_trunc_sat_f32_s(&mut self) -> Self::Output {
2341 use OperandSize::*;
2342
2343 self.context
2344 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
2345 masm.signed_truncate(writable!(dst), src, S32, dst_size, TruncKind::Checked)
2346 })
2347 }
2348
2349 fn visit_i64_trunc_sat_f32_u(&mut self) -> Self::Output {
2350 use OperandSize::*;
2351
2352 self.masm
2353 .unsigned_truncate(&mut self.context, S32, S64, TruncKind::Checked)
2354 }
2355
2356 fn visit_i64_trunc_sat_f64_s(&mut self) -> Self::Output {
2357 use OperandSize::*;
2358
2359 self.context
2360 .convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
2361 masm.signed_truncate(writable!(dst), src, S64, dst_size, TruncKind::Checked)
2362 })
2363 }
2364
2365 fn visit_i64_trunc_sat_f64_u(&mut self) -> Self::Output {
2366 use OperandSize::*;
2367
2368 self.masm
2369 .unsigned_truncate(&mut self.context, S64, S64, TruncKind::Checked)
2370 }
2371
2372 fn visit_i64_add128(&mut self) -> Self::Output {
2373 self.context
2374 .binop128(self.masm, |masm, lhs_lo, lhs_hi, rhs_lo, rhs_hi| {
2375 masm.add128(
2376 writable!(lhs_lo),
2377 writable!(lhs_hi),
2378 lhs_lo,
2379 lhs_hi,
2380 rhs_lo,
2381 rhs_hi,
2382 )?;
2383 Ok((TypedReg::i64(lhs_lo), TypedReg::i64(lhs_hi)))
2384 })
2385 }
2386
2387 fn visit_i64_sub128(&mut self) -> Self::Output {
2388 self.context
2389 .binop128(self.masm, |masm, lhs_lo, lhs_hi, rhs_lo, rhs_hi| {
2390 masm.sub128(
2391 writable!(lhs_lo),
2392 writable!(lhs_hi),
2393 lhs_lo,
2394 lhs_hi,
2395 rhs_lo,
2396 rhs_hi,
2397 )?;
2398 Ok((TypedReg::i64(lhs_lo), TypedReg::i64(lhs_hi)))
2399 })
2400 }
2401
2402 fn visit_i64_mul_wide_s(&mut self) -> Self::Output {
2403 self.masm.mul_wide(&mut self.context, MulWideKind::Signed)
2404 }
2405
2406 fn visit_i64_mul_wide_u(&mut self) -> Self::Output {
2407 self.masm.mul_wide(&mut self.context, MulWideKind::Unsigned)
2408 }
2409
2410 fn visit_i32_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2411 self.emit_wasm_load(
2412 &memarg,
2413 WasmValType::I32,
2414 LoadKind::Atomic(OperandSize::S8, Some(Extend::<Zero>::I32Extend8.into())),
2415 )
2416 }
2417
2418 fn visit_i32_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2419 self.emit_wasm_load(
2420 &memarg,
2421 WasmValType::I32,
2422 LoadKind::Atomic(OperandSize::S16, Some(Extend::<Zero>::I32Extend16.into())),
2423 )
2424 }
2425
2426 fn visit_i32_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
2427 self.emit_wasm_load(
2428 &memarg,
2429 WasmValType::I32,
2430 LoadKind::Atomic(OperandSize::S32, None),
2431 )
2432 }
2433
2434 fn visit_i64_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
2435 self.emit_wasm_load(
2436 &memarg,
2437 WasmValType::I64,
2438 LoadKind::Atomic(OperandSize::S8, Some(Extend::<Zero>::I64Extend8.into())),
2439 )
2440 }
2441
2442 fn visit_i64_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
2443 self.emit_wasm_load(
2444 &memarg,
2445 WasmValType::I64,
2446 LoadKind::Atomic(OperandSize::S16, Some(Extend::<Zero>::I64Extend16.into())),
2447 )
2448 }
2449
2450 fn visit_i64_atomic_load32_u(&mut self, memarg: MemArg) -> Self::Output {
2451 self.emit_wasm_load(
2452 &memarg,
2453 WasmValType::I64,
2454 LoadKind::Atomic(OperandSize::S32, Some(Extend::<Zero>::I64Extend32.into())),
2455 )
2456 }
2457
2458 fn visit_i64_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
2459 self.emit_wasm_load(
2460 &memarg,
2461 WasmValType::I64,
2462 LoadKind::Atomic(OperandSize::S64, None),
2463 )
2464 }
2465
2466 fn visit_i32_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
2467 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S32))
2468 }
2469
2470 fn visit_i64_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
2471 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S64))
2472 }
2473
2474 fn visit_i32_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
2475 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S8))
2476 }
2477
2478 fn visit_i32_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
2479 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S16))
2480 }
2481
2482 fn visit_i64_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
2483 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S8))
2484 }
2485
2486 fn visit_i64_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
2487 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S16))
2488 }
2489
2490 fn visit_i64_atomic_store32(&mut self, memarg: MemArg) -> Self::Output {
2491 self.emit_wasm_store(&memarg, StoreKind::Atomic(OperandSize::S32))
2492 }
2493
2494 fn visit_i32_atomic_rmw8_add_u(&mut self, arg: MemArg) -> Self::Output {
2495 self.emit_atomic_rmw(
2496 &arg,
2497 RmwOp::Add,
2498 OperandSize::S8,
2499 Some(Extend::<Zero>::I32Extend8),
2500 )
2501 }
2502
2503 fn visit_i32_atomic_rmw16_add_u(&mut self, arg: MemArg) -> Self::Output {
2504 self.emit_atomic_rmw(
2505 &arg,
2506 RmwOp::Add,
2507 OperandSize::S16,
2508 Some(Extend::<Zero>::I32Extend16),
2509 )
2510 }
2511
2512 fn visit_i32_atomic_rmw_add(&mut self, arg: MemArg) -> Self::Output {
2513 self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S32, None)
2514 }
2515
2516 fn visit_i64_atomic_rmw8_add_u(&mut self, arg: MemArg) -> Self::Output {
2517 self.emit_atomic_rmw(
2518 &arg,
2519 RmwOp::Add,
2520 OperandSize::S8,
2521 Some(Extend::<Zero>::I64Extend8),
2522 )
2523 }
2524
2525 fn visit_i64_atomic_rmw16_add_u(&mut self, arg: MemArg) -> Self::Output {
2526 self.emit_atomic_rmw(
2527 &arg,
2528 RmwOp::Add,
2529 OperandSize::S16,
2530 Some(Extend::<Zero>::I64Extend16),
2531 )
2532 }
2533
2534 fn visit_i64_atomic_rmw32_add_u(&mut self, arg: MemArg) -> Self::Output {
2535 self.emit_atomic_rmw(
2536 &arg,
2537 RmwOp::Add,
2538 OperandSize::S32,
2539 Some(Extend::<Zero>::I64Extend32),
2540 )
2541 }
2542
2543 fn visit_i64_atomic_rmw_add(&mut self, arg: MemArg) -> Self::Output {
2544 self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S64, None)
2545 }
2546
2547 fn visit_i32_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2548 self.emit_atomic_rmw(
2549 &arg,
2550 RmwOp::Sub,
2551 OperandSize::S8,
2552 Some(Extend::<Zero>::I32Extend8),
2553 )
2554 }
2555 fn visit_i32_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2556 self.emit_atomic_rmw(
2557 &arg,
2558 RmwOp::Sub,
2559 OperandSize::S16,
2560 Some(Extend::<Zero>::I32Extend16),
2561 )
2562 }
2563
2564 fn visit_i32_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2565 self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
2566 }
2567
2568 fn visit_i64_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2569 self.emit_atomic_rmw(
2570 &arg,
2571 RmwOp::Sub,
2572 OperandSize::S8,
2573 Some(Extend::<Zero>::I64Extend8),
2574 )
2575 }
2576
2577 fn visit_i64_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2578 self.emit_atomic_rmw(
2579 &arg,
2580 RmwOp::Sub,
2581 OperandSize::S16,
2582 Some(Extend::<Zero>::I64Extend16),
2583 )
2584 }
2585
2586 fn visit_i64_atomic_rmw32_sub_u(&mut self, arg: MemArg) -> Self::Output {
2587 self.emit_atomic_rmw(
2588 &arg,
2589 RmwOp::Sub,
2590 OperandSize::S32,
2591 Some(Extend::<Zero>::I64Extend32),
2592 )
2593 }
2594
2595 fn visit_i64_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2596 self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S64, None)
2597 }
2598
2599 fn visit_i32_atomic_rmw8_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2600 self.emit_atomic_rmw(
2601 &arg,
2602 RmwOp::Xchg,
2603 OperandSize::S8,
2604 Some(Extend::<Zero>::I32Extend8),
2605 )
2606 }
2607
2608 fn visit_i32_atomic_rmw16_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2609 self.emit_atomic_rmw(
2610 &arg,
2611 RmwOp::Xchg,
2612 OperandSize::S16,
2613 Some(Extend::<Zero>::I32Extend16),
2614 )
2615 }
2616
2617 fn visit_i32_atomic_rmw_xchg(&mut self, arg: MemArg) -> Self::Output {
2618 self.emit_atomic_rmw(&arg, RmwOp::Xchg, OperandSize::S32, None)
2619 }
2620
2621 fn visit_i64_atomic_rmw8_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2622 self.emit_atomic_rmw(
2623 &arg,
2624 RmwOp::Xchg,
2625 OperandSize::S8,
2626 Some(Extend::<Zero>::I64Extend8),
2627 )
2628 }
2629
2630 fn visit_i64_atomic_rmw16_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2631 self.emit_atomic_rmw(
2632 &arg,
2633 RmwOp::Xchg,
2634 OperandSize::S16,
2635 Some(Extend::<Zero>::I64Extend16),
2636 )
2637 }
2638
2639 fn visit_i64_atomic_rmw32_xchg_u(&mut self, arg: MemArg) -> Self::Output {
2640 self.emit_atomic_rmw(
2641 &arg,
2642 RmwOp::Xchg,
2643 OperandSize::S32,
2644 Some(Extend::<Zero>::I64Extend32),
2645 )
2646 }
2647
2648 fn visit_i64_atomic_rmw_xchg(&mut self, arg: MemArg) -> Self::Output {
2649 self.emit_atomic_rmw(&arg, RmwOp::Xchg, OperandSize::S64, None)
2650 }
2651
2652 fn visit_i32_atomic_rmw8_and_u(&mut self, arg: MemArg) -> Self::Output {
2653 self.emit_atomic_rmw(
2654 &arg,
2655 RmwOp::And,
2656 OperandSize::S8,
2657 Some(Extend::<Zero>::I32Extend8),
2658 )
2659 }
2660
2661 fn visit_i32_atomic_rmw16_and_u(&mut self, arg: MemArg) -> Self::Output {
2662 self.emit_atomic_rmw(
2663 &arg,
2664 RmwOp::And,
2665 OperandSize::S16,
2666 Some(Extend::<Zero>::I32Extend16),
2667 )
2668 }
2669
2670 fn visit_i32_atomic_rmw_and(&mut self, arg: MemArg) -> Self::Output {
2671 self.emit_atomic_rmw(&arg, RmwOp::And, OperandSize::S32, None)
2672 }
2673
2674 fn visit_i64_atomic_rmw8_and_u(&mut self, arg: MemArg) -> Self::Output {
2675 self.emit_atomic_rmw(
2676 &arg,
2677 RmwOp::And,
2678 OperandSize::S8,
2679 Some(Extend::<Zero>::I64Extend8),
2680 )
2681 }
2682
2683 fn visit_i64_atomic_rmw16_and_u(&mut self, arg: MemArg) -> Self::Output {
2684 self.emit_atomic_rmw(
2685 &arg,
2686 RmwOp::And,
2687 OperandSize::S16,
2688 Some(Extend::<Zero>::I64Extend16),
2689 )
2690 }
2691
2692 fn visit_i64_atomic_rmw32_and_u(&mut self, arg: MemArg) -> Self::Output {
2693 self.emit_atomic_rmw(
2694 &arg,
2695 RmwOp::And,
2696 OperandSize::S32,
2697 Some(Extend::<Zero>::I64Extend32),
2698 )
2699 }
2700
2701 fn visit_i64_atomic_rmw_and(&mut self, arg: MemArg) -> Self::Output {
2702 self.emit_atomic_rmw(&arg, RmwOp::And, OperandSize::S64, None)
2703 }
2704
2705 fn visit_i32_atomic_rmw8_or_u(&mut self, arg: MemArg) -> Self::Output {
2706 self.emit_atomic_rmw(
2707 &arg,
2708 RmwOp::Or,
2709 OperandSize::S8,
2710 Some(Extend::<Zero>::I32Extend8),
2711 )
2712 }
2713
2714 fn visit_i32_atomic_rmw16_or_u(&mut self, arg: MemArg) -> Self::Output {
2715 self.emit_atomic_rmw(
2716 &arg,
2717 RmwOp::Or,
2718 OperandSize::S16,
2719 Some(Extend::<Zero>::I32Extend16),
2720 )
2721 }
2722
2723 fn visit_i32_atomic_rmw_or(&mut self, arg: MemArg) -> Self::Output {
2724 self.emit_atomic_rmw(&arg, RmwOp::Or, OperandSize::S32, None)
2725 }
2726
2727 fn visit_i64_atomic_rmw8_or_u(&mut self, arg: MemArg) -> Self::Output {
2728 self.emit_atomic_rmw(
2729 &arg,
2730 RmwOp::Or,
2731 OperandSize::S8,
2732 Some(Extend::<Zero>::I64Extend8),
2733 )
2734 }
2735
2736 fn visit_i64_atomic_rmw16_or_u(&mut self, arg: MemArg) -> Self::Output {
2737 self.emit_atomic_rmw(
2738 &arg,
2739 RmwOp::Or,
2740 OperandSize::S16,
2741 Some(Extend::<Zero>::I64Extend16),
2742 )
2743 }
2744
2745 fn visit_i64_atomic_rmw32_or_u(&mut self, arg: MemArg) -> Self::Output {
2746 self.emit_atomic_rmw(
2747 &arg,
2748 RmwOp::Or,
2749 OperandSize::S32,
2750 Some(Extend::<Zero>::I64Extend32),
2751 )
2752 }
2753
2754 fn visit_i64_atomic_rmw_or(&mut self, arg: MemArg) -> Self::Output {
2755 self.emit_atomic_rmw(&arg, RmwOp::Or, OperandSize::S64, None)
2756 }
2757
2758 fn visit_i32_atomic_rmw8_xor_u(&mut self, arg: MemArg) -> Self::Output {
2759 self.emit_atomic_rmw(
2760 &arg,
2761 RmwOp::Xor,
2762 OperandSize::S8,
2763 Some(Extend::<Zero>::I32Extend8),
2764 )
2765 }
2766
2767 fn visit_i32_atomic_rmw16_xor_u(&mut self, arg: MemArg) -> Self::Output {
2768 self.emit_atomic_rmw(
2769 &arg,
2770 RmwOp::Xor,
2771 OperandSize::S16,
2772 Some(Extend::<Zero>::I32Extend16),
2773 )
2774 }
2775
2776 fn visit_i32_atomic_rmw_xor(&mut self, arg: MemArg) -> Self::Output {
2777 self.emit_atomic_rmw(&arg, RmwOp::Xor, OperandSize::S32, None)
2778 }
2779
2780 fn visit_i64_atomic_rmw8_xor_u(&mut self, arg: MemArg) -> Self::Output {
2781 self.emit_atomic_rmw(
2782 &arg,
2783 RmwOp::Xor,
2784 OperandSize::S8,
2785 Some(Extend::<Zero>::I64Extend8),
2786 )
2787 }
2788
2789 fn visit_i64_atomic_rmw16_xor_u(&mut self, arg: MemArg) -> Self::Output {
2790 self.emit_atomic_rmw(
2791 &arg,
2792 RmwOp::Xor,
2793 OperandSize::S16,
2794 Some(Extend::<Zero>::I64Extend16),
2795 )
2796 }
2797
2798 fn visit_i64_atomic_rmw32_xor_u(&mut self, arg: MemArg) -> Self::Output {
2799 self.emit_atomic_rmw(
2800 &arg,
2801 RmwOp::Xor,
2802 OperandSize::S32,
2803 Some(Extend::<Zero>::I64Extend32),
2804 )
2805 }
2806
2807 fn visit_i64_atomic_rmw_xor(&mut self, arg: MemArg) -> Self::Output {
2808 self.emit_atomic_rmw(&arg, RmwOp::Xor, OperandSize::S64, None)
2809 }
2810
2811 fn visit_i32_atomic_rmw8_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2812 self.emit_atomic_cmpxchg(&arg, OperandSize::S8, Some(Extend::I32Extend8))
2813 }
2814
2815 fn visit_i32_atomic_rmw16_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2816 self.emit_atomic_cmpxchg(&arg, OperandSize::S16, Some(Extend::I32Extend16))
2817 }
2818
2819 fn visit_i32_atomic_rmw_cmpxchg(&mut self, arg: MemArg) -> Self::Output {
2820 self.emit_atomic_cmpxchg(&arg, OperandSize::S32, None)
2821 }
2822
2823 fn visit_i64_atomic_rmw8_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2824 self.emit_atomic_cmpxchg(&arg, OperandSize::S8, Some(Extend::I64Extend8))
2825 }
2826
2827 fn visit_i64_atomic_rmw16_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2828 self.emit_atomic_cmpxchg(&arg, OperandSize::S16, Some(Extend::I64Extend16))
2829 }
2830
2831 fn visit_i64_atomic_rmw32_cmpxchg_u(&mut self, arg: MemArg) -> Self::Output {
2832 self.emit_atomic_cmpxchg(&arg, OperandSize::S32, Some(Extend::I64Extend32))
2833 }
2834
2835 fn visit_i64_atomic_rmw_cmpxchg(&mut self, arg: MemArg) -> Self::Output {
2836 self.emit_atomic_cmpxchg(&arg, OperandSize::S64, None)
2837 }
2838
2839 fn visit_memory_atomic_wait32(&mut self, arg: MemArg) -> Self::Output {
2840 self.emit_atomic_wait(&arg, AtomicWaitKind::Wait32)
2841 }
2842
2843 fn visit_memory_atomic_wait64(&mut self, arg: MemArg) -> Self::Output {
2844 self.emit_atomic_wait(&arg, AtomicWaitKind::Wait64)
2845 }
2846
2847 fn visit_memory_atomic_notify(&mut self, arg: MemArg) -> Self::Output {
2848 self.emit_atomic_notify(&arg)
2849 }
2850
2851 fn visit_atomic_fence(&mut self) -> Self::Output {
2852 self.masm.fence()
2853 }
2854
2855 wasmparser::for_each_visit_operator!(def_unsupported);
2856}
2857
2858impl<'a, 'translation, 'data, M> VisitSimdOperator<'a>
2859 for CodeGen<'a, 'translation, 'data, M, Emission>
2860where
2861 M: MacroAssembler,
2862{
2863 fn visit_v128_const(&mut self, val: V128) -> Self::Output {
2864 self.context.stack.push(Val::v128(val.i128()));
2865 Ok(())
2866 }
2867
2868 fn visit_v128_load(&mut self, memarg: MemArg) -> Self::Output {
2869 self.emit_wasm_load(
2870 &memarg,
2871 WasmValType::V128,
2872 LoadKind::Operand(OperandSize::S128),
2873 )
2874 }
2875
2876 fn visit_v128_store(&mut self, memarg: MemArg) -> Self::Output {
2877 self.emit_wasm_store(&memarg, StoreKind::Operand(OperandSize::S128))
2878 }
2879
2880 fn visit_v128_load8x8_s(&mut self, memarg: MemArg) -> Self::Output {
2881 self.emit_wasm_load(
2882 &memarg,
2883 WasmValType::V128,
2884 LoadKind::VectorExtend(V128LoadExtendKind::E8x8S),
2885 )
2886 }
2887
2888 fn visit_v128_load8x8_u(&mut self, memarg: MemArg) -> Self::Output {
2889 self.emit_wasm_load(
2890 &memarg,
2891 WasmValType::V128,
2892 LoadKind::VectorExtend(V128LoadExtendKind::E8x8U),
2893 )
2894 }
2895
2896 fn visit_v128_load16x4_s(&mut self, memarg: MemArg) -> Self::Output {
2897 self.emit_wasm_load(
2898 &memarg,
2899 WasmValType::V128,
2900 LoadKind::VectorExtend(V128LoadExtendKind::E16x4S),
2901 )
2902 }
2903
2904 fn visit_v128_load16x4_u(&mut self, memarg: MemArg) -> Self::Output {
2905 self.emit_wasm_load(
2906 &memarg,
2907 WasmValType::V128,
2908 LoadKind::VectorExtend(V128LoadExtendKind::E16x4U),
2909 )
2910 }
2911
2912 fn visit_v128_load32x2_s(&mut self, memarg: MemArg) -> Self::Output {
2913 self.emit_wasm_load(
2914 &memarg,
2915 WasmValType::V128,
2916 LoadKind::VectorExtend(V128LoadExtendKind::E32x2S),
2917 )
2918 }
2919
2920 fn visit_v128_load32x2_u(&mut self, memarg: MemArg) -> Self::Output {
2921 self.emit_wasm_load(
2922 &memarg,
2923 WasmValType::V128,
2924 LoadKind::VectorExtend(V128LoadExtendKind::E32x2U),
2925 )
2926 }
2927
2928 fn visit_v128_load8_splat(&mut self, memarg: MemArg) -> Self::Output {
2929 self.emit_wasm_load(
2930 &memarg,
2931 WasmValType::V128,
2932 LoadKind::Splat(SplatLoadKind::S8),
2933 )
2934 }
2935
2936 fn visit_v128_load16_splat(&mut self, memarg: MemArg) -> Self::Output {
2937 self.emit_wasm_load(
2938 &memarg,
2939 WasmValType::V128,
2940 LoadKind::Splat(SplatLoadKind::S16),
2941 )
2942 }
2943
2944 fn visit_v128_load32_splat(&mut self, memarg: MemArg) -> Self::Output {
2945 self.emit_wasm_load(
2946 &memarg,
2947 WasmValType::V128,
2948 LoadKind::Splat(SplatLoadKind::S32),
2949 )
2950 }
2951
2952 fn visit_v128_load64_splat(&mut self, memarg: MemArg) -> Self::Output {
2953 self.emit_wasm_load(
2954 &memarg,
2955 WasmValType::V128,
2956 LoadKind::Splat(SplatLoadKind::S64),
2957 )
2958 }
2959
2960 fn visit_i8x16_splat(&mut self) -> Self::Output {
2961 self.masm.splat(&mut self.context, SplatKind::I8x16)
2962 }
2963
2964 fn visit_i16x8_splat(&mut self) -> Self::Output {
2965 self.masm.splat(&mut self.context, SplatKind::I16x8)
2966 }
2967
2968 fn visit_i32x4_splat(&mut self) -> Self::Output {
2969 self.masm.splat(&mut self.context, SplatKind::I32x4)
2970 }
2971
2972 fn visit_i64x2_splat(&mut self) -> Self::Output {
2973 self.masm.splat(&mut self.context, SplatKind::I64x2)
2974 }
2975
2976 fn visit_f32x4_splat(&mut self) -> Self::Output {
2977 self.masm.splat(&mut self.context, SplatKind::F32x4)
2978 }
2979
2980 fn visit_f64x2_splat(&mut self) -> Self::Output {
2981 self.masm.splat(&mut self.context, SplatKind::F64x2)
2982 }
2983
2984 fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
2985 let rhs = self.context.pop_to_reg(self.masm, None)?;
2986 let lhs = self.context.pop_to_reg(self.masm, None)?;
2987 self.masm
2988 .shuffle(writable!(lhs.into()), lhs.into(), rhs.into(), lanes)?;
2989 self.context.stack.push(TypedReg::v128(lhs.into()).into());
2990 self.context.free_reg(rhs);
2991 Ok(())
2992 }
2993
2994 fn visit_i8x16_swizzle(&mut self) -> Self::Output {
2995 let rhs = self.context.pop_to_reg(self.masm, None)?;
2996 let lhs = self.context.pop_to_reg(self.masm, None)?;
2997 self.masm
2998 .swizzle(writable!(lhs.into()), lhs.into(), rhs.into())?;
2999 self.context.stack.push(TypedReg::v128(lhs.into()).into());
3000 self.context.free_reg(rhs);
3001 Ok(())
3002 }
3003
3004 fn visit_i8x16_extract_lane_s(&mut self, lane: u8) -> Self::Output {
3005 self.context.extract_lane_op(
3006 self.masm,
3007 ExtractLaneKind::I8x16S,
3008 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3009 )
3010 }
3011
3012 fn visit_i8x16_extract_lane_u(&mut self, lane: u8) -> Self::Output {
3013 self.context.extract_lane_op(
3014 self.masm,
3015 ExtractLaneKind::I8x16U,
3016 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3017 )
3018 }
3019
3020 fn visit_i16x8_extract_lane_s(&mut self, lane: u8) -> Self::Output {
3021 self.context.extract_lane_op(
3022 self.masm,
3023 ExtractLaneKind::I16x8S,
3024 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3025 )
3026 }
3027
3028 fn visit_i16x8_extract_lane_u(&mut self, lane: u8) -> Self::Output {
3029 self.context.extract_lane_op(
3030 self.masm,
3031 ExtractLaneKind::I16x8U,
3032 |masm, src, dst, kind| masm.extract_lane(src, dst, lane, kind),
3033 )
3034 }
3035
3036 fn visit_i32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
3037 self.context
3038 .extract_lane_op(self.masm, ExtractLaneKind::I32x4, |masm, src, dst, kind| {
3039 masm.extract_lane(src, dst, lane, kind)
3040 })
3041 }
3042
3043 fn visit_i64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
3044 self.context
3045 .extract_lane_op(self.masm, ExtractLaneKind::I64x2, |masm, src, dst, kind| {
3046 masm.extract_lane(src, dst, lane, kind)
3047 })
3048 }
3049
3050 fn visit_f32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
3051 self.context
3052 .extract_lane_op(self.masm, ExtractLaneKind::F32x4, |masm, src, dst, kind| {
3053 masm.extract_lane(src, dst, lane, kind)
3054 })
3055 }
3056
3057 fn visit_f64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
3058 self.context
3059 .extract_lane_op(self.masm, ExtractLaneKind::F64x2, |masm, src, dst, kind| {
3060 masm.extract_lane(src, dst, lane, kind)
3061 })
3062 }
3063
3064 fn visit_i8x16_eq(&mut self) -> Self::Output {
3065 self.context
3066 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3067 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I8x16)?;
3068 Ok(TypedReg::v128(dst))
3069 })
3070 }
3071
3072 fn visit_i16x8_eq(&mut self) -> Self::Output {
3073 self.context
3074 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3075 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I16x8)?;
3076 Ok(TypedReg::v128(dst))
3077 })
3078 }
3079
3080 fn visit_i32x4_eq(&mut self) -> Self::Output {
3081 self.context
3082 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3083 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I32x4)?;
3084 Ok(TypedReg::v128(dst))
3085 })
3086 }
3087
3088 fn visit_i64x2_eq(&mut self) -> Self::Output {
3089 self.context
3090 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3091 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::I64x2)?;
3092 Ok(TypedReg::v128(dst))
3093 })
3094 }
3095
3096 fn visit_f32x4_eq(&mut self) -> Self::Output {
3097 self.context
3098 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3099 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::F32x4)?;
3100 Ok(TypedReg::v128(dst))
3101 })
3102 }
3103
3104 fn visit_f64x2_eq(&mut self) -> Self::Output {
3105 self.context
3106 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3107 masm.v128_eq(writable!(dst), dst, src, VectorEqualityKind::F64x2)?;
3108 Ok(TypedReg::v128(dst))
3109 })
3110 }
3111
3112 fn visit_i8x16_ne(&mut self) -> Self::Output {
3113 self.context
3114 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3115 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I8x16)?;
3116 Ok(TypedReg::v128(dst))
3117 })
3118 }
3119
3120 fn visit_i16x8_ne(&mut self) -> Self::Output {
3121 self.context
3122 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3123 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I16x8)?;
3124 Ok(TypedReg::v128(dst))
3125 })
3126 }
3127
3128 fn visit_i32x4_ne(&mut self) -> Self::Output {
3129 self.context
3130 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3131 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I32x4)?;
3132 Ok(TypedReg::v128(dst))
3133 })
3134 }
3135
3136 fn visit_i64x2_ne(&mut self) -> Self::Output {
3137 self.context
3138 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3139 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::I64x2)?;
3140 Ok(TypedReg::v128(dst))
3141 })
3142 }
3143
3144 fn visit_f32x4_ne(&mut self) -> Self::Output {
3145 self.context
3146 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3147 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::F32x4)?;
3148 Ok(TypedReg::v128(dst))
3149 })
3150 }
3151
3152 fn visit_f64x2_ne(&mut self) -> Self::Output {
3153 self.context
3154 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3155 masm.v128_ne(writable!(dst), dst, src, VectorEqualityKind::F64x2)?;
3156 Ok(TypedReg::v128(dst))
3157 })
3158 }
3159
3160 fn visit_i8x16_lt_s(&mut self) -> Self::Output {
3161 self.context
3162 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3163 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3164 Ok(TypedReg::v128(dst))
3165 })
3166 }
3167
3168 fn visit_i8x16_lt_u(&mut self) -> Self::Output {
3169 self.context
3170 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3171 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3172 Ok(TypedReg::v128(dst))
3173 })
3174 }
3175
3176 fn visit_i16x8_lt_s(&mut self) -> Self::Output {
3177 self.context
3178 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3179 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3180 Ok(TypedReg::v128(dst))
3181 })
3182 }
3183
3184 fn visit_i16x8_lt_u(&mut self) -> Self::Output {
3185 self.context
3186 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3187 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3188 Ok(TypedReg::v128(dst))
3189 })
3190 }
3191
3192 fn visit_i32x4_lt_s(&mut self) -> Self::Output {
3193 self.context
3194 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3195 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3196 Ok(TypedReg::v128(dst))
3197 })
3198 }
3199
3200 fn visit_i32x4_lt_u(&mut self) -> Self::Output {
3201 self.context
3202 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3203 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3204 Ok(TypedReg::v128(dst))
3205 })
3206 }
3207
3208 fn visit_i64x2_lt_s(&mut self) -> Self::Output {
3209 self.context
3210 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3211 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3212 Ok(TypedReg::v128(dst))
3213 })
3214 }
3215
3216 fn visit_f32x4_lt(&mut self) -> Self::Output {
3217 self.context
3218 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3219 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3220 Ok(TypedReg::v128(dst))
3221 })
3222 }
3223
3224 fn visit_f64x2_lt(&mut self) -> Self::Output {
3225 self.context
3226 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3227 masm.v128_lt(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3228 Ok(TypedReg::v128(dst))
3229 })
3230 }
3231
3232 fn visit_i8x16_le_s(&mut self) -> Self::Output {
3233 self.context
3234 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3235 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3236 Ok(TypedReg::v128(dst))
3237 })
3238 }
3239
3240 fn visit_i8x16_le_u(&mut self) -> Self::Output {
3241 self.context
3242 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3243 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3244 Ok(TypedReg::v128(dst))
3245 })
3246 }
3247
3248 fn visit_i16x8_le_s(&mut self) -> Self::Output {
3249 self.context
3250 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3251 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3252 Ok(TypedReg::v128(dst))
3253 })
3254 }
3255
3256 fn visit_i16x8_le_u(&mut self) -> Self::Output {
3257 self.context
3258 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3259 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3260 Ok(TypedReg::v128(dst))
3261 })
3262 }
3263
3264 fn visit_i32x4_le_s(&mut self) -> Self::Output {
3265 self.context
3266 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3267 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3268 Ok(TypedReg::v128(dst))
3269 })
3270 }
3271
3272 fn visit_i32x4_le_u(&mut self) -> Self::Output {
3273 self.context
3274 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3275 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3276 Ok(TypedReg::v128(dst))
3277 })
3278 }
3279
3280 fn visit_i64x2_le_s(&mut self) -> Self::Output {
3281 self.context
3282 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3283 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3284 Ok(TypedReg::v128(dst))
3285 })
3286 }
3287
3288 fn visit_f32x4_le(&mut self) -> Self::Output {
3289 self.context
3290 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3291 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3292 Ok(TypedReg::v128(dst))
3293 })
3294 }
3295
3296 fn visit_f64x2_le(&mut self) -> Self::Output {
3297 self.context
3298 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3299 masm.v128_le(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3300 Ok(TypedReg::v128(dst))
3301 })
3302 }
3303
3304 fn visit_i8x16_gt_s(&mut self) -> Self::Output {
3305 self.context
3306 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3307 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3308 Ok(TypedReg::v128(dst))
3309 })
3310 }
3311
3312 fn visit_i8x16_gt_u(&mut self) -> Self::Output {
3313 self.context
3314 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3315 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3316 Ok(TypedReg::v128(dst))
3317 })
3318 }
3319
3320 fn visit_i16x8_gt_s(&mut self) -> Self::Output {
3321 self.context
3322 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3323 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3324 Ok(TypedReg::v128(dst))
3325 })
3326 }
3327
3328 fn visit_i16x8_gt_u(&mut self) -> Self::Output {
3329 self.context
3330 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3331 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3332 Ok(TypedReg::v128(dst))
3333 })
3334 }
3335
3336 fn visit_i32x4_gt_s(&mut self) -> Self::Output {
3337 self.context
3338 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3339 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3340 Ok(TypedReg::v128(dst))
3341 })
3342 }
3343
3344 fn visit_i32x4_gt_u(&mut self) -> Self::Output {
3345 self.context
3346 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3347 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3348 Ok(TypedReg::v128(dst))
3349 })
3350 }
3351
3352 fn visit_i64x2_gt_s(&mut self) -> Self::Output {
3353 self.context
3354 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3355 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3356 Ok(TypedReg::v128(dst))
3357 })
3358 }
3359
3360 fn visit_f32x4_gt(&mut self) -> Self::Output {
3361 self.context
3362 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3363 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3364 Ok(TypedReg::v128(dst))
3365 })
3366 }
3367
3368 fn visit_f64x2_gt(&mut self) -> Self::Output {
3369 self.context
3370 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3371 masm.v128_gt(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3372 Ok(TypedReg::v128(dst))
3373 })
3374 }
3375
3376 fn visit_i8x16_ge_s(&mut self) -> Self::Output {
3377 self.context
3378 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3379 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I8x16S)?;
3380 Ok(TypedReg::v128(dst))
3381 })
3382 }
3383
3384 fn visit_i8x16_ge_u(&mut self) -> Self::Output {
3385 self.context
3386 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3387 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I8x16U)?;
3388 Ok(TypedReg::v128(dst))
3389 })
3390 }
3391
3392 fn visit_i16x8_ge_s(&mut self) -> Self::Output {
3393 self.context
3394 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3395 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I16x8S)?;
3396 Ok(TypedReg::v128(dst))
3397 })
3398 }
3399
3400 fn visit_i16x8_ge_u(&mut self) -> Self::Output {
3401 self.context
3402 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3403 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I16x8U)?;
3404 Ok(TypedReg::v128(dst))
3405 })
3406 }
3407
3408 fn visit_i32x4_ge_s(&mut self) -> Self::Output {
3409 self.context
3410 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3411 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I32x4S)?;
3412 Ok(TypedReg::v128(dst))
3413 })
3414 }
3415
3416 fn visit_i32x4_ge_u(&mut self) -> Self::Output {
3417 self.context
3418 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3419 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I32x4U)?;
3420 Ok(TypedReg::v128(dst))
3421 })
3422 }
3423
3424 fn visit_i64x2_ge_s(&mut self) -> Self::Output {
3425 self.context
3426 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3427 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::I64x2S)?;
3428 Ok(TypedReg::v128(dst))
3429 })
3430 }
3431
3432 fn visit_f32x4_ge(&mut self) -> Self::Output {
3433 self.context
3434 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3435 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::F32x4)?;
3436 Ok(TypedReg::v128(dst))
3437 })
3438 }
3439
3440 fn visit_f64x2_ge(&mut self) -> Self::Output {
3441 self.context
3442 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3443 masm.v128_ge(writable!(dst), dst, src, VectorCompareKind::F64x2)?;
3444 Ok(TypedReg::v128(dst))
3445 })
3446 }
3447
3448 fn visit_i8x16_replace_lane(&mut self, lane: u8) -> Self::Output {
3449 self.context
3450 .replace_lane_op(self.masm, ReplaceLaneKind::I8x16, |masm, src, dst, kind| {
3451 masm.replace_lane(src, dst, lane, kind)
3452 })
3453 }
3454
3455 fn visit_i16x8_replace_lane(&mut self, lane: u8) -> Self::Output {
3456 self.context
3457 .replace_lane_op(self.masm, ReplaceLaneKind::I16x8, |masm, src, dst, kind| {
3458 masm.replace_lane(src, dst, lane, kind)
3459 })
3460 }
3461
3462 fn visit_i32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
3463 self.context
3464 .replace_lane_op(self.masm, ReplaceLaneKind::I32x4, |masm, src, dst, kind| {
3465 masm.replace_lane(src, dst, lane, kind)
3466 })
3467 }
3468
3469 fn visit_i64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
3470 self.context
3471 .replace_lane_op(self.masm, ReplaceLaneKind::I64x2, |masm, src, dst, kind| {
3472 masm.replace_lane(src, dst, lane, kind)
3473 })
3474 }
3475
3476 fn visit_f32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
3477 self.context
3478 .replace_lane_op(self.masm, ReplaceLaneKind::F32x4, |masm, src, dst, kind| {
3479 masm.replace_lane(src, dst, lane, kind)
3480 })
3481 }
3482
3483 fn visit_f64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
3484 self.context
3485 .replace_lane_op(self.masm, ReplaceLaneKind::F64x2, |masm, src, dst, kind| {
3486 masm.replace_lane(src, dst, lane, kind)
3487 })
3488 }
3489
3490 fn visit_v128_not(&mut self) -> Self::Output {
3491 self.context.unop(self.masm, |masm, reg| {
3492 masm.v128_not(writable!(reg))?;
3493 Ok(TypedReg::new(WasmValType::V128, reg))
3494 })
3495 }
3496
3497 fn visit_v128_and(&mut self) -> Self::Output {
3498 self.context
3499 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3500 masm.v128_and(dst, src, writable!(dst))?;
3501 Ok(TypedReg::new(WasmValType::V128, dst))
3502 })
3503 }
3504
3505 fn visit_v128_andnot(&mut self) -> Self::Output {
3506 self.context
3507 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3508 masm.v128_and_not(src, dst, writable!(dst))?;
3510 Ok(TypedReg::new(WasmValType::V128, dst))
3511 })
3512 }
3513
3514 fn visit_v128_or(&mut self) -> Self::Output {
3515 self.context
3516 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3517 masm.v128_or(src, dst, writable!(dst))?;
3519 Ok(TypedReg::new(WasmValType::V128, dst))
3520 })
3521 }
3522
3523 fn visit_v128_xor(&mut self) -> Self::Output {
3524 self.context
3525 .binop(self.masm, OperandSize::S128, |masm, dst, src, _size| {
3526 masm.v128_xor(src, dst, writable!(dst))?;
3528 Ok(TypedReg::new(WasmValType::V128, dst))
3529 })
3530 }
3531
3532 fn visit_v128_bitselect(&mut self) -> Self::Output {
3533 let mask = self.context.pop_to_reg(self.masm, None)?;
3534 let op2 = self.context.pop_to_reg(self.masm, None)?;
3535 let op1 = self.context.pop_to_reg(self.masm, None)?;
3536 let dst = self.context.any_fpr(self.masm)?;
3537
3538 self.masm
3540 .v128_bitselect(op1.reg, op2.reg, mask.reg, writable!(dst))?;
3541
3542 self.context
3543 .stack
3544 .push(TypedReg::new(WasmValType::V128, dst).into());
3545 self.context.free_reg(op1);
3546 self.context.free_reg(op2);
3547 self.context.free_reg(mask);
3548
3549 Ok(())
3550 }
3551
3552 fn visit_v128_any_true(&mut self) -> Self::Output {
3553 let src = self.context.pop_to_reg(self.masm, None)?;
3554 let dst = self.context.any_gpr(self.masm)?;
3555
3556 self.masm.v128_any_true(src.reg, writable!(dst))?;
3557
3558 self.context
3559 .stack
3560 .push(TypedReg::new(WasmValType::I32, dst).into());
3561 self.context.free_reg(src);
3562
3563 Ok(())
3564 }
3565
3566 fn visit_v128_load8_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3567 self.emit_wasm_load(
3568 &arg,
3569 WasmValType::V128,
3570 LoadKind::vector_lane(lane, OperandSize::S8),
3571 )
3572 }
3573
3574 fn visit_v128_load16_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3575 self.emit_wasm_load(
3576 &arg,
3577 WasmValType::V128,
3578 LoadKind::vector_lane(lane, OperandSize::S16),
3579 )
3580 }
3581
3582 fn visit_v128_load32_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3583 self.emit_wasm_load(
3584 &arg,
3585 WasmValType::V128,
3586 LoadKind::vector_lane(lane, OperandSize::S32),
3587 )
3588 }
3589
3590 fn visit_v128_load64_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3591 self.emit_wasm_load(
3592 &arg,
3593 WasmValType::V128,
3594 LoadKind::vector_lane(lane, OperandSize::S64),
3595 )
3596 }
3597
3598 fn visit_v128_store8_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3599 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S8))
3600 }
3601
3602 fn visit_v128_store16_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3603 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S16))
3604 }
3605
3606 fn visit_v128_store32_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3607 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S32))
3608 }
3609
3610 fn visit_v128_store64_lane(&mut self, arg: MemArg, lane: u8) -> Self::Output {
3611 self.emit_wasm_store(&arg, StoreKind::vector_lane(lane, OperandSize::S64))
3612 }
3613
3614 fn visit_f32x4_convert_i32x4_s(&mut self) -> Self::Output {
3615 self.context.unop(self.masm, |masm, reg| {
3616 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4S)?;
3617 Ok(TypedReg::v128(reg))
3618 })
3619 }
3620
3621 fn visit_f32x4_convert_i32x4_u(&mut self) -> Self::Output {
3622 self.context.unop(self.masm, |masm, reg| {
3623 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4U)?;
3624 Ok(TypedReg::v128(reg))
3625 })
3626 }
3627
3628 fn visit_f64x2_convert_low_i32x4_s(&mut self) -> Self::Output {
3629 self.context.unop(self.masm, |masm, reg| {
3630 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4LowS)?;
3631 Ok(TypedReg::v128(reg))
3632 })
3633 }
3634
3635 fn visit_f64x2_convert_low_i32x4_u(&mut self) -> Self::Output {
3636 self.context.unop(self.masm, |masm, reg| {
3637 masm.v128_convert(reg, writable!(reg), V128ConvertKind::I32x4LowU)?;
3638 Ok(TypedReg::v128(reg))
3639 })
3640 }
3641
3642 fn visit_i8x16_narrow_i16x8_s(&mut self) -> Self::Output {
3643 self.context
3644 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3645 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I16x8S)?;
3646 Ok(TypedReg::v128(dst))
3647 })
3648 }
3649
3650 fn visit_i8x16_narrow_i16x8_u(&mut self) -> Self::Output {
3651 self.context
3652 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3653 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I16x8U)?;
3654 Ok(TypedReg::v128(dst))
3655 })
3656 }
3657
3658 fn visit_i16x8_narrow_i32x4_s(&mut self) -> Self::Output {
3659 self.context
3660 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3661 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I32x4S)?;
3662 Ok(TypedReg::v128(dst))
3663 })
3664 }
3665
3666 fn visit_i16x8_narrow_i32x4_u(&mut self) -> Self::Output {
3667 self.context
3668 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3669 masm.v128_narrow(dst, src, writable!(dst), V128NarrowKind::I32x4U)?;
3670 Ok(TypedReg::v128(dst))
3671 })
3672 }
3673
3674 fn visit_f32x4_demote_f64x2_zero(&mut self) -> Self::Output {
3675 self.context.unop(self.masm, |masm, reg| {
3676 masm.v128_demote(reg, writable!(reg))?;
3677 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S32)?;
3678 Ok(TypedReg::v128(reg))
3679 })
3680 }
3681
3682 fn visit_f64x2_promote_low_f32x4(&mut self) -> Self::Output {
3683 self.context.unop(self.masm, |masm, reg| {
3684 masm.v128_promote(reg, writable!(reg))?;
3685 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S64)?;
3686 Ok(TypedReg::v128(reg))
3687 })
3688 }
3689
3690 fn visit_i16x8_extend_low_i8x16_s(&mut self) -> Self::Output {
3691 self.context.unop(self.masm, |masm, reg| {
3692 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI8x16S)?;
3693 Ok(TypedReg::v128(reg))
3694 })
3695 }
3696
3697 fn visit_i16x8_extend_high_i8x16_s(&mut self) -> Self::Output {
3698 self.context.unop(self.masm, |masm, reg| {
3699 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI8x16S)?;
3700 Ok(TypedReg::v128(reg))
3701 })
3702 }
3703
3704 fn visit_i16x8_extend_low_i8x16_u(&mut self) -> Self::Output {
3705 self.context.unop(self.masm, |masm, reg| {
3706 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI8x16U)?;
3707 Ok(TypedReg::v128(reg))
3708 })
3709 }
3710
3711 fn visit_i16x8_extend_high_i8x16_u(&mut self) -> Self::Output {
3712 self.context.unop(self.masm, |masm, reg| {
3713 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI8x16U)?;
3714 Ok(TypedReg::v128(reg))
3715 })
3716 }
3717
3718 fn visit_i32x4_extend_low_i16x8_s(&mut self) -> Self::Output {
3719 self.context.unop(self.masm, |masm, reg| {
3720 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI16x8S)?;
3721 Ok(TypedReg::v128(reg))
3722 })
3723 }
3724
3725 fn visit_i32x4_extend_high_i16x8_s(&mut self) -> Self::Output {
3726 self.context.unop(self.masm, |masm, reg| {
3727 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI16x8S)?;
3728 Ok(TypedReg::v128(reg))
3729 })
3730 }
3731
3732 fn visit_i32x4_extend_low_i16x8_u(&mut self) -> Self::Output {
3733 self.context.unop(self.masm, |masm, reg| {
3734 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI16x8U)?;
3735 Ok(TypedReg::v128(reg))
3736 })
3737 }
3738
3739 fn visit_i32x4_extend_high_i16x8_u(&mut self) -> Self::Output {
3740 self.context.unop(self.masm, |masm, reg| {
3741 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI16x8U)?;
3742 Ok(TypedReg::v128(reg))
3743 })
3744 }
3745
3746 fn visit_i64x2_extend_low_i32x4_s(&mut self) -> Self::Output {
3747 self.context.unop(self.masm, |masm, reg| {
3748 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI32x4S)?;
3749 Ok(TypedReg::v128(reg))
3750 })
3751 }
3752
3753 fn visit_i64x2_extend_high_i32x4_s(&mut self) -> Self::Output {
3754 self.context.unop(self.masm, |masm, reg| {
3755 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI32x4S)?;
3756 Ok(TypedReg::v128(reg))
3757 })
3758 }
3759
3760 fn visit_i64x2_extend_low_i32x4_u(&mut self) -> Self::Output {
3761 self.context.unop(self.masm, |masm, reg| {
3762 masm.v128_extend(reg, writable!(reg), V128ExtendKind::LowI32x4U)?;
3763 Ok(TypedReg::v128(reg))
3764 })
3765 }
3766
3767 fn visit_i64x2_extend_high_i32x4_u(&mut self) -> Self::Output {
3768 self.context.unop(self.masm, |masm, reg| {
3769 masm.v128_extend(reg, writable!(reg), V128ExtendKind::HighI32x4U)?;
3770 Ok(TypedReg::v128(reg))
3771 })
3772 }
3773
3774 fn visit_i8x16_add(&mut self) -> Self::Output {
3775 self.context
3776 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3777 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16)?;
3778 Ok(TypedReg::new(WasmValType::V128, dst))
3779 })
3780 }
3781
3782 fn visit_i16x8_add(&mut self) -> Self::Output {
3783 self.context
3784 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3785 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8)?;
3786 Ok(TypedReg::new(WasmValType::V128, dst))
3787 })
3788 }
3789
3790 fn visit_i32x4_add(&mut self) -> Self::Output {
3791 self.context
3792 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3793 masm.v128_add(dst, src, writable!(dst), V128AddKind::I32x4)?;
3794 Ok(TypedReg::new(WasmValType::V128, dst))
3795 })
3796 }
3797
3798 fn visit_i64x2_add(&mut self) -> Self::Output {
3799 self.context
3800 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3801 masm.v128_add(dst, src, writable!(dst), V128AddKind::I64x2)?;
3802 Ok(TypedReg::new(WasmValType::V128, dst))
3803 })
3804 }
3805
3806 fn visit_i8x16_sub(&mut self) -> Self::Output {
3807 self.context
3808 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3809 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16)?;
3810 Ok(TypedReg::new(WasmValType::V128, dst))
3811 })
3812 }
3813
3814 fn visit_i16x8_sub(&mut self) -> Self::Output {
3815 self.context
3816 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3817 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8)?;
3818 Ok(TypedReg::new(WasmValType::V128, dst))
3819 })
3820 }
3821
3822 fn visit_i32x4_sub(&mut self) -> Self::Output {
3823 self.context
3824 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
3825 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I32x4)?;
3826 Ok(TypedReg::new(WasmValType::V128, dst))
3827 })
3828 }
3829
3830 fn visit_i64x2_sub(&mut self) -> Self::Output {
3831 self.context
3832 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
3833 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I64x2)?;
3834 Ok(TypedReg::new(WasmValType::V128, dst))
3835 })
3836 }
3837
3838 fn visit_i16x8_mul(&mut self) -> Self::Output {
3839 self.masm.v128_mul(&mut self.context, V128MulKind::I16x8)
3840 }
3841
3842 fn visit_i32x4_mul(&mut self) -> Self::Output {
3843 self.masm.v128_mul(&mut self.context, V128MulKind::I32x4)
3844 }
3845
3846 fn visit_i64x2_mul(&mut self) -> Self::Output {
3847 self.masm.v128_mul(&mut self.context, V128MulKind::I64x2)
3848 }
3849
3850 fn visit_i8x16_add_sat_s(&mut self) -> Self::Output {
3851 self.context
3852 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3853 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16SatS)?;
3854 Ok(TypedReg::new(WasmValType::V128, dst))
3855 })
3856 }
3857
3858 fn visit_i16x8_add_sat_s(&mut self) -> Self::Output {
3859 self.context
3860 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3861 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8SatS)?;
3862 Ok(TypedReg::new(WasmValType::V128, dst))
3863 })
3864 }
3865
3866 fn visit_i8x16_add_sat_u(&mut self) -> Self::Output {
3867 self.context
3868 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3869 masm.v128_add(dst, src, writable!(dst), V128AddKind::I8x16SatU)?;
3870 Ok(TypedReg::new(WasmValType::V128, dst))
3871 })
3872 }
3873
3874 fn visit_i16x8_add_sat_u(&mut self) -> Self::Output {
3875 self.context
3876 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3877 masm.v128_add(dst, src, writable!(dst), V128AddKind::I16x8SatU)?;
3878 Ok(TypedReg::new(WasmValType::V128, dst))
3879 })
3880 }
3881
3882 fn visit_i8x16_sub_sat_s(&mut self) -> Self::Output {
3883 self.context
3884 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3885 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16SatS)?;
3886 Ok(TypedReg::new(WasmValType::V128, dst))
3887 })
3888 }
3889
3890 fn visit_i16x8_sub_sat_s(&mut self) -> Self::Output {
3891 self.context
3892 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3893 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8SatS)?;
3894 Ok(TypedReg::new(WasmValType::V128, dst))
3895 })
3896 }
3897
3898 fn visit_i8x16_sub_sat_u(&mut self) -> Self::Output {
3899 self.context
3900 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
3901 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I8x16SatU)?;
3902 Ok(TypedReg::new(WasmValType::V128, dst))
3903 })
3904 }
3905
3906 fn visit_i16x8_sub_sat_u(&mut self) -> Self::Output {
3907 self.context
3908 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
3909 masm.v128_sub(dst, src, writable!(dst), V128SubKind::I16x8SatU)?;
3910 Ok(TypedReg::new(WasmValType::V128, dst))
3911 })
3912 }
3913
3914 fn visit_i8x16_abs(&mut self) -> Self::Output {
3915 self.context.unop(self.masm, |masm, reg| {
3916 masm.v128_abs(reg, writable!(reg), V128AbsKind::I8x16)?;
3917 Ok(TypedReg::new(WasmValType::V128, reg))
3918 })
3919 }
3920
3921 fn visit_i16x8_abs(&mut self) -> Self::Output {
3922 self.context.unop(self.masm, |masm, reg| {
3923 masm.v128_abs(reg, writable!(reg), V128AbsKind::I16x8)?;
3924 Ok(TypedReg::new(WasmValType::V128, reg))
3925 })
3926 }
3927
3928 fn visit_i32x4_abs(&mut self) -> Self::Output {
3929 self.context.unop(self.masm, |masm, reg| {
3930 masm.v128_abs(reg, writable!(reg), V128AbsKind::I32x4)?;
3931 Ok(TypedReg::new(WasmValType::V128, reg))
3932 })
3933 }
3934
3935 fn visit_i64x2_abs(&mut self) -> Self::Output {
3936 self.context.unop(self.masm, |masm, reg| {
3937 masm.v128_abs(reg, writable!(reg), V128AbsKind::I64x2)?;
3938 Ok(TypedReg::new(WasmValType::V128, reg))
3939 })
3940 }
3941
3942 fn visit_f32x4_abs(&mut self) -> Self::Output {
3943 self.context.unop(self.masm, |masm, reg| {
3944 masm.v128_abs(reg, writable!(reg), V128AbsKind::F32x4)?;
3945 Ok(TypedReg::new(WasmValType::V128, reg))
3946 })
3947 }
3948
3949 fn visit_f64x2_abs(&mut self) -> Self::Output {
3950 self.context.unop(self.masm, |masm, reg| {
3951 masm.v128_abs(reg, writable!(reg), V128AbsKind::F64x2)?;
3952 Ok(TypedReg::new(WasmValType::V128, reg))
3953 })
3954 }
3955
3956 fn visit_i8x16_neg(&mut self) -> Self::Output {
3957 self.context.unop(self.masm, |masm, op| {
3958 masm.v128_neg(writable!(op), V128NegKind::I8x16)?;
3959 Ok(TypedReg::new(WasmValType::V128, op))
3960 })
3961 }
3962
3963 fn visit_i16x8_neg(&mut self) -> Self::Output {
3964 self.context.unop(self.masm, |masm, op| {
3965 masm.v128_neg(writable!(op), V128NegKind::I16x8)?;
3966 Ok(TypedReg::new(WasmValType::V128, op))
3967 })
3968 }
3969
3970 fn visit_i32x4_neg(&mut self) -> Self::Output {
3971 self.context.unop(self.masm, |masm, op| {
3972 masm.v128_neg(writable!(op), V128NegKind::I32x4)?;
3973 Ok(TypedReg::new(WasmValType::V128, op))
3974 })
3975 }
3976
3977 fn visit_i64x2_neg(&mut self) -> Self::Output {
3978 self.context.unop(self.masm, |masm, op| {
3979 masm.v128_neg(writable!(op), V128NegKind::I64x2)?;
3980 Ok(TypedReg::new(WasmValType::V128, op))
3981 })
3982 }
3983
3984 fn visit_i8x16_shl(&mut self) -> Self::Output {
3985 self.masm
3986 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::Shl)
3987 }
3988
3989 fn visit_i16x8_shl(&mut self) -> Self::Output {
3990 self.masm
3991 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::Shl)
3992 }
3993
3994 fn visit_i32x4_shl(&mut self) -> Self::Output {
3995 self.masm
3996 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::Shl)
3997 }
3998
3999 fn visit_i64x2_shl(&mut self) -> Self::Output {
4000 self.masm
4001 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::Shl)
4002 }
4003
4004 fn visit_i8x16_shr_u(&mut self) -> Self::Output {
4005 self.masm
4006 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::ShrU)
4007 }
4008
4009 fn visit_i16x8_shr_u(&mut self) -> Self::Output {
4010 self.masm
4011 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::ShrU)
4012 }
4013
4014 fn visit_i32x4_shr_u(&mut self) -> Self::Output {
4015 self.masm
4016 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::ShrU)
4017 }
4018
4019 fn visit_i64x2_shr_u(&mut self) -> Self::Output {
4020 self.masm
4021 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::ShrU)
4022 }
4023
4024 fn visit_i8x16_shr_s(&mut self) -> Self::Output {
4025 self.masm
4026 .v128_shift(&mut self.context, OperandSize::S8, ShiftKind::ShrS)
4027 }
4028
4029 fn visit_i16x8_shr_s(&mut self) -> Self::Output {
4030 self.masm
4031 .v128_shift(&mut self.context, OperandSize::S16, ShiftKind::ShrS)
4032 }
4033
4034 fn visit_i32x4_shr_s(&mut self) -> Self::Output {
4035 self.masm
4036 .v128_shift(&mut self.context, OperandSize::S32, ShiftKind::ShrS)
4037 }
4038
4039 fn visit_i64x2_shr_s(&mut self) -> Self::Output {
4040 self.masm
4041 .v128_shift(&mut self.context, OperandSize::S64, ShiftKind::ShrS)
4042 }
4043
4044 fn visit_i16x8_q15mulr_sat_s(&mut self) -> Self::Output {
4045 self.context
4046 .binop(self.masm, OperandSize::S16, |masm, dst, src, size| {
4047 masm.v128_q15mulr_sat_s(dst, src, writable!(dst), size)?;
4048 Ok(TypedReg::v128(dst))
4049 })
4050 }
4051
4052 fn visit_i8x16_min_s(&mut self) -> Self::Output {
4053 self.context
4054 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4055 masm.v128_min(src, dst, writable!(dst), V128MinKind::I8x16S)?;
4056 Ok(TypedReg::v128(dst))
4057 })
4058 }
4059
4060 fn visit_i8x16_all_true(&mut self) -> Self::Output {
4061 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4062 masm.v128_all_true(src, writable!(dst), OperandSize::S8)
4063 })
4064 }
4065
4066 fn visit_i16x8_all_true(&mut self) -> Self::Output {
4067 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4068 masm.v128_all_true(src, writable!(dst), OperandSize::S16)
4069 })
4070 }
4071
4072 fn visit_i32x4_all_true(&mut self) -> Self::Output {
4073 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4074 masm.v128_all_true(src, writable!(dst), OperandSize::S32)
4075 })
4076 }
4077
4078 fn visit_i64x2_all_true(&mut self) -> Self::Output {
4079 self.context.v128_all_true_op(self.masm, |masm, src, dst| {
4080 masm.v128_all_true(src, writable!(dst), OperandSize::S64)
4081 })
4082 }
4083
4084 fn visit_i8x16_bitmask(&mut self) -> Self::Output {
4085 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4086 masm.v128_bitmask(src, writable!(dst), OperandSize::S8)
4087 })
4088 }
4089
4090 fn visit_i16x8_bitmask(&mut self) -> Self::Output {
4091 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4092 masm.v128_bitmask(src, writable!(dst), OperandSize::S16)
4093 })
4094 }
4095
4096 fn visit_i32x4_bitmask(&mut self) -> Self::Output {
4097 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4098 masm.v128_bitmask(src, writable!(dst), OperandSize::S32)
4099 })
4100 }
4101
4102 fn visit_i64x2_bitmask(&mut self) -> Self::Output {
4103 self.context.v128_bitmask_op(self.masm, |masm, src, dst| {
4104 masm.v128_bitmask(src, writable!(dst), OperandSize::S64)
4105 })
4106 }
4107
4108 fn visit_i32x4_trunc_sat_f32x4_s(&mut self) -> Self::Output {
4109 self.masm
4110 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF32x4S)
4111 }
4112
4113 fn visit_i32x4_trunc_sat_f32x4_u(&mut self) -> Self::Output {
4114 self.masm
4115 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF32x4U)
4116 }
4117
4118 fn visit_i32x4_trunc_sat_f64x2_s_zero(&mut self) -> Self::Output {
4119 self.masm
4120 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF64x2SZero)
4121 }
4122
4123 fn visit_i32x4_trunc_sat_f64x2_u_zero(&mut self) -> Self::Output {
4124 self.masm
4125 .v128_trunc(&mut self.context, V128TruncKind::I32x4FromF64x2UZero)
4126 }
4127
4128 fn visit_i16x8_min_s(&mut self) -> Self::Output {
4129 self.context
4130 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4131 masm.v128_min(src, dst, writable!(dst), V128MinKind::I16x8S)?;
4132 Ok(TypedReg::v128(dst))
4133 })
4134 }
4135
4136 fn visit_i32x4_dot_i16x8_s(&mut self) -> Self::Output {
4137 self.context
4138 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4139 masm.v128_dot(dst, src, writable!(dst))?;
4140 Ok(TypedReg::v128(dst))
4141 })
4142 }
4143
4144 fn visit_i8x16_popcnt(&mut self) -> Self::Output {
4145 self.masm.v128_popcnt(&mut self.context)
4146 }
4147
4148 fn visit_i8x16_avgr_u(&mut self) -> Self::Output {
4149 self.context
4150 .binop(self.masm, OperandSize::S8, |masm, dst, src, size| {
4151 masm.v128_avgr(dst, src, writable!(dst), size)?;
4152 Ok(TypedReg::v128(dst))
4153 })
4154 }
4155
4156 fn visit_i32x4_min_s(&mut self) -> Self::Output {
4157 self.context
4158 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4159 masm.v128_min(src, dst, writable!(dst), V128MinKind::I32x4S)?;
4160 Ok(TypedReg::v128(dst))
4161 })
4162 }
4163
4164 fn visit_i8x16_min_u(&mut self) -> Self::Output {
4165 self.context
4166 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4167 masm.v128_min(src, dst, writable!(dst), V128MinKind::I8x16U)?;
4168 Ok(TypedReg::v128(dst))
4169 })
4170 }
4171
4172 fn visit_i16x8_avgr_u(&mut self) -> Self::Output {
4173 self.context
4174 .binop(self.masm, OperandSize::S16, |masm, dst, src, size| {
4175 masm.v128_avgr(dst, src, writable!(dst), size)?;
4176 Ok(TypedReg::v128(dst))
4177 })
4178 }
4179
4180 fn visit_i16x8_min_u(&mut self) -> Self::Output {
4181 self.context
4182 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4183 masm.v128_min(src, dst, writable!(dst), V128MinKind::I16x8U)?;
4184 Ok(TypedReg::v128(dst))
4185 })
4186 }
4187
4188 fn visit_i32x4_min_u(&mut self) -> Self::Output {
4189 self.context
4190 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4191 masm.v128_min(src, dst, writable!(dst), V128MinKind::I32x4U)?;
4192 Ok(TypedReg::v128(dst))
4193 })
4194 }
4195
4196 fn visit_i8x16_max_s(&mut self) -> Self::Output {
4197 self.context
4198 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4199 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I8x16S)?;
4200 Ok(TypedReg::v128(dst))
4201 })
4202 }
4203
4204 fn visit_i16x8_max_s(&mut self) -> Self::Output {
4205 self.context
4206 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4207 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I16x8S)?;
4208 Ok(TypedReg::v128(dst))
4209 })
4210 }
4211
4212 fn visit_i32x4_max_s(&mut self) -> Self::Output {
4213 self.context
4214 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4215 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I32x4S)?;
4216 Ok(TypedReg::v128(dst))
4217 })
4218 }
4219
4220 fn visit_i8x16_max_u(&mut self) -> Self::Output {
4221 self.context
4222 .binop(self.masm, OperandSize::S8, |masm, dst, src, _size| {
4223 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I8x16U)?;
4224 Ok(TypedReg::v128(dst))
4225 })
4226 }
4227
4228 fn visit_i16x8_max_u(&mut self) -> Self::Output {
4229 self.context
4230 .binop(self.masm, OperandSize::S16, |masm, dst, src, _size| {
4231 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I16x8U)?;
4232 Ok(TypedReg::v128(dst))
4233 })
4234 }
4235
4236 fn visit_i32x4_max_u(&mut self) -> Self::Output {
4237 self.context
4238 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4239 masm.v128_max(src, dst, writable!(dst), V128MaxKind::I32x4U)?;
4240 Ok(TypedReg::v128(dst))
4241 })
4242 }
4243
4244 fn visit_i16x8_extmul_low_i8x16_s(&mut self) -> Self::Output {
4245 self.masm
4246 .v128_extmul(&mut self.context, V128ExtMulKind::LowI8x16S)
4247 }
4248
4249 fn visit_i32x4_extmul_low_i16x8_s(&mut self) -> Self::Output {
4250 self.masm
4251 .v128_extmul(&mut self.context, V128ExtMulKind::LowI16x8S)
4252 }
4253
4254 fn visit_i64x2_extmul_low_i32x4_s(&mut self) -> Self::Output {
4255 self.masm
4256 .v128_extmul(&mut self.context, V128ExtMulKind::LowI32x4S)
4257 }
4258
4259 fn visit_i16x8_extmul_low_i8x16_u(&mut self) -> Self::Output {
4260 self.masm
4261 .v128_extmul(&mut self.context, V128ExtMulKind::LowI8x16U)
4262 }
4263
4264 fn visit_i32x4_extmul_low_i16x8_u(&mut self) -> Self::Output {
4265 self.masm
4266 .v128_extmul(&mut self.context, V128ExtMulKind::LowI16x8U)
4267 }
4268
4269 fn visit_i64x2_extmul_low_i32x4_u(&mut self) -> Self::Output {
4270 self.masm
4271 .v128_extmul(&mut self.context, V128ExtMulKind::LowI32x4U)
4272 }
4273
4274 fn visit_i16x8_extmul_high_i8x16_u(&mut self) -> Self::Output {
4275 self.masm
4276 .v128_extmul(&mut self.context, V128ExtMulKind::HighI8x16U)
4277 }
4278
4279 fn visit_i32x4_extmul_high_i16x8_u(&mut self) -> Self::Output {
4280 self.masm
4281 .v128_extmul(&mut self.context, V128ExtMulKind::HighI16x8U)
4282 }
4283
4284 fn visit_i64x2_extmul_high_i32x4_u(&mut self) -> Self::Output {
4285 self.masm
4286 .v128_extmul(&mut self.context, V128ExtMulKind::HighI32x4U)
4287 }
4288
4289 fn visit_i16x8_extmul_high_i8x16_s(&mut self) -> Self::Output {
4290 self.masm
4291 .v128_extmul(&mut self.context, V128ExtMulKind::HighI8x16S)
4292 }
4293
4294 fn visit_i32x4_extmul_high_i16x8_s(&mut self) -> Self::Output {
4295 self.masm
4296 .v128_extmul(&mut self.context, V128ExtMulKind::HighI16x8S)
4297 }
4298
4299 fn visit_i64x2_extmul_high_i32x4_s(&mut self) -> Self::Output {
4300 self.masm
4301 .v128_extmul(&mut self.context, V128ExtMulKind::HighI32x4S)
4302 }
4303
4304 fn visit_i16x8_extadd_pairwise_i8x16_s(&mut self) -> Self::Output {
4305 self.context.unop(self.masm, |masm, op| {
4306 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I8x16S)?;
4307 Ok(TypedReg::v128(op))
4308 })
4309 }
4310
4311 fn visit_i16x8_extadd_pairwise_i8x16_u(&mut self) -> Self::Output {
4312 self.context.unop(self.masm, |masm, op| {
4313 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I8x16U)?;
4314 Ok(TypedReg::v128(op))
4315 })
4316 }
4317
4318 fn visit_i32x4_extadd_pairwise_i16x8_s(&mut self) -> Self::Output {
4319 self.context.unop(self.masm, |masm, op| {
4320 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I16x8S)?;
4321 Ok(TypedReg::v128(op))
4322 })
4323 }
4324
4325 fn visit_i32x4_extadd_pairwise_i16x8_u(&mut self) -> Self::Output {
4326 self.context.unop(self.masm, |masm, op| {
4327 masm.v128_extadd_pairwise(op, writable!(op), V128ExtAddKind::I16x8U)?;
4328 Ok(TypedReg::v128(op))
4329 })
4330 }
4331
4332 fn visit_f32x4_add(&mut self) -> Self::Output {
4333 self.context
4334 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4335 masm.v128_add(dst, src, writable!(dst), V128AddKind::F32x4)?;
4336 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S32)?;
4337 Ok(TypedReg::v128(dst))
4338 })
4339 }
4340
4341 fn visit_f64x2_add(&mut self) -> Self::Output {
4342 self.context
4343 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4344 masm.v128_add(dst, src, writable!(dst), V128AddKind::F64x2)?;
4345 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S64)?;
4346 Ok(TypedReg::v128(dst))
4347 })
4348 }
4349
4350 fn visit_f32x4_sub(&mut self) -> Self::Output {
4351 self.context
4352 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4353 masm.v128_sub(dst, src, writable!(dst), V128SubKind::F32x4)?;
4354 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S32)?;
4355 Ok(TypedReg::v128(dst))
4356 })
4357 }
4358
4359 fn visit_f64x2_sub(&mut self) -> Self::Output {
4360 self.context
4361 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4362 masm.v128_sub(dst, src, writable!(dst), V128SubKind::F64x2)?;
4363 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S64)?;
4364 Ok(TypedReg::v128(dst))
4365 })
4366 }
4367
4368 fn visit_f32x4_mul(&mut self) -> Self::Output {
4369 self.masm.v128_mul(&mut self.context, V128MulKind::F32x4)?;
4370 let result = self.context.pop_to_reg(self.masm, None)?;
4371 self.masm
4372 .maybe_canonicalize_v128_nan(writable!(result.into()), OperandSize::S32)?;
4373 self.context.stack.push(result.into());
4374 Ok(())
4375 }
4376
4377 fn visit_f64x2_mul(&mut self) -> Self::Output {
4378 self.masm.v128_mul(&mut self.context, V128MulKind::F64x2)?;
4379 let result = self.context.pop_to_reg(self.masm, None)?;
4380 self.masm
4381 .maybe_canonicalize_v128_nan(writable!(result.into()), OperandSize::S64)?;
4382 self.context.stack.push(result.into());
4383 Ok(())
4384 }
4385
4386 fn visit_f32x4_div(&mut self) -> Self::Output {
4387 self.context
4388 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4389 masm.v128_div(dst, src, writable!(dst), size)?;
4390 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S32)?;
4391 Ok(TypedReg::v128(dst))
4392 })
4393 }
4394
4395 fn visit_f64x2_div(&mut self) -> Self::Output {
4396 self.context
4397 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4398 masm.v128_div(dst, src, writable!(dst), size)?;
4399 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S64)?;
4400 Ok(TypedReg::v128(dst))
4401 })
4402 }
4403
4404 fn visit_f32x4_neg(&mut self) -> Self::Output {
4405 self.context.unop(self.masm, |masm, reg| {
4406 masm.v128_neg(writable!(reg), V128NegKind::F32x4)?;
4407 Ok(TypedReg::v128(reg))
4408 })
4409 }
4410
4411 fn visit_f32x4_ceil(&mut self) -> Self::Output {
4412 self.context.unop(self.masm, |masm, reg| {
4413 masm.v128_ceil(reg, writable!(reg), OperandSize::S32)?;
4414 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S32)?;
4415 Ok(TypedReg::v128(reg))
4416 })
4417 }
4418
4419 fn visit_f64x2_neg(&mut self) -> Self::Output {
4420 self.context.unop(self.masm, |masm, reg| {
4421 masm.v128_neg(writable!(reg), V128NegKind::F64x2)?;
4422 Ok(TypedReg::v128(reg))
4423 })
4424 }
4425
4426 fn visit_f64x2_ceil(&mut self) -> Self::Output {
4427 self.context.unop(self.masm, |masm, reg| {
4428 masm.v128_ceil(reg, writable!(reg), OperandSize::S64)?;
4429 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S64)?;
4430 Ok(TypedReg::v128(reg))
4431 })
4432 }
4433
4434 fn visit_f32x4_sqrt(&mut self) -> Self::Output {
4435 self.context.unop(self.masm, |masm, reg| {
4436 masm.v128_sqrt(reg, writable!(reg), OperandSize::S32)?;
4437 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S32)?;
4438 Ok(TypedReg::v128(reg))
4439 })
4440 }
4441
4442 fn visit_f32x4_floor(&mut self) -> Self::Output {
4443 self.context.unop(self.masm, |masm, reg| {
4444 masm.v128_floor(reg, writable!(reg), OperandSize::S32)?;
4445 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S32)?;
4446 Ok(TypedReg::v128(reg))
4447 })
4448 }
4449
4450 fn visit_f64x2_sqrt(&mut self) -> Self::Output {
4451 self.context.unop(self.masm, |masm, reg| {
4452 masm.v128_sqrt(reg, writable!(reg), OperandSize::S64)?;
4453 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S64)?;
4454 Ok(TypedReg::v128(reg))
4455 })
4456 }
4457
4458 fn visit_f64x2_floor(&mut self) -> Self::Output {
4459 self.context.unop(self.masm, |masm, reg| {
4460 masm.v128_floor(reg, writable!(reg), OperandSize::S64)?;
4461 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S64)?;
4462 Ok(TypedReg::v128(reg))
4463 })
4464 }
4465
4466 fn visit_f32x4_nearest(&mut self) -> Self::Output {
4467 self.context.unop(self.masm, |masm, reg| {
4468 masm.v128_nearest(reg, writable!(reg), OperandSize::S32)?;
4469 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S32)?;
4470 Ok(TypedReg::v128(reg))
4471 })
4472 }
4473
4474 fn visit_f64x2_nearest(&mut self) -> Self::Output {
4475 self.context.unop(self.masm, |masm, reg| {
4476 masm.v128_nearest(reg, writable!(reg), OperandSize::S64)?;
4477 masm.maybe_canonicalize_v128_nan(writable!(reg), OperandSize::S64)?;
4478 Ok(TypedReg::v128(reg))
4479 })
4480 }
4481
4482 fn visit_f32x4_trunc(&mut self) -> Self::Output {
4483 self.masm
4484 .v128_trunc(&mut self.context, V128TruncKind::F32x4)?;
4485 let result = self.context.pop_to_reg(self.masm, None)?;
4486 self.masm
4487 .maybe_canonicalize_v128_nan(writable!(result.into()), OperandSize::S32)?;
4488 self.context.stack.push(result.into());
4489 Ok(())
4490 }
4491
4492 fn visit_f64x2_trunc(&mut self) -> Self::Output {
4493 self.masm
4494 .v128_trunc(&mut self.context, V128TruncKind::F64x2)?;
4495 let result = self.context.pop_to_reg(self.masm, None)?;
4496 self.masm
4497 .maybe_canonicalize_v128_nan(writable!(result.into()), OperandSize::S64)?;
4498 self.context.stack.push(result.into());
4499 Ok(())
4500 }
4501
4502 fn visit_v128_load32_zero(&mut self, memarg: MemArg) -> Self::Output {
4503 self.emit_wasm_load(
4504 &memarg,
4505 WasmValType::V128,
4506 LoadKind::VectorZero(OperandSize::S32),
4507 )
4508 }
4509
4510 fn visit_v128_load64_zero(&mut self, memarg: MemArg) -> Self::Output {
4511 self.emit_wasm_load(
4512 &memarg,
4513 WasmValType::V128,
4514 LoadKind::VectorZero(OperandSize::S64),
4515 )
4516 }
4517
4518 fn visit_f32x4_pmin(&mut self) -> Self::Output {
4519 self.context
4520 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4521 masm.v128_pmin(dst, src, writable!(dst), size)?;
4522 Ok(TypedReg::v128(dst))
4523 })
4524 }
4525
4526 fn visit_f64x2_pmin(&mut self) -> Self::Output {
4527 self.context
4528 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4529 masm.v128_pmin(dst, src, writable!(dst), size)?;
4530 Ok(TypedReg::v128(dst))
4531 })
4532 }
4533
4534 fn visit_f32x4_pmax(&mut self) -> Self::Output {
4535 self.context
4536 .binop(self.masm, OperandSize::S32, |masm, dst, src, size| {
4537 masm.v128_pmax(dst, src, writable!(dst), size)?;
4538 Ok(TypedReg::v128(dst))
4539 })
4540 }
4541
4542 fn visit_f64x2_pmax(&mut self) -> Self::Output {
4543 self.context
4544 .binop(self.masm, OperandSize::S64, |masm, dst, src, size| {
4545 masm.v128_pmax(dst, src, writable!(dst), size)?;
4546 Ok(TypedReg::v128(dst))
4547 })
4548 }
4549
4550 fn visit_f32x4_min(&mut self) -> Self::Output {
4551 self.context
4552 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4553 masm.v128_min(dst, src, writable!(dst), V128MinKind::F32x4)?;
4554 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S32)?;
4555 Ok(TypedReg::v128(dst))
4556 })
4557 }
4558
4559 fn visit_f64x2_min(&mut self) -> Self::Output {
4560 self.context
4561 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4562 masm.v128_min(dst, src, writable!(dst), V128MinKind::F64x2)?;
4563 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S64)?;
4564 Ok(TypedReg::v128(dst))
4565 })
4566 }
4567
4568 fn visit_f32x4_max(&mut self) -> Self::Output {
4569 self.context
4570 .binop(self.masm, OperandSize::S32, |masm, dst, src, _size| {
4571 masm.v128_max(dst, src, writable!(dst), V128MaxKind::F32x4)?;
4572 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S32)?;
4573 Ok(TypedReg::v128(dst))
4574 })
4575 }
4576
4577 fn visit_f64x2_max(&mut self) -> Self::Output {
4578 self.context
4579 .binop(self.masm, OperandSize::S64, |masm, dst, src, _size| {
4580 masm.v128_max(dst, src, writable!(dst), V128MaxKind::F64x2)?;
4581 masm.maybe_canonicalize_v128_nan(writable!(dst), OperandSize::S64)?;
4582 Ok(TypedReg::v128(dst))
4583 })
4584 }
4585
4586 wasmparser::for_each_visit_simd_operator!(def_unsupported);
4587}
4588
4589impl<'a, 'translation, 'data, M> CodeGen<'a, 'translation, 'data, M, Emission>
4590where
4591 M: MacroAssembler,
4592{
4593 fn cmp_i32s(&mut self, kind: IntCmpKind) -> Result<()> {
4594 self.context.i32_binop(self.masm, |masm, dst, src, size| {
4595 masm.cmp_with_set(writable!(dst), src, kind, size)?;
4596 Ok(TypedReg::i32(dst))
4597 })
4598 }
4599
4600 fn cmp_i64s(&mut self, kind: IntCmpKind) -> Result<()> {
4601 self.context
4602 .i64_binop(self.masm, move |masm, dst, src, size| {
4603 masm.cmp_with_set(writable!(dst), src, kind, size)?;
4604 Ok(TypedReg::i32(dst)) })
4606 }
4607}
4608
4609impl TryFrom<WasmValType> for OperandSize {
4610 type Error = crate::Error;
4611 fn try_from(ty: WasmValType) -> Result<OperandSize> {
4612 let ty = match ty {
4613 WasmValType::I32 | WasmValType::F32 => OperandSize::S32,
4614 WasmValType::I64 | WasmValType::F64 => OperandSize::S64,
4615 WasmValType::V128 => OperandSize::S128,
4616 WasmValType::Ref(rt) => {
4617 match rt.heap_type {
4618 WasmHeapType::Func => OperandSize::S64,
4623 WasmHeapType::Extern => OperandSize::S64,
4624 _ => bail!(CodeGenError::unsupported_wasm_type()),
4625 }
4626 }
4627 };
4628 Ok(ty)
4629 }
4630}