target/s390x: Fix the "ignored match" case in VSTRS
Currently the emulation of VSTRS recognizes partial matches in presence of \0 in the haystack, which, according to PoP, is not correct: If the ZS flag is one and a zero byte was detected in the second operand, then there can not be a partial match ... Add a check for this. While at it, fold a number of explicitly handled special cases into the generic logic. Cc: qemu-stable@nongnu.org Reported-by: Claudio Fontana <cfontana@suse.de> Closes: https://lists.gnu.org/archive/html/qemu-devel/2023-08/msg00633.html Fixes:1d706f3141
("target/s390x: vxeh2: vector string search") Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20230804233748.218935-3-iii@linux.ibm.com> Tested-by: Claudio Fontana <cfontana@suse.de> Acked-by: David Hildenbrand <david@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com> (cherry picked from commit791b2b6a93
) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
parent
7e5a8bb223
commit
5980189e96
@ -474,9 +474,9 @@ 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 substr_elen, i, j, k, cc;
|
||||
int nelem = 16 >> es;
|
||||
bool eos = false;
|
||||
int str_leftmost_0;
|
||||
|
||||
substr_elen = s390_vec_read_element8(v4, 7) >> es;
|
||||
|
||||
@ -498,47 +498,20 @@ static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
|
||||
}
|
||||
|
||||
/* If ZS, look for eos in the searched string. */
|
||||
str_leftmost_0 = nelem;
|
||||
if (zs) {
|
||||
for (k = 0; k < nelem; k++) {
|
||||
if (s390_vec_read_element(v2, k, es) == 0) {
|
||||
eos = true;
|
||||
str_leftmost_0 = k;
|
||||
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;
|
||||
}
|
||||
|
||||
cc = str_leftmost_0 == nelem ? 0 : 1; /* No match. */
|
||||
for (k = 0; k < nelem; k++) {
|
||||
i = MIN(nelem, k + substr_elen);
|
||||
for (j = k + 1; j < i; j++) {
|
||||
for (j = k; 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) {
|
||||
@ -546,9 +519,16 @@ static int vstrs(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
|
||||
}
|
||||
}
|
||||
if (j == i) {
|
||||
/* Matched up until "end". */
|
||||
cc = i - k == substr_elen ? 2 : 3; /* full or partial match */
|
||||
goto done;
|
||||
/* All elements matched. */
|
||||
if (k > str_leftmost_0) {
|
||||
cc = 1; /* Ignored match. */
|
||||
k = nelem;
|
||||
} else if (i - k == substr_elen) {
|
||||
cc = 2; /* Full match. */
|
||||
} else {
|
||||
cc = 3; /* Partial match. */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user