@@ -2112,6 +2112,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21122112 }
21132113#elif defined(TARGET_S390X )
21142114 if (type_enum_is_float (arg0_type )) {
2115+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2116+ return NULL ;
21152117 return emit_simd_ins_for_sig (cfg , klass , arg0_type == MONO_TYPE_R8 ? OP_S390_VFLPDB : OP_S390_VFLPSB , -1 , arg0_type , fsig , args );
21162118 } else {
21172119 return emit_simd_ins_for_sig (cfg , klass , OP_VECTOR_IABS , -1 , arg0_type , fsig , args );
@@ -2135,11 +2137,16 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21352137 if (!is_element_type_primitive (fsig -> params [0 ]) || !is_element_type_primitive (fsig -> params [1 ]))
21362138 return NULL ;
21372139
2138- #if !defined(TARGET_ARM64 ) && !defined( TARGET_S390X )
2140+ #if !defined(TARGET_ARM64 )
21392141 if (((id == SN_Max ) || (id == SN_Min )) && type_enum_is_float (arg0_type ))
21402142 return NULL ;
21412143#endif
21422144
2145+ #if defined(TARGET_S390X )
2146+ if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max ) || (id == SN_Min ) || (id == SN_MaxNative ) || (id == SN_MinNative ) || (id != SN_Xor ) || (id != SN_BitwiseAnd ) || (id != SN_BitwiseOr )) && arg0_type == MONO_TYPE_R4 )
2147+ return NULL ;
2148+ #endif
2149+
21432150 return emit_simd_ins_for_binary_op (cfg , klass , fsig , args , arg0_type , id );
21442151 }
21452152 case SN_Divide : {
@@ -2149,7 +2156,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21492156 if (!is_element_type_primitive (fsig -> params [0 ]) ||
21502157 !(MONO_TYPE_IS_VECTOR_PRIMITIVE (fsig -> params [1 ]) || is_element_type_primitive (fsig -> params [1 ])))
21512158 return NULL ;
2152-
2159+ #if defined(TARGET_S390X )
2160+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2161+ return NULL ;
2162+ #endif
21532163 return emit_simd_ins_for_binary_op (cfg , klass , fsig , args , arg0_type , id );
21542164 }
21552165 case SN_Multiply : {
@@ -2170,7 +2180,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21702180 return NULL ;
21712181 } else if (!(is_element_type_primitive (fsig -> params [0 ]) && is_element_type_primitive (fsig -> params [1 ])))
21722182 return NULL ;
2173-
2183+ #if defined(TARGET_S390X )
2184+ if (!mono_hwcap_s390x_has_ve1 && (vector_inner_type == MONO_TYPE_R4 ))
2185+ return NULL ;
2186+ #endif
21742187 return emit_simd_ins_for_binary_op (cfg , klass , fsig , args , vector_inner_type , id );
21752188 }
21762189 case SN_AndNot : {
@@ -2198,13 +2211,17 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21982211 int add_op ;
21992212
22002213 if (type_enum_is_float (arg0_type )) {
2214+ #if defined(TARGET_S390X )
2215+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2216+ return NULL ;
2217+ #endif
22012218 mul_op = OP_FMUL ;
22022219 add_op = OP_FADD ;
22032220 } else {
22042221 mul_op = OP_IMUL ;
22052222 add_op = OP_IADD ;
22062223
2207- #ifdef TARGET_ARM64
2224+ #if defined( TARGET_ARM64 ) || defined( TARGET_S390X )
22082225 if (!COMPILE_LLVM (cfg ) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8 || arg0_type == MONO_TYPE_I || arg0_type == MONO_TYPE_U ))
22092226 return NULL ;
22102227#endif
@@ -2274,6 +2291,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
22742291 int ceil_or_floor = id == SN_Ceiling ? 10 : 9 ;
22752292 return emit_simd_ins_for_sig (cfg , klass , OP_SSE41_ROUNDP , ceil_or_floor , arg0_type , fsig , args );
22762293#elif defined(TARGET_S390X )
2294+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2295+ return NULL ;
22772296 int ceil_or_floor = id == SN_Ceiling ? 6 : 7 ;
22782297 switch (arg0_type ){
22792298 case MONO_TYPE_R4 :
@@ -2464,6 +2483,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
24642483 return emit_vector_create_scalar (cfg , vklass , etype , args [0 ], is_unsafe );
24652484 }
24662485 case SN_Dot : {
2486+ #if defined(TARGET_S390X )
2487+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2488+ return NULL ;
2489+ #endif
24672490 return emit_dot (cfg , klass , fsig -> params [0 ], arg0_type , args [0 ]-> dreg , args [1 ]-> dreg );
24682491 }
24692492 case SN_Equals :
@@ -2472,6 +2495,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
24722495 if (!is_element_type_primitive (fsig -> params [0 ]))
24732496 return NULL ;
24742497 MonoClass * arg_class = mono_class_from_mono_type_internal (fsig -> params [0 ]);
2498+ #ifdef TARGET_S390X
2499+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2500+ return NULL ;
2501+ #endif
24752502 if (id == SN_Equals )
24762503 return emit_xcompare (cfg , klass , arg0_type , args [0 ], args [1 ]);
24772504
@@ -2733,7 +2760,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
27332760 case SN_LessThanOrEqual : {
27342761 if (!is_element_type_primitive (fsig -> params [0 ]))
27352762 return NULL ;
2736-
2763+ #ifdef TARGET_S390X
2764+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2765+ return NULL ;
2766+ #endif
27372767 return emit_xcompare_for_intrinsic (cfg , klass , id , arg0_type , args [0 ], args [1 ]);
27382768 }
27392769 case SN_GreaterThanAll :
@@ -2750,7 +2780,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
27502780 g_assert (fsig -> param_count == 2 &&
27512781 fsig -> ret -> type == MONO_TYPE_BOOLEAN &&
27522782 mono_metadata_type_equal (fsig -> params [0 ], fsig -> params [1 ]));
2753-
2783+ #ifdef TARGET_S390X
2784+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2785+ return NULL ;
2786+ #endif
27542787 gboolean is_all = FALSE;
27552788 switch (id ) {
27562789 case SN_GreaterThanAll :
@@ -2857,6 +2890,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
28572890 return NULL ;
28582891 if (!type_enum_is_float (arg0_type ))
28592892 return emit_xzero (cfg , klass );
2893+ #ifdef TARGET_S390X
2894+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2895+ return NULL ;
2896+ #endif
28602897 int op = -1 ;
28612898#if defined(TARGET_ARM64 ) || defined(TARGET_AMD64 ) || defined(TARGET_WASM ) || defined(TARGET_S390X )
28622899 op = OP_ONES_COMPLEMENT ;
@@ -2879,7 +2916,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
28792916 return emit_xones (cfg , klass );
28802917 }
28812918 }
2882-
2919+ #ifdef TARGET_S390X
2920+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2921+ return NULL ;
2922+ #endif
28832923 MonoInst * arg0 = args [0 ];
28842924 MonoClass * op_klass = klass ;
28852925
@@ -2907,6 +2947,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
29072947 case SN_IsPositiveInfinity : {
29082948 if (!is_element_type_primitive (fsig -> params [0 ]))
29092949 return NULL ;
2950+ #ifdef TARGET_S390X
2951+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
2952+ return NULL ;
2953+ #endif
29102954 if (arg0_type == MONO_TYPE_R4 ) {
29112955 guint32 value [4 ];
29122956
@@ -2984,6 +3028,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
29843028 case SN_IsZero : {
29853029 if (!is_element_type_primitive (fsig -> params [0 ]))
29863030 return NULL ;
3031+ #ifdef TARGET_S390X
3032+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
3033+ return NULL ;
3034+ #endif
29873035 return emit_xcompare (cfg , klass , arg0_type , args [0 ], emit_xzero (cfg , klass ));
29883036 }
29893037 case SN_Narrow : {
@@ -3129,7 +3177,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
31293177 case SN_OnesComplement : {
31303178 if (!is_element_type_primitive (fsig -> params [0 ]))
31313179 return NULL ;
3180+ #ifdef TARGET_S390X
3181+ if (!mono_hwcap_s390x_has_ve1 && (id == SN_Negate ) && (arg0_type == MONO_TYPE_R4 ))
31323182 return emit_simd_ins_for_unary_op (cfg , klass , fsig , args , arg0_type , id );
3183+ #endif
31333184 }
31343185 case SN_Shuffle : {
31353186 MonoType * etype = get_vector_t_elem_type (fsig -> ret );
@@ -3295,6 +3346,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
32953346
32963347 return emit_simd_ins_for_sig (cfg , klass , OP_XOP_X_X , instc0 , arg0_type , fsig , args );
32973348#elif defined(TARGET_S390X )
3349+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
3350+ return NULL ;
3351+
32983352 int instc0 = arg0_type == MONO_TYPE_R4 ? OP_S390_VFSQSB : OP_S390_VFSQDB ;
32993353 return emit_simd_ins_for_sig (cfg , klass , instc0 , 0 , arg0_type , fsig , args );
33003354#else
@@ -3792,6 +3846,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
37923846 if (fsig -> param_count != 2 )
37933847 return NULL ;
37943848 arg0_type = fsig -> param_count > 0 ? get_underlying_type (fsig -> params [0 ]) : MONO_TYPE_VOID ;
3849+ #ifdef TARGET_S390X
3850+ if (!mono_hwcap_s390x_has_ve1 && ((id != SN_op_ExclusiveOr ) || (id != SN_op_BitwiseAnd ) || (id != SN_op_BitwiseOr )) && arg0_type == MONO_TYPE_R4 )
3851+ return NULL ;
3852+ #endif
37953853 return emit_simd_ins_for_binary_op (cfg , klass , fsig , args , arg0_type , id );
37963854
37973855 }
@@ -3800,6 +3858,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
38003858 if (fsig -> param_count != 2 )
38013859 return NULL ;
38023860 MonoClass * arg_class = mono_class_from_mono_type_internal (fsig -> params [0 ]);
3861+ #ifdef TARGET_S390X
3862+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4 ))
3863+ return NULL ;
3864+ #endif
38033865 switch (id ) {
38043866 case SN_op_Equality : return emit_xequal (cfg , arg_class , arg0_type , args [0 ], args [1 ]);
38053867 case SN_op_Inequality : return emit_not_xequal (cfg , arg_class , arg0_type , args [0 ], args [1 ]);
@@ -3810,6 +3872,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
38103872 case SN_op_UnaryNegation :
38113873 if (fsig -> param_count != 1 )
38123874 return NULL ;
3875+ #if defined(TARGET_S390X )
3876+ if (!mono_hwcap_s390x_has_ve1 && (id == SN_op_UnaryNegation ) && (arg0_type == MONO_TYPE_R4 ))
3877+ return NULL ;
3878+ #endif
38133879 return emit_simd_ins_for_unary_op (cfg , klass , fsig , args , arg0_type , id );
38143880 case SN_op_UnaryPlus :
38153881 if (fsig -> param_count != 1 )
@@ -4150,10 +4216,18 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
41504216#ifndef TARGET_ARM64
41514217 if ((id == SN_Max ) || (id == SN_Min ))
41524218 return NULL ;
4219+ #endif
4220+ #ifdef TARGET_S390X
4221+ if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max ) || (id == SN_Min ) || (id == SN_MaxNative ) || (id == SN_MinNative )))
4222+ return NULL ;
41534223#endif
41544224 return emit_simd_ins_for_binary_op (cfg , klass , fsig , args , MONO_TYPE_R4 , id );
41554225 }
41564226 case SN_Dot : {
4227+ #ifdef TARGET_S390X
4228+ if (!mono_hwcap_s390x_has_ve1 )
4229+ return NULL ;
4230+ #endif
41574231 return emit_dot (cfg , klass , fsig -> params [0 ], MONO_TYPE_R4 , args [0 ]-> dreg , args [1 ]-> dreg );
41584232 }
41594233 case SN_Negate :
@@ -4172,6 +4246,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
41724246 return emit_simd_ins_for_sig (cfg , cmethod -> klass , OP_XOP_OVR_X_X , INTRINS_AARCH64_ADV_SIMD_FABS , MONO_TYPE_R4 , fsig , args );
41734247#endif
41744248 }
4249+ #ifdef TARGET_S390X
4250+ if (!mono_hwcap_s390x_has_ve1 )
4251+ return NULL ;
4252+ #endif
41754253 // MAX(x,0-x)
41764254 MonoInst * zero = emit_xzero (cfg , klass );
41774255 MonoInst * neg = emit_simd_ins (cfg , klass , OP_XBINOP , zero -> dreg , args [0 ]-> dreg );
@@ -4185,12 +4263,20 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
41854263 case SN_op_Equality : {
41864264 if (!(fsig -> param_count == 2 && mono_metadata_type_equal (fsig -> params [0 ], type ) && mono_metadata_type_equal (fsig -> params [1 ], type )))
41874265 return NULL ;
4266+ #ifdef TARGET_S390X
4267+ if (!mono_hwcap_s390x_has_ve1 )
4268+ return NULL ;
4269+ #endif
41884270 MonoClass * arg_class = mono_class_from_mono_type_internal (fsig -> params [0 ]);
41894271 return emit_xequal (cfg , arg_class , MONO_TYPE_R4 , args [0 ], args [1 ]);
41904272 }
41914273 case SN_op_Inequality : {
41924274 if (!(fsig -> param_count == 2 && mono_metadata_type_equal (fsig -> params [0 ], type ) && mono_metadata_type_equal (fsig -> params [1 ], type )))
41934275 return NULL ;
4276+ #ifdef TARGET_S390X
4277+ if (!mono_hwcap_s390x_has_ve1 )
4278+ return NULL ;
4279+ #endif
41944280 MonoClass * arg_class = mono_class_from_mono_type_internal (fsig -> params [0 ]);
41954281 return emit_not_xequal (cfg , arg_class , MONO_TYPE_R4 , args [0 ], args [1 ]);
41964282 }
@@ -4201,6 +4287,11 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
42014287 ins = emit_simd_ins (cfg , klass , OP_XOP_X_X , args [0 ]-> dreg , -1 );
42024288 ins -> inst_c0 = (IntrinsicId )INTRINS_SIMD_SQRT_R4 ;
42034289 return ins ;
4290+ #elif defined(TARGET_S390X )
4291+ if (!mono_hwcap_s390x_has_ve1 )
4292+ return NULL ;
4293+ ins = emit_simd_ins (cfg , klass , OP_S390_VFSQSB , args [0 ]-> dreg , -1 );
4294+ return ins ;
42044295#else
42054296 return NULL ;
42064297#endif
@@ -4215,6 +4306,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
42154306 if (id == SN_Clamp )
42164307 return NULL ;
42174308#endif
4309+ #ifdef TARGET_S390X
4310+ if (!mono_hwcap_s390x_has_ve1 )
4311+ return NULL ;
4312+ #endif
42184313
42194314 MonoInst * max = emit_simd_ins (cfg , klass , OP_XBINOP , args [0 ]-> dreg , args [1 ]-> dreg );
42204315 max -> inst_c0 = OP_FMAX ;
@@ -6865,6 +6960,11 @@ static MonoInst*
68656960emit_simd_intrinsics (const char * class_ns , const char * class_name , MonoCompile * cfg , MonoMethod * cmethod , MonoMethodSignature * fsig , MonoInst * * args )
68666961{
68676962 MonoInst * ins ;
6963+ #ifdef TARGET_S390X
6964+ /* vector facility was introduced in z13 */
6965+ if (!mono_hwcap_s390x_has_vec )
6966+ return NULL ;
6967+ #endif
68686968
68696969 if (cfg -> opt & MONO_OPT_SIMD ) {
68706970 ins = arch_emit_simd_intrinsics (class_ns , class_name , cfg , cmethod , fsig , args );
0 commit comments