@@ -4472,6 +4472,86 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
44724472 }
44734473 }
44744474 }
4475+ Opcode :: ExtendedPairwiseAddSigned | Opcode :: ExtendedPairwiseAddUnsigned => {
4476+
4477+ // Extended pairwise addition instructions computes extended sums within adjacent
4478+ // pairs of lanes of a SIMD vector, producing a SIMD vector with half as many lanes.
4479+ // Instruction sequences taken from instruction SPEC PR https://github.com/WebAssembly/simd/pull/380
4480+
4481+ let input_ty = ctx. input_ty ( insn, 0 ) ;
4482+ let output_ty = ctx. output_ty ( insn, 0 ) ;
4483+ let src = put_input_in_reg ( ctx, inputs[ 0 ] ) ;
4484+ let dst = get_output_reg ( ctx, outputs[ 0 ] ) . only_reg ( ) . unwrap ( ) ;
4485+ match op {
4486+ Opcode :: ExtendedPairwiseAddSigned => match ( input_ty, output_ty) {
4487+ ( types:: I8X16 , types:: I16X8 ) => {
4488+ static MUL_CONST : [ u8 ; 16 ] = [ 0x01 ; 16 ] ;
4489+ let mul_const = ctx. use_constant ( VCodeConstantData :: WellKnown ( & MUL_CONST ) ) ;
4490+ let mul_const_reg = ctx. alloc_tmp ( types:: I8X16 ) . only_reg ( ) . unwrap ( ) ;
4491+ ctx. emit ( Inst :: xmm_load_const ( mul_const, mul_const_reg, types:: I8X16 ) ) ;
4492+ ctx. emit ( Inst :: xmm_mov (
4493+ SseOpcode :: Movdqa ,
4494+ RegMem :: reg ( mul_const_reg. to_reg ( ) ) ,
4495+ dst,
4496+ ) ) ;
4497+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Pmaddubsw , RegMem :: reg ( src) , dst) ) ;
4498+ } ,
4499+ ( types:: I16X8 , types:: I32X4 ) => {
4500+ static MUL_CONST : [ u8 ; 16 ] = [ 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 ] ;
4501+ let mul_const = ctx. use_constant ( VCodeConstantData :: WellKnown ( & MUL_CONST ) ) ;
4502+ let mul_const_reg = ctx. alloc_tmp ( types:: I16X8 ) . only_reg ( ) . unwrap ( ) ;
4503+ ctx. emit ( Inst :: xmm_load_const ( mul_const, mul_const_reg, types:: I16X8 ) ) ;
4504+ ctx. emit ( Inst :: xmm_mov (
4505+ SseOpcode :: Movdqa ,
4506+ RegMem :: reg ( src) ,
4507+ dst,
4508+ ) ) ;
4509+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Pmaddwd , RegMem :: reg ( mul_const_reg. to_reg ( ) ) , dst) ) ;
4510+ } ,
4511+ _ => unreachable ! ( "Type pattern not supported {:?}-{:?} not supported for {:?}." , input_ty, output_ty, op) ,
4512+ } ,
4513+ Opcode :: ExtendedPairwiseAddUnsigned => match ( input_ty, output_ty) {
4514+ ( types:: I8X16 , types:: I16X8 ) => {
4515+ static MUL_CONST : [ u8 ; 16 ] = [ 0x01 ; 16 ] ;
4516+ let mul_const = ctx. use_constant ( VCodeConstantData :: WellKnown ( & MUL_CONST ) ) ;
4517+ let mul_const_reg = ctx. alloc_tmp ( types:: I8X16 ) . only_reg ( ) . unwrap ( ) ;
4518+ ctx. emit ( Inst :: xmm_load_const ( mul_const, mul_const_reg, types:: I8X16 ) ) ;
4519+ ctx. emit ( Inst :: xmm_mov (
4520+ SseOpcode :: Movdqa ,
4521+ RegMem :: reg ( src) ,
4522+ dst,
4523+ ) ) ;
4524+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Pmaddubsw , RegMem :: reg ( mul_const_reg. to_reg ( ) ) , dst) ) ;
4525+ } ,
4526+ ( types:: I16X8 , types:: I32X4 ) => {
4527+ static PXOR_CONST : [ u8 ; 16 ] = [ 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 , 0x00 , 0x80 ] ;
4528+ let pxor_const = ctx. use_constant ( VCodeConstantData :: WellKnown ( & PXOR_CONST ) ) ;
4529+ let pxor_const_reg = ctx. alloc_tmp ( types:: I16X8 ) . only_reg ( ) . unwrap ( ) ;
4530+ ctx. emit ( Inst :: xmm_load_const ( pxor_const, pxor_const_reg, types:: I16X8 ) ) ;
4531+ ctx. emit ( Inst :: xmm_mov (
4532+ SseOpcode :: Movdqa ,
4533+ RegMem :: reg ( src) ,
4534+ dst,
4535+ ) ) ;
4536+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Pxor , RegMem :: reg ( pxor_const_reg. to_reg ( ) ) , dst) ) ;
4537+
4538+ static MADD_CONST : [ u8 ; 16 ] = [ 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 , 0x01 , 0x00 ] ;
4539+ let madd_const = ctx. use_constant ( VCodeConstantData :: WellKnown ( & MADD_CONST ) ) ;
4540+ let madd_const_reg = ctx. alloc_tmp ( types:: I8X16 ) . only_reg ( ) . unwrap ( ) ;
4541+ ctx. emit ( Inst :: xmm_load_const ( madd_const, madd_const_reg, types:: I16X8 ) ) ;
4542+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Pmaddwd , RegMem :: reg ( madd_const_reg. to_reg ( ) ) , dst) ) ;
4543+
4544+ static ADDD_CONST2 : [ u8 ; 16 ] = [ 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 ] ;
4545+ let addd_const2 = ctx. use_constant ( VCodeConstantData :: WellKnown ( & ADDD_CONST2 ) ) ;
4546+ let addd_const2_reg = ctx. alloc_tmp ( types:: I8X16 ) . only_reg ( ) . unwrap ( ) ;
4547+ ctx. emit ( Inst :: xmm_load_const ( addd_const2, addd_const2_reg, types:: I16X8 ) ) ;
4548+ ctx. emit ( Inst :: xmm_rm_r ( SseOpcode :: Paddd , RegMem :: reg ( addd_const2_reg. to_reg ( ) ) , dst) ) ;
4549+ } ,
4550+ _ => unreachable ! ( "Type pattern not supported {:?}-{:?} not supported for {:?}." , input_ty, output_ty, op) ,
4551+ } ,
4552+ _ => unreachable ! ( "{:?} not supported." , op) ,
4553+ }
4554+ }
44754555 Opcode :: UwidenHigh | Opcode :: UwidenLow | Opcode :: SwidenHigh | Opcode :: SwidenLow => {
44764556 let input_ty = ctx. input_ty ( insn, 0 ) ;
44774557 let output_ty = ctx. output_ty ( insn, 0 ) ;
0 commit comments