// SIMD instruction translation (V128 / SIMD / relaxed SIMD)
// Split from translator_instr.mbt for maintainability
///|
/// Translate SIMD instructions
fn Translator::translate_instruction_simd(
self : Translator,
instr : @types.Instruction,
) -> Unit {
match instr {
// ============ SIMD Instructions ============
// V128 constant
V128Const(bytes) => {
let v = self.builder.v128_const(bytes)
self.push(v)
}
// Splat operations (scalar -> vector)
I8x16Splat => {
let val = self.pop()
let result = self.builder.v128_splat8(val)
self.push(result)
}
I16x8Splat => {
let val = self.pop()
let result = self.builder.v128_splat16(val)
self.push(result)
}
I32x4Splat => {
let val = self.pop()
let result = self.builder.v128_splat32(val)
self.push(result)
}
I64x2Splat => {
let val = self.pop()
let result = self.builder.v128_splat64(val)
self.push(result)
}
F32x4Splat => {
let val = self.pop()
let result = self.builder.v128_splat_f32(val)
self.push(result)
}
F64x2Splat => {
let val = self.pop()
let result = self.builder.v128_splat_f64(val)
self.push(result)
}
// Extract lane operations (vector -> scalar)
I8x16ExtractLaneS(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract8s(vec, lane)
self.push(result)
}
I8x16ExtractLaneU(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract8u(vec, lane)
self.push(result)
}
I16x8ExtractLaneS(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract16s(vec, lane)
self.push(result)
}
I16x8ExtractLaneU(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract16u(vec, lane)
self.push(result)
}
I32x4ExtractLane(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract32(vec, lane)
self.push(result)
}
I64x2ExtractLane(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract64(vec, lane)
self.push(result)
}
F32x4ExtractLane(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract_f32(vec, lane)
self.push(result)
}
F64x2ExtractLane(lane) => {
let vec = self.pop()
let result = self.builder.v128_extract_f64(vec, lane)
self.push(result)
}
// Replace lane operations (vector, scalar -> vector)
I8x16ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace8(vec, val, lane)
self.push(result)
}
I16x8ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace16(vec, val, lane)
self.push(result)
}
I32x4ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace32(vec, val, lane)
self.push(result)
}
I64x2ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace64(vec, val, lane)
self.push(result)
}
F32x4ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace_f32(vec, val, lane)
self.push(result)
}
F64x2ReplaceLane(lane) => {
let val = self.pop()
let vec = self.pop()
let result = self.builder.v128_replace_f64(vec, val, lane)
self.push(result)
}
// Shuffle and swizzle
I8x16Shuffle(lanes) => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_shuffle(a, b, lanes)
self.push(result)
}
I8x16Swizzle => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_swizzle(a, b)
self.push(result)
}
// Bitwise operations
V128Not => {
let a = self.pop()
let result = self.builder.v128_not(a)
self.push(result)
}
V128And => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_and(a, b)
self.push(result)
}
V128AndNot => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_andnot(a, b)
self.push(result)
}
V128Or => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_or(a, b)
self.push(result)
}
V128Xor => {
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_xor(a, b)
self.push(result)
}
V128Bitselect => {
let c = self.pop() // mask
let b = self.pop()
let a = self.pop()
let result = self.builder.v128_bitselect(a, b, c)
self.push(result)
}
V128AnyTrue => {
let a = self.pop()
let result = self.builder.v128_anytrue(a)
self.push(result)
}
// i8x16 operations
I8x16Eq => self.translate_simd_binary(IntCompare(Eq, I8))
I8x16Ne => self.translate_simd_binary(IntCompare(Ne, I8))
I8x16LtS => self.translate_simd_binary(IntCompare(Lt(Signed), I8))
I8x16LtU => self.translate_simd_binary(IntCompare(Lt(Unsigned), I8))
I8x16GtS => self.translate_simd_binary(IntCompare(Gt(Signed), I8))
I8x16GtU => self.translate_simd_binary(IntCompare(Gt(Unsigned), I8))
I8x16LeS => self.translate_simd_binary(IntCompare(Le(Signed), I8))
I8x16LeU => self.translate_simd_binary(IntCompare(Le(Unsigned), I8))
I8x16GeS => self.translate_simd_binary(IntCompare(Ge(Signed), I8))
I8x16GeU => self.translate_simd_binary(IntCompare(Ge(Unsigned), I8))
I8x16Abs => self.translate_simd_unary(IntUnary(Abs, I8))
I8x16Neg => self.translate_simd_unary(IntUnary(Neg, I8))
I8x16Popcnt => self.translate_simd_unary(IntUnary(Popcnt, I8))
I8x16AllTrue => self.translate_simd_to_i32(Predicate(AllTrue(I8)))
I8x16Bitmask => self.translate_simd_to_i32(Predicate(Bitmask(I8)))
I8x16NarrowI16x8S => self.translate_simd_binary(Narrow(I8, Signed))
I8x16NarrowI16x8U => self.translate_simd_binary(Narrow(I8, Unsigned))
I8x16Shl => self.translate_simd_shift(IntShift(Left, I8))
I8x16ShrS => self.translate_simd_shift(IntShift(Right(Signed), I8))
I8x16ShrU => self.translate_simd_shift(IntShift(Right(Unsigned), I8))
I8x16Add => self.translate_simd_binary(IntBinary(Add, I8))
I8x16AddSatS =>
self.translate_simd_binary(IntBinary(AddSaturating(Signed), I8))
I8x16AddSatU =>
self.translate_simd_binary(IntBinary(AddSaturating(Unsigned), I8))
I8x16Sub => self.translate_simd_binary(IntBinary(Sub, I8))
I8x16SubSatS =>
self.translate_simd_binary(IntBinary(SubSaturating(Signed), I8))
I8x16SubSatU =>
self.translate_simd_binary(IntBinary(SubSaturating(Unsigned), I8))
I8x16MinS => self.translate_simd_binary(IntBinary(Min(Signed), I8))
I8x16MinU => self.translate_simd_binary(IntBinary(Min(Unsigned), I8))
I8x16MaxS => self.translate_simd_binary(IntBinary(Max(Signed), I8))
I8x16MaxU => self.translate_simd_binary(IntBinary(Max(Unsigned), I8))
I8x16AvgrU => self.translate_simd_binary(IntBinary(AverageUnsigned, I8))
// i16x8 operations
I16x8ExtAddPairwiseI8x16S =>
self.translate_simd_unary(IntUnary(ExtAddPairwise(Signed), I16))
I16x8ExtAddPairwiseI8x16U =>
self.translate_simd_unary(IntUnary(ExtAddPairwise(Unsigned), I16))
I16x8Eq => self.translate_simd_binary(IntCompare(Eq, I16))
I16x8Ne => self.translate_simd_binary(IntCompare(Ne, I16))
I16x8LtS => self.translate_simd_binary(IntCompare(Lt(Signed), I16))
I16x8LtU => self.translate_simd_binary(IntCompare(Lt(Unsigned), I16))
I16x8GtS => self.translate_simd_binary(IntCompare(Gt(Signed), I16))
I16x8GtU => self.translate_simd_binary(IntCompare(Gt(Unsigned), I16))
I16x8LeS => self.translate_simd_binary(IntCompare(Le(Signed), I16))
I16x8LeU => self.translate_simd_binary(IntCompare(Le(Unsigned), I16))
I16x8GeS => self.translate_simd_binary(IntCompare(Ge(Signed), I16))
I16x8GeU => self.translate_simd_binary(IntCompare(Ge(Unsigned), I16))
I16x8Abs => self.translate_simd_unary(IntUnary(Abs, I16))
I16x8Neg => self.translate_simd_unary(IntUnary(Neg, I16))
I16x8Q15MulrSatS =>
self.translate_simd_binary(IntBinary(Q15MulrSaturating, I16))
I16x8AllTrue => self.translate_simd_to_i32(Predicate(AllTrue(I16)))
I16x8Bitmask => self.translate_simd_to_i32(Predicate(Bitmask(I16)))
I16x8NarrowI32x4S => self.translate_simd_binary(Narrow(I16, Signed))
I16x8NarrowI32x4U => self.translate_simd_binary(Narrow(I16, Unsigned))
I16x8ExtendLowI8x16S =>
self.translate_simd_unary(IntUnary(Extend(Low, Signed), I16))
I16x8ExtendHighI8x16S =>
self.translate_simd_unary(IntUnary(Extend(High, Signed), I16))
I16x8ExtendLowI8x16U =>
self.translate_simd_unary(IntUnary(Extend(Low, Unsigned), I16))
I16x8ExtendHighI8x16U =>
self.translate_simd_unary(IntUnary(Extend(High, Unsigned), I16))
I16x8Shl => self.translate_simd_shift(IntShift(Left, I16))
I16x8ShrS => self.translate_simd_shift(IntShift(Right(Signed), I16))
I16x8ShrU => self.translate_simd_shift(IntShift(Right(Unsigned), I16))
I16x8Add => self.translate_simd_binary(IntBinary(Add, I16))
I16x8AddSatS =>
self.translate_simd_binary(IntBinary(AddSaturating(Signed), I16))
I16x8AddSatU =>
self.translate_simd_binary(IntBinary(AddSaturating(Unsigned), I16))
I16x8Sub => self.translate_simd_binary(IntBinary(Sub, I16))
I16x8SubSatS =>
self.translate_simd_binary(IntBinary(SubSaturating(Signed), I16))
I16x8SubSatU =>
self.translate_simd_binary(IntBinary(SubSaturating(Unsigned), I16))
I16x8Mul => self.translate_simd_binary(IntBinary(Mul, I16))
I16x8MinS => self.translate_simd_binary(IntBinary(Min(Signed), I16))
I16x8MinU => self.translate_simd_binary(IntBinary(Min(Unsigned), I16))
I16x8MaxS => self.translate_simd_binary(IntBinary(Max(Signed), I16))
I16x8MaxU => self.translate_simd_binary(IntBinary(Max(Unsigned), I16))
I16x8AvgrU => self.translate_simd_binary(IntBinary(AverageUnsigned, I16))
I16x8ExtMulLowI8x16S =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Signed), I16))
I16x8ExtMulHighI8x16S =>
self.translate_simd_binary(IntBinary(ExtMul(High, Signed), I16))
I16x8ExtMulLowI8x16U =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Unsigned), I16))
I16x8ExtMulHighI8x16U =>
self.translate_simd_binary(IntBinary(ExtMul(High, Unsigned), I16))
// i32x4 operations
I32x4ExtAddPairwiseI16x8S =>
self.translate_simd_unary(IntUnary(ExtAddPairwise(Signed), I32))
I32x4ExtAddPairwiseI16x8U =>
self.translate_simd_unary(IntUnary(ExtAddPairwise(Unsigned), I32))
I32x4Eq => self.translate_simd_binary(IntCompare(Eq, I32))
I32x4Ne => self.translate_simd_binary(IntCompare(Ne, I32))
I32x4LtS => self.translate_simd_binary(IntCompare(Lt(Signed), I32))
I32x4LtU => self.translate_simd_binary(IntCompare(Lt(Unsigned), I32))
I32x4GtS => self.translate_simd_binary(IntCompare(Gt(Signed), I32))
I32x4GtU => self.translate_simd_binary(IntCompare(Gt(Unsigned), I32))
I32x4LeS => self.translate_simd_binary(IntCompare(Le(Signed), I32))
I32x4LeU => self.translate_simd_binary(IntCompare(Le(Unsigned), I32))
I32x4GeS => self.translate_simd_binary(IntCompare(Ge(Signed), I32))
I32x4GeU => self.translate_simd_binary(IntCompare(Ge(Unsigned), I32))
I32x4Abs => self.translate_simd_unary(IntUnary(Abs, I32))
I32x4Neg => self.translate_simd_unary(IntUnary(Neg, I32))
I32x4AllTrue => self.translate_simd_to_i32(Predicate(AllTrue(I32)))
I32x4Bitmask => self.translate_simd_to_i32(Predicate(Bitmask(I32)))
I32x4ExtendLowI16x8S =>
self.translate_simd_unary(IntUnary(Extend(Low, Signed), I32))
I32x4ExtendHighI16x8S =>
self.translate_simd_unary(IntUnary(Extend(High, Signed), I32))
I32x4ExtendLowI16x8U =>
self.translate_simd_unary(IntUnary(Extend(Low, Unsigned), I32))
I32x4ExtendHighI16x8U =>
self.translate_simd_unary(IntUnary(Extend(High, Unsigned), I32))
I32x4Shl => self.translate_simd_shift(IntShift(Left, I32))
I32x4ShrS => self.translate_simd_shift(IntShift(Right(Signed), I32))
I32x4ShrU => self.translate_simd_shift(IntShift(Right(Unsigned), I32))
I32x4Add => self.translate_simd_binary(IntBinary(Add, I32))
I32x4Sub => self.translate_simd_binary(IntBinary(Sub, I32))
I32x4Mul => self.translate_simd_binary(IntBinary(Mul, I32))
I32x4MinS => self.translate_simd_binary(IntBinary(Min(Signed), I32))
I32x4MinU => self.translate_simd_binary(IntBinary(Min(Unsigned), I32))
I32x4MaxS => self.translate_simd_binary(IntBinary(Max(Signed), I32))
I32x4MaxU => self.translate_simd_binary(IntBinary(Max(Unsigned), I32))
I32x4DotI16x8S =>
self.translate_simd_binary(IntBinary(Dot16To32Signed, I32))
I32x4ExtMulLowI16x8S =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Signed), I32))
I32x4ExtMulHighI16x8S =>
self.translate_simd_binary(IntBinary(ExtMul(High, Signed), I32))
I32x4ExtMulLowI16x8U =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Unsigned), I32))
I32x4ExtMulHighI16x8U =>
self.translate_simd_binary(IntBinary(ExtMul(High, Unsigned), I32))
// i64x2 operations
I64x2Eq => self.translate_simd_binary(IntCompare(Eq, I64))
I64x2Ne => self.translate_simd_binary(IntCompare(Ne, I64))
I64x2LtS => self.translate_simd_binary(IntCompare(Lt(Signed), I64))
I64x2GtS => self.translate_simd_binary(IntCompare(Gt(Signed), I64))
I64x2LeS => self.translate_simd_binary(IntCompare(Le(Signed), I64))
I64x2GeS => self.translate_simd_binary(IntCompare(Ge(Signed), I64))
I64x2Abs => self.translate_simd_unary(IntUnary(Abs, I64))
I64x2Neg => self.translate_simd_unary(IntUnary(Neg, I64))
I64x2AllTrue => self.translate_simd_to_i32(Predicate(AllTrue(I64)))
I64x2Bitmask => self.translate_simd_to_i32(Predicate(Bitmask(I64)))
I64x2ExtendLowI32x4S =>
self.translate_simd_unary(IntUnary(Extend(Low, Signed), I64))
I64x2ExtendHighI32x4S =>
self.translate_simd_unary(IntUnary(Extend(High, Signed), I64))
I64x2ExtendLowI32x4U =>
self.translate_simd_unary(IntUnary(Extend(Low, Unsigned), I64))
I64x2ExtendHighI32x4U =>
self.translate_simd_unary(IntUnary(Extend(High, Unsigned), I64))
I64x2Shl => self.translate_simd_shift(IntShift(Left, I64))
I64x2ShrS => self.translate_simd_shift(IntShift(Right(Signed), I64))
I64x2ShrU => self.translate_simd_shift(IntShift(Right(Unsigned), I64))
I64x2Add => self.translate_simd_binary(IntBinary(Add, I64))
I64x2Sub => self.translate_simd_binary(IntBinary(Sub, I64))
I64x2Mul => self.translate_simd_binary(IntBinary(Mul, I64))
I64x2ExtMulLowI32x4S =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Signed), I64))
I64x2ExtMulHighI32x4S =>
self.translate_simd_binary(IntBinary(ExtMul(High, Signed), I64))
I64x2ExtMulLowI32x4U =>
self.translate_simd_binary(IntBinary(ExtMul(Low, Unsigned), I64))
I64x2ExtMulHighI32x4U =>
self.translate_simd_binary(IntBinary(ExtMul(High, Unsigned), I64))
// f32x4 operations
F32x4Eq => self.translate_simd_binary(FloatCompare(Eq, F32))
F32x4Ne => self.translate_simd_binary(FloatCompare(Ne, F32))
F32x4Lt => self.translate_simd_binary(FloatCompare(Lt, F32))
F32x4Gt => self.translate_simd_binary(FloatCompare(Gt, F32))
F32x4Le => self.translate_simd_binary(FloatCompare(Le, F32))
F32x4Ge => self.translate_simd_binary(FloatCompare(Ge, F32))
F32x4Ceil => self.translate_simd_unary(FloatUnary(Ceil, F32))
F32x4Floor => self.translate_simd_unary(FloatUnary(Floor, F32))
F32x4Trunc => self.translate_simd_unary(FloatUnary(Trunc, F32))
F32x4Nearest => self.translate_simd_unary(FloatUnary(Nearest, F32))
F32x4Abs => self.translate_simd_unary(FloatUnary(Abs, F32))
F32x4Neg => self.translate_simd_unary(FloatUnary(Neg, F32))
F32x4Sqrt => self.translate_simd_unary(FloatUnary(Sqrt, F32))
F32x4Add => self.translate_simd_binary(FloatBinary(Add, F32))
F32x4Sub => self.translate_simd_binary(FloatBinary(Sub, F32))
F32x4Mul => self.translate_simd_binary(FloatBinary(Mul, F32))
F32x4Div => self.translate_simd_binary(FloatBinary(Div, F32))
F32x4Min => self.translate_simd_binary(FloatBinary(Min, F32))
F32x4Max => self.translate_simd_binary(FloatBinary(Max, F32))
F32x4Pmin => self.translate_simd_binary(FloatBinary(PseudoMin, F32))
F32x4Pmax => self.translate_simd_binary(FloatBinary(PseudoMax, F32))
// f64x2 operations
F64x2Eq => self.translate_simd_binary(FloatCompare(Eq, F64))
F64x2Ne => self.translate_simd_binary(FloatCompare(Ne, F64))
F64x2Lt => self.translate_simd_binary(FloatCompare(Lt, F64))
F64x2Gt => self.translate_simd_binary(FloatCompare(Gt, F64))
F64x2Le => self.translate_simd_binary(FloatCompare(Le, F64))
F64x2Ge => self.translate_simd_binary(FloatCompare(Ge, F64))
F64x2Ceil => self.translate_simd_unary(FloatUnary(Ceil, F64))
F64x2Floor => self.translate_simd_unary(FloatUnary(Floor, F64))
F64x2Trunc => self.translate_simd_unary(FloatUnary(Trunc, F64))
F64x2Nearest => self.translate_simd_unary(FloatUnary(Nearest, F64))
F64x2Abs => self.translate_simd_unary(FloatUnary(Abs, F64))
F64x2Neg => self.translate_simd_unary(FloatUnary(Neg, F64))
F64x2Sqrt => self.translate_simd_unary(FloatUnary(Sqrt, F64))
F64x2Add => self.translate_simd_binary(FloatBinary(Add, F64))
F64x2Sub => self.translate_simd_binary(FloatBinary(Sub, F64))
F64x2Mul => self.translate_simd_binary(FloatBinary(Mul, F64))
F64x2Div => self.translate_simd_binary(FloatBinary(Div, F64))
F64x2Min => self.translate_simd_binary(FloatBinary(Min, F64))
F64x2Max => self.translate_simd_binary(FloatBinary(Max, F64))
F64x2Pmin => self.translate_simd_binary(FloatBinary(PseudoMin, F64))
F64x2Pmax => self.translate_simd_binary(FloatBinary(PseudoMax, F64))
// SIMD conversions
I32x4TruncSatF32x4S =>
self.translate_simd_unary(Convert(TruncSatF32ToI32(Signed)))
I32x4TruncSatF32x4U =>
self.translate_simd_unary(Convert(TruncSatF32ToI32(Unsigned)))
F32x4ConvertI32x4S =>
self.translate_simd_unary(Convert(ConvertI32ToF32(Signed)))
F32x4ConvertI32x4U =>
self.translate_simd_unary(Convert(ConvertI32ToF32(Unsigned)))
I32x4TruncSatF64x2SZero =>
self.translate_simd_unary(Convert(TruncSatF64ToI32Zero(Signed)))
I32x4TruncSatF64x2UZero =>
self.translate_simd_unary(Convert(TruncSatF64ToI32Zero(Unsigned)))
F64x2ConvertLowI32x4S =>
self.translate_simd_unary(Convert(ConvertLowI32ToF64(Signed)))
F64x2ConvertLowI32x4U =>
self.translate_simd_unary(Convert(ConvertLowI32ToF64(Unsigned)))
F32x4DemoteF64x2Zero =>
self.translate_simd_unary(Convert(DemoteF64ToF32Zero))
F64x2PromoteLowF32x4 =>
self.translate_simd_unary(Convert(PromoteLowF32ToF64))
// V128 load/store operations
V128Load(memidx, _, offset) => {
let addr = self.pop()
let result = self.func_env.translate_memory_load(
self.builder,
self.vmctx,
memidx,
V128,
addr,
offset,
)
self.push(result)
}
V128Store(memidx, _, offset) => {
let value = self.pop()
let addr = self.pop()
self.func_env.translate_memory_store(
self.builder,
self.vmctx,
memidx,
V128,
addr,
value,
offset,
)
}
V128Load8x8S(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I8, Signed),
)
self.push(result)
}
V128Load8x8U(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I8, Unsigned),
)
self.push(result)
}
V128Load16x4S(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I16, Signed),
)
self.push(result)
}
V128Load16x4U(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I16, Unsigned),
)
self.push(result)
}
V128Load32x2S(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I32, Signed),
)
self.push(result)
}
V128Load32x2U(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadExtend(I32, Unsigned),
)
self.push(result)
}
V128Load8Splat(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(memidx, offset, addr, LoadSplat(I8))
self.push(result)
}
V128Load16Splat(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadSplat(I16),
)
self.push(result)
}
V128Load32Splat(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadSplat(I32),
)
self.push(result)
}
V128Load64Splat(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(
memidx,
offset,
addr,
LoadSplat(I64),
)
self.push(result)
}
V128Load32Zero(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(memidx, offset, addr, LoadZero(I32))
self.push(result)
}
V128Load64Zero(memidx, _, offset) => {
let addr = self.pop()
let result = self.translate_simd_load(memidx, offset, addr, LoadZero(I64))
self.push(result)
}
V128Load8Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
let result = self.translate_simd_load_lane(
memidx,
offset,
addr,
vec,
LoadLane(I8, lane),
)
self.push(result)
}
V128Load16Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
let result = self.translate_simd_load_lane(
memidx,
offset,
addr,
vec,
LoadLane(I16, lane),
)
self.push(result)
}
V128Load32Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
let result = self.translate_simd_load_lane(
memidx,
offset,
addr,
vec,
LoadLane(I32, lane),
)
self.push(result)
}
V128Load64Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
let result = self.translate_simd_load_lane(
memidx,
offset,
addr,
vec,
LoadLane(I64, lane),
)
self.push(result)
}
V128Store8Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
self.translate_simd_store_lane(
memidx,
offset,
addr,
vec,
StoreLane(I8, lane),
)
}
V128Store16Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
self.translate_simd_store_lane(
memidx,
offset,
addr,
vec,
StoreLane(I16, lane),
)
}
V128Store32Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
self.translate_simd_store_lane(
memidx,
offset,
addr,
vec,
StoreLane(I32, lane),
)
}
V128Store64Lane(memidx, _, offset, lane) => {
let vec = self.pop()
let addr = self.pop()
self.translate_simd_store_lane(
memidx,
offset,
addr,
vec,
StoreLane(I64, lane),
)
}
// Relaxed SIMD instructions
I8x16RelaxedSwizzle => {
// Same as regular swizzle on ARM
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(V128, Vector(Relaxed(Swizzle)), [a, b])
self.push(result)
}
I32x4RelaxedTruncF32x4S =>
self.translate_simd_unary(Relaxed(TruncF32ToI32(Signed)))
I32x4RelaxedTruncF32x4U =>
self.translate_simd_unary(Relaxed(TruncF32ToI32(Unsigned)))
I32x4RelaxedTruncF64x2SZero =>
self.translate_simd_unary(Relaxed(TruncF64ToI32Zero(Signed)))
I32x4RelaxedTruncF64x2UZero =>
self.translate_simd_unary(Relaxed(TruncF64ToI32Zero(Unsigned)))
F32x4RelaxedMadd => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(Fma(F32, Add))),
[a, b, c],
)
self.push(result)
}
F32x4RelaxedNmadd => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(Fma(F32, NegatedAdd))),
[a, b, c],
)
self.push(result)
}
F64x2RelaxedMadd => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(Fma(F64, Add))),
[a, b, c],
)
self.push(result)
}
F64x2RelaxedNmadd => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(Fma(F64, NegatedAdd))),
[a, b, c],
)
self.push(result)
}
I8x16RelaxedLaneselect => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(LaneSelect(I8))),
[a, b, c],
)
self.push(result)
}
I16x8RelaxedLaneselect => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(LaneSelect(I16))),
[a, b, c],
)
self.push(result)
}
I32x4RelaxedLaneselect => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(LaneSelect(I32))),
[a, b, c],
)
self.push(result)
}
I64x2RelaxedLaneselect => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(LaneSelect(I64))),
[a, b, c],
)
self.push(result)
}
F32x4RelaxedMin => self.translate_simd_binary(Relaxed(Min(F32)))
F32x4RelaxedMax => self.translate_simd_binary(Relaxed(Max(F32)))
F64x2RelaxedMin => self.translate_simd_binary(Relaxed(Min(F64)))
F64x2RelaxedMax => self.translate_simd_binary(Relaxed(Max(F64)))
I16x8RelaxedQ15mulrS => self.translate_simd_binary(Relaxed(Q15MulrSigned))
I16x8RelaxedDotI8x16I7x16S =>
self.translate_simd_binary(Relaxed(Dot8To16Signed))
I32x4RelaxedDotI8x16I7x16AddS => {
let c = self.pop()
let b = self.pop()
let a = self.pop()
let result = self.builder.emit_inst(
V128,
Vector(Relaxed(Dot8To32AddSigned)),
[a, b, c],
)
self.push(result)
}
_ => abort("non-SIMD instruction routed to SIMD translator: \{instr}")
}
}