@@ -122,6 +122,8 @@ unsafe extern "unadjusted" {
122122 #[ link_name = "llvm.s390.vsbiq" ] fn vsbiq ( a : u128 , b : u128 , c : u128 ) -> u128 ;
123123 #[ link_name = "llvm.s390.vsbcbiq" ] fn vsbcbiq ( a : u128 , b : u128 , c : u128 ) -> u128 ;
124124
125+ #[ link_name = "llvm.s390.vacq" ] fn vacq ( a : u128 , b : u128 , c : u128 ) -> u128 ;
126+
125127 #[ link_name = "llvm.s390.vscbib" ] fn vscbib ( a : vector_unsigned_char , b : vector_unsigned_char ) -> vector_unsigned_char ;
126128 #[ link_name = "llvm.s390.vscbih" ] fn vscbih ( a : vector_unsigned_short , b : vector_unsigned_short ) -> vector_unsigned_short ;
127129 #[ link_name = "llvm.s390.vscbif" ] fn vscbif ( a : vector_unsigned_int , b : vector_unsigned_int ) -> vector_unsigned_int ;
@@ -3085,6 +3087,24 @@ pub unsafe fn vec_sum4<T: sealed::VectorSum4>(a: T, b: T) -> vector_unsigned_int
30853087 a. vec_sum4 ( b)
30863088}
30873089
3090+ /// Vector Addition unsigned 128-bits
3091+ ///
3092+ /// Adds unsigned quadword values.
3093+ ///
3094+ /// This function operates on the vectors as 128-bit unsigned integers. It returns low 128 bits of a + b.
3095+ #[ inline]
3096+ #[ target_feature( enable = "vector" ) ]
3097+ #[ unstable( feature = "stdarch_s390x" , issue = "135681" ) ]
3098+ #[ cfg_attr( test, assert_instr( vaq) ) ]
3099+ pub unsafe fn vec_add_u128 (
3100+ a : vector_unsigned_char ,
3101+ b : vector_unsigned_char ,
3102+ ) -> vector_unsigned_char {
3103+ let a: u128 = transmute ( a) ;
3104+ let b: u128 = transmute ( b) ;
3105+ transmute ( a. wrapping_add ( b) )
3106+ }
3107+
30883108/// Vector Subtract unsigned 128-bits
30893109///
30903110/// Subtracts unsigned quadword values.
@@ -3130,9 +3150,63 @@ pub unsafe fn vec_subc_u128(
31303150 a : vector_unsigned_char ,
31313151 b : vector_unsigned_char ,
31323152) -> vector_unsigned_char {
3153+ // FIXME(llvm) sadly this does not work https://github.com/llvm/llvm-project/issues/129608
3154+ // let a: u128 = transmute(a);
3155+ // let b: u128 = transmute(b);
3156+ // transmute(!a.overflowing_sub(b).1 as u128)
31333157 transmute ( vscbiq ( transmute ( a) , transmute ( b) ) )
31343158}
31353159
3160+ /// Vector Add Compute Carryout unsigned 128-bits
3161+ #[ inline]
3162+ #[ target_feature( enable = "vector" ) ]
3163+ #[ unstable( feature = "stdarch_s390x" , issue = "135681" ) ]
3164+ #[ cfg_attr( test, assert_instr( vaccq) ) ]
3165+ pub unsafe fn vec_addc_u128 (
3166+ a : vector_unsigned_char ,
3167+ b : vector_unsigned_char ,
3168+ ) -> vector_unsigned_char {
3169+ let a: u128 = transmute ( a) ;
3170+ let b: u128 = transmute ( b) ;
3171+ transmute ( a. overflowing_add ( b) . 1 as u128 )
3172+ }
3173+
3174+ /// Vector Add With Carry unsigned 128-bits
3175+ #[ inline]
3176+ #[ target_feature( enable = "vector" ) ]
3177+ #[ unstable( feature = "stdarch_s390x" , issue = "135681" ) ]
3178+ #[ cfg_attr( test, assert_instr( vacq) ) ]
3179+ pub unsafe fn vec_adde_u128 (
3180+ a : vector_unsigned_char ,
3181+ b : vector_unsigned_char ,
3182+ c : vector_unsigned_char ,
3183+ ) -> vector_unsigned_char {
3184+ let a: u128 = transmute ( a) ;
3185+ let b: u128 = transmute ( b) ;
3186+ let c: u128 = transmute ( c) ;
3187+ // FIXME(llvm) sadly this does not work
3188+ // let (d, _carry) = a.carrying_add(b, c & 1 != 0);
3189+ // transmute(d)
3190+ transmute ( vacq ( a, b, c) )
3191+ }
3192+
3193+ /// Vector Add With Carry Compute Carry unsigned 128-bits
3194+ #[ inline]
3195+ #[ target_feature( enable = "vector" ) ]
3196+ #[ unstable( feature = "stdarch_s390x" , issue = "135681" ) ]
3197+ #[ cfg_attr( test, assert_instr( vacccq) ) ]
3198+ pub unsafe fn vec_addec_u128 (
3199+ a : vector_unsigned_char ,
3200+ b : vector_unsigned_char ,
3201+ c : vector_unsigned_char ,
3202+ ) -> vector_unsigned_char {
3203+ let a: u128 = transmute ( a) ;
3204+ let b: u128 = transmute ( b) ;
3205+ let c: u128 = transmute ( c) ;
3206+ let ( _d, carry) = a. carrying_add ( b, c & 1 != 0 ) ;
3207+ transmute ( carry as u128 )
3208+ }
3209+
31363210/// Subtracts unsigned quadword values with carry bit from a previous operation.
31373211///
31383212/// This function operates on the vectors as 128-bit unsigned integers. It returns a vector containing the result of subtracting of b from a,
@@ -4246,4 +4320,50 @@ mod tests {
42464320 [ 5 , 6 , 7 , 8 ] ,
42474321 [ 0 , 12 , 0 , 0 ]
42484322 }
4323+
4324+ test_vec_2 ! { test_vec_add_u128, vec_add_u128, u8x16,
4325+ [ 0x01 , 0x05 , 0x0F , 0x1A , 0x2F , 0x3F , 0x50 , 0x65 ,
4326+ 0x7A , 0x8F , 0x9A , 0xAD , 0xB0 , 0xC3 , 0xD5 , 0xE8 ] ,
4327+ [ 0xF0 , 0xEF , 0xC3 , 0xB1 , 0x92 , 0x71 , 0x5A , 0x43 ,
4328+ 0x3B , 0x29 , 0x13 , 0x04 , 0xD7 , 0xA1 , 0x8C , 0x76 ] ,
4329+ [ 0xF1 , 0xF4 , 0xD2 , 0xCB , 0xC1 , 0xB0 , 0xAA , 0xA8 , 0xB5 , 0xB8 , 0xAD , 0xB2 , 0x88 , 0x65 , 0x62 , 0x5E ]
4330+ }
4331+
4332+ #[ simd_test( enable = "vector" ) ]
4333+ fn test_vec_addc_u128 ( ) {
4334+ unsafe {
4335+ let a = u128:: MAX ;
4336+ let b = 1u128 ;
4337+
4338+ let d: u128 = transmute ( vec_addc_u128 ( transmute ( a) , transmute ( b) ) ) ;
4339+ assert ! ( a. checked_add( b) . is_none( ) ) ;
4340+ assert_eq ! ( d, 1 ) ;
4341+
4342+ let a = 1u128 ;
4343+ let b = 1u128 ;
4344+
4345+ let d: u128 = transmute ( vec_addc_u128 ( transmute ( a) , transmute ( b) ) ) ;
4346+ assert ! ( a. checked_add( b) . is_some( ) ) ;
4347+ assert_eq ! ( d, 0 ) ;
4348+ }
4349+ }
4350+
4351+ #[ simd_test( enable = "vector" ) ]
4352+ fn test_vec_subc_u128 ( ) {
4353+ unsafe {
4354+ let a = 0u128 ;
4355+ let b = 1u128 ;
4356+
4357+ let d: u128 = transmute ( vec_subc_u128 ( transmute ( a) , transmute ( b) ) ) ;
4358+ assert ! ( a. checked_sub( b) . is_none( ) ) ;
4359+ assert_eq ! ( d, 0 ) ;
4360+
4361+ let a = 1u128 ;
4362+ let b = 1u128 ;
4363+
4364+ let d: u128 = transmute ( vec_subc_u128 ( transmute ( a) , transmute ( b) ) ) ;
4365+ assert ! ( a. checked_sub( b) . is_some( ) ) ;
4366+ assert_eq ! ( d, 1 ) ;
4367+ }
4368+ }
42494369}
0 commit comments