target/s390x: vxeh2: vector string search
Signed-off-by: David Miller <dmiller423@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com> Tested-by: Thomas Huth <thuth@redhat.com> Reviewed-by: David Hildenbrand <david@redhat.com> Message-Id: <20220428094708.84835-7-david@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Thomas Huth
						Thomas Huth
					
				
			
			
				
	
			
			
			
						parent
						
							acc2d3a406
						
					
				
				
					commit
					1d706f3141
				
			| @@ -246,6 +246,12 @@ DEF_HELPER_6(gvec_vstrc_cc32, void, ptr, cptr, cptr, cptr, env, i32) | |||||||
| DEF_HELPER_6(gvec_vstrc_cc_rt8, void, ptr, cptr, cptr, cptr, env, i32) | DEF_HELPER_6(gvec_vstrc_cc_rt8, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
| DEF_HELPER_6(gvec_vstrc_cc_rt16, void, ptr, cptr, cptr, cptr, env, i32) | DEF_HELPER_6(gvec_vstrc_cc_rt16, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
| DEF_HELPER_6(gvec_vstrc_cc_rt32, void, ptr, cptr, cptr, cptr, env, i32) | DEF_HELPER_6(gvec_vstrc_cc_rt32, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_8, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_16, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_32, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_zs8, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_zs16, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  | DEF_HELPER_6(gvec_vstrs_zs32, void, ptr, cptr, cptr, cptr, env, i32) | ||||||
|  |  | ||||||
| /* === Vector Floating-Point Instructions */ | /* === Vector Floating-Point Instructions */ | ||||||
| DEF_HELPER_FLAGS_5(gvec_vfa32, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) | DEF_HELPER_FLAGS_5(gvec_vfa32, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) | ||||||
|   | |||||||
| @@ -1246,6 +1246,8 @@ | |||||||
|     F(0xe75c, VISTR,   VRR_a, V,   0, 0, 0, 0, vistr, 0, IF_VEC) |     F(0xe75c, VISTR,   VRR_a, V,   0, 0, 0, 0, vistr, 0, IF_VEC) | ||||||
| /* VECTOR STRING RANGE COMPARE */ | /* VECTOR STRING RANGE COMPARE */ | ||||||
|     F(0xe78a, VSTRC,   VRR_d, V,   0, 0, 0, 0, vstrc, 0, IF_VEC) |     F(0xe78a, VSTRC,   VRR_d, V,   0, 0, 0, 0, vstrc, 0, IF_VEC) | ||||||
|  | /* VECTOR STRING SEARCH */ | ||||||
|  |     F(0xe78b, VSTRS,   VRR_d, VE2, 0, 0, 0, 0, vstrs, 0, IF_VEC) | ||||||
|  |  | ||||||
| /* === Vector Floating-Point Instructions */ | /* === Vector Floating-Point Instructions */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6222,7 +6222,8 @@ enum DisasInsnEnum { | |||||||
| #define FAC_PCI         S390_FEAT_ZPCI /* z/PCI facility */ | #define FAC_PCI         S390_FEAT_ZPCI /* z/PCI facility */ | ||||||
| #define FAC_AIS         S390_FEAT_ADAPTER_INT_SUPPRESSION | #define FAC_AIS         S390_FEAT_ADAPTER_INT_SUPPRESSION | ||||||
| #define FAC_V           S390_FEAT_VECTOR /* vector facility */ | #define FAC_V           S390_FEAT_VECTOR /* vector facility */ | ||||||
| #define FAC_VE          S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */ | #define FAC_VE          S390_FEAT_VECTOR_ENH  /* vector enhancements facility 1 */ | ||||||
|  | #define FAC_VE2         S390_FEAT_VECTOR_ENH2 /* vector enhancements facility 2 */ | ||||||
| #define FAC_MIE2        S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */ | #define FAC_MIE2        S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */ | ||||||
| #define FAC_MIE3        S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */ | #define FAC_MIE3        S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2497,6 +2497,31 @@ static DisasJumpType op_vstrc(DisasContext *s, DisasOps *o) | |||||||
|     return DISAS_NEXT; |     return DISAS_NEXT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static DisasJumpType op_vstrs(DisasContext *s, DisasOps *o) | ||||||
|  | { | ||||||
|  |     typedef void (*helper_vstrs)(TCGv_ptr, TCGv_ptr, TCGv_ptr, | ||||||
|  |                                  TCGv_ptr, TCGv_ptr, TCGv_i32); | ||||||
|  |     static const helper_vstrs fns[3][2] = { | ||||||
|  |         { gen_helper_gvec_vstrs_8, gen_helper_gvec_vstrs_zs8 }, | ||||||
|  |         { gen_helper_gvec_vstrs_16, gen_helper_gvec_vstrs_zs16 }, | ||||||
|  |         { gen_helper_gvec_vstrs_32, gen_helper_gvec_vstrs_zs32 }, | ||||||
|  |     }; | ||||||
|  |     const uint8_t es = get_field(s, m5); | ||||||
|  |     const uint8_t m6 = get_field(s, m6); | ||||||
|  |     const bool zs = extract32(m6, 1, 1); | ||||||
|  | 
 | ||||||
|  |     if (es > ES_32 || m6 & ~2) { | ||||||
|  |         gen_program_exception(s, PGM_SPECIFICATION); | ||||||
|  |         return DISAS_NORETURN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     gen_gvec_4_ptr(get_field(s, v1), get_field(s, v2), | ||||||
|  |                    get_field(s, v3), get_field(s, v4), | ||||||
|  |                    cpu_env, 0, fns[es][zs]); | ||||||
|  |     set_cc_static(s); | ||||||
|  |     return DISAS_NEXT; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static DisasJumpType op_vfa(DisasContext *s, DisasOps *o) | static DisasJumpType op_vfa(DisasContext *s, DisasOps *o) | ||||||
| { | { | ||||||
|     const uint8_t fpf = get_field(s, m4); |     const uint8_t fpf = get_field(s, m4); | ||||||
|   | |||||||
| @@ -470,3 +470,102 @@ void HELPER(gvec_vstrc_cc_rt##BITS)(void *v1, const void *v2, const void *v3,  \ | |||||||
| DEF_VSTRC_CC_RT_HELPER(8) | DEF_VSTRC_CC_RT_HELPER(8) | ||||||
| DEF_VSTRC_CC_RT_HELPER(16) | DEF_VSTRC_CC_RT_HELPER(16) | ||||||
| DEF_VSTRC_CC_RT_HELPER(32) | DEF_VSTRC_CC_RT_HELPER(32) | ||||||
|  |  | ||||||
|  | static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3, | ||||||
|  |                  const S390Vector *v4, uint8_t es, bool zs) | ||||||
|  | { | ||||||
|  |     int substr_elen, substr_0, str_elen, i, j, k, cc; | ||||||
|  |     int nelem = 16 >> es; | ||||||
|  |     bool eos = false; | ||||||
|  |  | ||||||
|  |     substr_elen = s390_vec_read_element8(v4, 7) >> es; | ||||||
|  |  | ||||||
|  |     /* If ZS, bound substr length by min(nelem, strlen(v3)). */ | ||||||
|  |     if (zs) { | ||||||
|  |         substr_elen = MIN(substr_elen, nelem); | ||||||
|  |         for (i = 0; i < substr_elen; i++) { | ||||||
|  |             if (s390_vec_read_element(v3, i, es) == 0) { | ||||||
|  |                 substr_elen = i; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (substr_elen == 0) { | ||||||
|  |         cc = 2; /* full match for degenerate case of empty substr */ | ||||||
|  |         k = 0; | ||||||
|  |         goto done; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* If ZS, look for eos in the searched string. */ | ||||||
|  |     if (zs) { | ||||||
|  |         for (k = 0; k < nelem; k++) { | ||||||
|  |             if (s390_vec_read_element(v2, k, es) == 0) { | ||||||
|  |                 eos = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         str_elen = k; | ||||||
|  |     } else { | ||||||
|  |         str_elen = nelem; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     substr_0 = s390_vec_read_element(v3, 0, es); | ||||||
|  |  | ||||||
|  |     for (k = 0; ; k++) { | ||||||
|  |         for (; k < str_elen; k++) { | ||||||
|  |             if (s390_vec_read_element(v2, k, es) == substr_0) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* If we reached the end of the string, no match. */ | ||||||
|  |         if (k == str_elen) { | ||||||
|  |             cc = eos; /* no match (with or without zero char) */ | ||||||
|  |             goto done; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* If the substring is only one char, match. */ | ||||||
|  |         if (substr_elen == 1) { | ||||||
|  |             cc = 2; /* full match */ | ||||||
|  |             goto done; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* If the match begins at the last char, we have a partial match. */ | ||||||
|  |         if (k == str_elen - 1) { | ||||||
|  |             cc = 3; /* partial match */ | ||||||
|  |             goto done; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         i = MIN(nelem, k + substr_elen); | ||||||
|  |         for (j = k + 1; j < i; j++) { | ||||||
|  |             uint32_t e2 = s390_vec_read_element(v2, j, es); | ||||||
|  |             uint32_t e3 = s390_vec_read_element(v3, j - k, es); | ||||||
|  |             if (e2 != e3) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (j == i) { | ||||||
|  |             /* Matched up until "end". */ | ||||||
|  |             cc = i - k == substr_elen ? 2 : 3; /* full or partial match */ | ||||||
|  |             goto done; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  done: | ||||||
|  |     s390_vec_write_element64(v1, 0, k << es); | ||||||
|  |     s390_vec_write_element64(v1, 1, 0); | ||||||
|  |     return cc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define DEF_VSTRS_HELPER(BITS)                                             \ | ||||||
|  | void QEMU_FLATTEN HELPER(gvec_vstrs_##BITS)(void *v1, const void *v2,      \ | ||||||
|  |     const void *v3, const void *v4, CPUS390XState *env, uint32_t desc)     \ | ||||||
|  |     { env->cc_op = vstrs(v1, v2, v3, v4, MO_##BITS, false); }              \ | ||||||
|  | void QEMU_FLATTEN HELPER(gvec_vstrs_zs##BITS)(void *v1, const void *v2,    \ | ||||||
|  |     const void *v3, const void *v4, CPUS390XState *env, uint32_t desc)     \ | ||||||
|  |     { env->cc_op = vstrs(v1, v2, v3, v4, MO_##BITS, true); } | ||||||
|  |  | ||||||
|  | DEF_VSTRS_HELPER(8) | ||||||
|  | DEF_VSTRS_HELPER(16) | ||||||
|  | DEF_VSTRS_HELPER(32) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user