|
|
bca718 |
From 1026f1e15a84134fd19f58c98af85ec9474f7722 Mon Sep 17 00:00:00 2001
|
|
|
bca718 |
From: Stefan Liebler <stli@linux.vnet.ibm.com>
|
|
|
bca718 |
Date: Thu, 8 Oct 2015 11:21:50 +0200
|
|
|
bca718 |
Subject: [PATCH 19/30] S390: Optimize strncmp and wcsncmp. (AND COMMON-CODE
|
|
|
bca718 |
WCSNCMP - picked form upstream)
|
|
|
bca718 |
|
|
|
bca718 |
upstream-commit-id: cee82e70ccb7b2f054cd781b0a603ae244523e72
|
|
|
bca718 |
https://www.sourceware.org/ml/libc-alpha/2015-07/msg00087.html
|
|
|
bca718 |
|
|
|
bca718 |
common-code wcsncmp:
|
|
|
bca718 |
upstream-commit-id: 920a0395ba9fa5949ec87aaf5daa0259da16749d
|
|
|
bca718 |
https://www.sourceware.org/ml/libc-alpha/2015-04/msg00098.html
|
|
|
bca718 |
|
|
|
bca718 |
This patch provides optimized versions of strncmp and wcsncmp with the z13
|
|
|
bca718 |
vector instructions.
|
|
|
bca718 |
|
|
|
bca718 |
ChangeLog:
|
|
|
bca718 |
|
|
|
bca718 |
* sysdeps/s390/multiarch/strncmp-c.c: New File.
|
|
|
bca718 |
* sysdeps/s390/multiarch/strncmp-vx.S: Likewise.
|
|
|
bca718 |
* sysdeps/s390/multiarch/strncmp.c: Likewise.
|
|
|
bca718 |
* sysdeps/s390/multiarch/wcsncmp-c.c: Likewise.
|
|
|
bca718 |
* sysdeps/s390/multiarch/wcsncmp-vx.S: Likewise.
|
|
|
bca718 |
* sysdeps/s390/multiarch/wcsncmp.c: Likewise.
|
|
|
bca718 |
* sysdeps/s390/multiarch/Makefile (sysdep_routines): Add strncmp and
|
|
|
bca718 |
wcsncmp functions.
|
|
|
bca718 |
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
|
|
bca718 |
(__libc_ifunc_impl_list): Add ifunc test for strncmp, wcsncmp.
|
|
|
bca718 |
* wcsmbs/wcsncmp.c (WCSNCMP): Define and use macro.
|
|
|
bca718 |
* benchtests/bench-strncmp.c: Add wcsncmp support.
|
|
|
bca718 |
* benchtests/bench-wcsncmp.c: New File.
|
|
|
bca718 |
* benchtests/Makefile (wcsmbs-bench): Add wcsncmp.
|
|
|
bca718 |
---
|
|
|
bca718 |
benchtests/Makefile | 2 +-
|
|
|
bca718 |
benchtests/bench-strncmp.c | 104 +++++++++++++-----
|
|
|
bca718 |
benchtests/bench-wcsncmp.c | 20 ++++
|
|
|
bca718 |
localedata/tests-mbwc/dat_wcsncmp.c | 18 ++--
|
|
|
bca718 |
localedata/tests-mbwc/tst_wcsncmp.c | 2 +
|
|
|
bca718 |
string/strncmp.c | 2 +-
|
|
|
bca718 |
string/test-strncmp.c | 175 +++++++++++++++++++++---------
|
|
|
bca718 |
sysdeps/s390/multiarch/Makefile | 6 +-
|
|
|
bca718 |
sysdeps/s390/multiarch/ifunc-impl-list.c | 3 +
|
|
|
bca718 |
sysdeps/s390/multiarch/strncmp-c.c | 28 +++++
|
|
|
bca718 |
sysdeps/s390/multiarch/strncmp-vx.S | 137 ++++++++++++++++++++++++
|
|
|
bca718 |
sysdeps/s390/multiarch/strncmp.c | 30 ++++++
|
|
|
bca718 |
sysdeps/s390/multiarch/wcsncmp-c.c | 25 +++++
|
|
|
bca718 |
sysdeps/s390/multiarch/wcsncmp-vx.S | 177 +++++++++++++++++++++++++++++++
|
|
|
bca718 |
sysdeps/s390/multiarch/wcsncmp.c | 27 +++++
|
|
|
bca718 |
wcsmbs/Makefile | 2 +-
|
|
|
bca718 |
wcsmbs/test-wcsncmp-ifunc.c | 20 ++++
|
|
|
bca718 |
wcsmbs/test-wcsncmp.c | 2 +
|
|
|
bca718 |
wcsmbs/wcsncmp.c | 41 +++----
|
|
|
bca718 |
19 files changed, 716 insertions(+), 105 deletions(-)
|
|
|
bca718 |
create mode 100644 benchtests/bench-wcsncmp.c
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/strncmp-c.c
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/strncmp-vx.S
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/strncmp.c
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/wcsncmp-c.c
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/wcsncmp-vx.S
|
|
|
bca718 |
create mode 100644 sysdeps/s390/multiarch/wcsncmp.c
|
|
|
bca718 |
create mode 100644 wcsmbs/test-wcsncmp-ifunc.c
|
|
|
bca718 |
create mode 100644 wcsmbs/test-wcsncmp.c
|
|
|
bca718 |
|
|
|
bca718 |
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
|
|
bca718 |
index f6333eb..f6342da 100644
|
|
|
bca718 |
--- a/benchtests/Makefile
|
|
|
bca718 |
+++ b/benchtests/Makefile
|
|
|
bca718 |
@@ -39,7 +39,7 @@ string-bench := bcopy bzero memccpy memchr memcmp memcpy memmem memmove \
|
|
|
bca718 |
strncasecmp strncat strncmp strncpy strnlen strpbrk strrchr \
|
|
|
bca718 |
strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok
|
|
|
bca718 |
wcsmbs-bench := wcslen wcsnlen wcscpy wcpcpy wcsncpy wcpncpy wcscat wcsncat \
|
|
|
bca718 |
- wcsncmp
|
|
|
bca718 |
+ wcsncmp wcsncmp
|
|
|
bca718 |
string-bench-all := $(string-bench) ${wcsmbs-bench}
|
|
|
bca718 |
|
|
|
bca718 |
stdlib-bench := strtod
|
|
|
bca718 |
diff --git a/benchtests/bench-strncmp.c b/benchtests/bench-strncmp.c
|
|
|
bca718 |
index 25df3db..496ed68 100644
|
|
|
bca718 |
--- a/benchtests/bench-strncmp.c
|
|
|
bca718 |
+++ b/benchtests/bench-strncmp.c
|
|
|
bca718 |
@@ -17,17 +17,66 @@
|
|
|
bca718 |
<http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
|
|
|
bca718 |
#define TEST_MAIN
|
|
|
bca718 |
-#define TEST_NAME "strncmp"
|
|
|
bca718 |
+#ifdef WIDE
|
|
|
bca718 |
+# define TEST_NAME "wcsncmp"
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# define TEST_NAME "strncmp"
|
|
|
bca718 |
+#endif /* !WIDE */
|
|
|
bca718 |
#include "bench-string.h"
|
|
|
bca718 |
|
|
|
bca718 |
-typedef int (*proto_t) (const char *, const char *, size_t);
|
|
|
bca718 |
-int simple_strncmp (const char *, const char *, size_t);
|
|
|
bca718 |
-int stupid_strncmp (const char *, const char *, size_t);
|
|
|
bca718 |
+#ifdef WIDE
|
|
|
bca718 |
+# include <wchar.h>
|
|
|
bca718 |
+
|
|
|
bca718 |
+# define L(str) L##str
|
|
|
bca718 |
+# define STRNCMP wcsncmp
|
|
|
bca718 |
+# define SIMPLE_STRNCMP simple_wcsncmp
|
|
|
bca718 |
+# define STUPID_STRNCMP stupid_wcsncmp
|
|
|
bca718 |
+# define CHAR wchar_t
|
|
|
bca718 |
+# define CHARBYTES 4
|
|
|
bca718 |
+/* Wcsncmp uses signed semantics for comparison, not unsigned.
|
|
|
bca718 |
+ Avoid using substraction since possible overflow. */
|
|
|
bca718 |
+int
|
|
|
bca718 |
+simple_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
|
|
|
bca718 |
+{
|
|
|
bca718 |
+ wchar_t c1, c2;
|
|
|
bca718 |
+ while (n--)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
+ if (c1 == L ('\0') || c1 != c2)
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ return 0;
|
|
|
bca718 |
+}
|
|
|
bca718 |
|
|
|
bca718 |
-IMPL (stupid_strncmp, 0)
|
|
|
bca718 |
-IMPL (simple_strncmp, 0)
|
|
|
bca718 |
-IMPL (strncmp, 1)
|
|
|
bca718 |
+int
|
|
|
bca718 |
+stupid_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
|
|
|
bca718 |
+{
|
|
|
bca718 |
+ wchar_t c1, c2;
|
|
|
bca718 |
+ size_t ns1 = wcsnlen (s1, n) + 1, ns2 = wcsnlen (s2, n) + 1;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ n = ns1 < n ? ns1 : n;
|
|
|
bca718 |
+ n = ns2 < n ? ns2 : n;
|
|
|
bca718 |
|
|
|
bca718 |
+ while (n--)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
+ if (c1 != c2)
|
|
|
bca718 |
+ return c1 > c2 ? 1 : -1;
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ return 0;
|
|
|
bca718 |
+}
|
|
|
bca718 |
+
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# define L(str) str
|
|
|
bca718 |
+# define STRNCMP strncmp
|
|
|
bca718 |
+# define SIMPLE_STRNCMP simple_strncmp
|
|
|
bca718 |
+# define STUPID_STRNCMP stupid_strncmp
|
|
|
bca718 |
+# define CHAR char
|
|
|
bca718 |
+# define CHARBYTES 1
|
|
|
bca718 |
+
|
|
|
bca718 |
+/* Strncmp uses unsigned semantics for comparison. */
|
|
|
bca718 |
int
|
|
|
bca718 |
simple_strncmp (const char *s1, const char *s2, size_t n)
|
|
|
bca718 |
{
|
|
|
bca718 |
@@ -49,9 +98,16 @@ stupid_strncmp (const char *s1, const char *s2, size_t n)
|
|
|
bca718 |
while (n-- && (ret = *(unsigned char *) s1++ - * (unsigned char *) s2++) == 0);
|
|
|
bca718 |
return ret;
|
|
|
bca718 |
}
|
|
|
bca718 |
+#endif /* !WIDE */
|
|
|
bca718 |
+
|
|
|
bca718 |
+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
|
|
|
bca718 |
+
|
|
|
bca718 |
+IMPL (STUPID_STRNCMP, 0)
|
|
|
bca718 |
+IMPL (SIMPLE_STRNCMP, 0)
|
|
|
bca718 |
+IMPL (STRNCMP, 1)
|
|
|
bca718 |
|
|
|
bca718 |
static void
|
|
|
bca718 |
-do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
|
|
|
bca718 |
+do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i, iters = INNER_LOOP_ITERS;
|
|
|
bca718 |
@@ -74,12 +130,12 @@ do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i, align_n;
|
|
|
bca718 |
- char *s1, *s2;
|
|
|
bca718 |
+ CHAR *s1, *s2;
|
|
|
bca718 |
|
|
|
bca718 |
if (n == 0)
|
|
|
bca718 |
{
|
|
|
bca718 |
- s1 = (char*)(buf1 + page_size);
|
|
|
bca718 |
- s2 = (char*)(buf2 + page_size);
|
|
|
bca718 |
+ s1 = (CHAR*)(buf1 + page_size);
|
|
|
bca718 |
+ s2 = (CHAR*)(buf2 + page_size);
|
|
|
bca718 |
printf ("Length %4zd/%4zd:", len, n);
|
|
|
bca718 |
|
|
|
bca718 |
FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
@@ -92,16 +148,16 @@ do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
|
|
|
bca718 |
align1 &= 15;
|
|
|
bca718 |
align2 &= 15;
|
|
|
bca718 |
- align_n = (page_size - n) & 15;
|
|
|
bca718 |
+ align_n = (page_size - n * CHARBYTES) & 15;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char*)(buf1 + page_size - n);
|
|
|
bca718 |
- s2 = (char*)(buf2 + page_size - n);
|
|
|
bca718 |
+ s1 = (CHAR*)(buf1 + page_size - n * CHARBYTES);
|
|
|
bca718 |
+ s2 = (CHAR*)(buf2 + page_size - n * CHARBYTES);
|
|
|
bca718 |
|
|
|
bca718 |
if (align1 < align_n)
|
|
|
bca718 |
- s1 -= (align_n - align1);
|
|
|
bca718 |
+ s1 = (CHAR *) ((char *) s1 - (align_n - align1));
|
|
|
bca718 |
|
|
|
bca718 |
if (align2 < align_n)
|
|
|
bca718 |
- s2 -= (align_n - align2);
|
|
|
bca718 |
+ s2 = (CHAR *) ((char *) s2 - (align_n - align2));
|
|
|
bca718 |
|
|
|
bca718 |
for (i = 0; i < n; i++)
|
|
|
bca718 |
s1[i] = s2[i] = 1 + 23 * i % max_char;
|
|
|
bca718 |
@@ -129,24 +185,24 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i;
|
|
|
bca718 |
- char *s1, *s2;
|
|
|
bca718 |
+ CHAR *s1, *s2;
|
|
|
bca718 |
|
|
|
bca718 |
if (n == 0)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
- align1 &= 7;
|
|
|
bca718 |
- if (align1 + n + 1 >= page_size)
|
|
|
bca718 |
+ align1 &= 63;
|
|
|
bca718 |
+ if (align1 + (n + 1) * CHARBYTES >= page_size)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
align2 &= 7;
|
|
|
bca718 |
- if (align2 + n + 1 >= page_size)
|
|
|
bca718 |
+ if (align2 + (n + 1) * CHARBYTES >= page_size)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char*)(buf1 + align1);
|
|
|
bca718 |
- s2 = (char*)(buf2 + align2);
|
|
|
bca718 |
+ s1 = (CHAR*)(buf1 + align1);
|
|
|
bca718 |
+ s2 = (CHAR*)(buf2 + align2);
|
|
|
bca718 |
|
|
|
bca718 |
for (i = 0; i < n; i++)
|
|
|
bca718 |
- s1[i] = s2[i] = 1 + 23 * i % max_char;
|
|
|
bca718 |
+ s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
|
|
|
bca718 |
|
|
|
bca718 |
s1[n] = 24 + exp_result;
|
|
|
bca718 |
s2[n] = 23;
|
|
|
bca718 |
@@ -162,7 +218,7 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2);
|
|
|
bca718 |
|
|
|
bca718 |
FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
- do_one_test (impl, (char*)s1, (char*)s2, n, exp_result);
|
|
|
bca718 |
+ do_one_test (impl, s1, s2, n, exp_result);
|
|
|
bca718 |
|
|
|
bca718 |
putchar ('\n');
|
|
|
bca718 |
}
|
|
|
bca718 |
diff --git a/benchtests/bench-wcsncmp.c b/benchtests/bench-wcsncmp.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..8720060
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/benchtests/bench-wcsncmp.c
|
|
|
bca718 |
@@ -0,0 +1,20 @@
|
|
|
bca718 |
+/* Measure wcsncmp functions.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#define WIDE 1
|
|
|
bca718 |
+#include "bench-strncmp.c"
|
|
|
bca718 |
diff --git a/localedata/tests-mbwc/dat_wcsncmp.c b/localedata/tests-mbwc/dat_wcsncmp.c
|
|
|
bca718 |
index 167ce48..f468a8b 100644
|
|
|
bca718 |
--- a/localedata/tests-mbwc/dat_wcsncmp.c
|
|
|
bca718 |
+++ b/localedata/tests-mbwc/dat_wcsncmp.c
|
|
|
bca718 |
@@ -33,7 +33,7 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
|
|
|
bca718 |
{ 0x0000,0x00D2,0x00D3,0x0000 }, 3 }, /* #06 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x00D1, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
|
|
|
bca718 |
{ 0x00D1,0x00D2,0x00D9,0x0000 }, 2 }, /* #07 */
|
|
|
bca718 |
@@ -41,11 +41,11 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
|
|
|
bca718 |
{ 0x00D1,0x00D2,0x00D9,0x0000 }, 3 }, /* #08 */
|
|
|
bca718 |
- /*expect*/ { 0,1,-0x0006, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,-1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
|
|
|
bca718 |
{ 0x00D1,0x00D2,0x0000 }, 4 }, /* #09 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x00D3, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ .is_last = 1 }
|
|
|
bca718 |
}
|
|
|
bca718 |
@@ -75,7 +75,7 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
|
|
|
bca718 |
{ 0x0000,0x0042,0x0043,0x0000 }, 3 }, /* #06 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x0041, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
|
|
|
bca718 |
{ 0x0041,0x0042,0x0049,0x0000 }, 2 }, /* #07 */
|
|
|
bca718 |
@@ -83,11 +83,11 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
|
|
|
bca718 |
{ 0x0041,0x0042,0x0049,0x0000 }, 3 }, /* #08 */
|
|
|
bca718 |
- /*expect*/ { 0,1,-0x0006, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,-1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
|
|
|
bca718 |
{ 0x0041,0x0042,0x0000 }, 4 }, /* #09 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x0043, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ .is_last = 1 }
|
|
|
bca718 |
}
|
|
|
bca718 |
@@ -117,7 +117,7 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
|
|
|
bca718 |
{ 0x0000,0x3042,0x3043,0x0000 }, 3 }, /* #06 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x3041, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
|
|
|
bca718 |
{ 0x3041,0x3042,0x3049,0x0000 }, 2 }, /* #07 */
|
|
|
bca718 |
@@ -125,11 +125,11 @@ TST_WCSNCMP tst_wcsncmp_loc [] = {
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
|
|
|
bca718 |
{ 0x3041,0x3042,0x3049,0x0000 }, 3 }, /* #08 */
|
|
|
bca718 |
- /*expect*/ { 0,1,-0x0006, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,-1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
|
|
|
bca718 |
{ 0x3041,0x3042,0x0000 }, 4 }, /* #09 */
|
|
|
bca718 |
- /*expect*/ { 0,1,0x3043, },
|
|
|
bca718 |
+ /*expect*/ { 0,1,1, },
|
|
|
bca718 |
},
|
|
|
bca718 |
{ .is_last = 1 }
|
|
|
bca718 |
}
|
|
|
bca718 |
diff --git a/localedata/tests-mbwc/tst_wcsncmp.c b/localedata/tests-mbwc/tst_wcsncmp.c
|
|
|
bca718 |
index d046ecd..e378efb 100644
|
|
|
bca718 |
--- a/localedata/tests-mbwc/tst_wcsncmp.c
|
|
|
bca718 |
+++ b/localedata/tests-mbwc/tst_wcsncmp.c
|
|
|
bca718 |
@@ -24,6 +24,8 @@ tst_wcsncmp (FILE * fp, int debug_flg)
|
|
|
bca718 |
ws2 = TST_INPUT (wcsncmp).ws2;
|
|
|
bca718 |
n = TST_INPUT (wcsncmp).n;
|
|
|
bca718 |
ret = wcsncmp (ws1, ws2, n);
|
|
|
bca718 |
+ ret = (ret > 0 ? 1 : ret < 0 ? -1 : 0);
|
|
|
bca718 |
+
|
|
|
bca718 |
|
|
|
bca718 |
if (debug_flg)
|
|
|
bca718 |
{
|
|
|
bca718 |
diff --git a/string/strncmp.c b/string/strncmp.c
|
|
|
bca718 |
index d79305a..bd52138 100644
|
|
|
bca718 |
--- a/string/strncmp.c
|
|
|
bca718 |
+++ b/string/strncmp.c
|
|
|
bca718 |
@@ -21,7 +21,7 @@
|
|
|
bca718 |
#undef strncmp
|
|
|
bca718 |
|
|
|
bca718 |
#ifndef STRNCMP
|
|
|
bca718 |
-#define STRNCMP strncmp
|
|
|
bca718 |
+# define STRNCMP strncmp
|
|
|
bca718 |
#endif
|
|
|
bca718 |
|
|
|
bca718 |
/* Compare no more than N characters of S1 and S2,
|
|
|
bca718 |
diff --git a/string/test-strncmp.c b/string/test-strncmp.c
|
|
|
bca718 |
index 7169593..950bf24 100644
|
|
|
bca718 |
--- a/string/test-strncmp.c
|
|
|
bca718 |
+++ b/string/test-strncmp.c
|
|
|
bca718 |
@@ -1,5 +1,5 @@
|
|
|
bca718 |
/* Test and measure strncmp functions.
|
|
|
bca718 |
- Copyright (C) 1999-2012 Free Software Foundation, Inc.
|
|
|
bca718 |
+ Copyright (C) 1999-2015 Free Software Foundation, Inc.
|
|
|
bca718 |
This file is part of the GNU C Library.
|
|
|
bca718 |
Written by Jakub Jelinek <jakub@redhat.com>, 1999.
|
|
|
bca718 |
|
|
|
bca718 |
@@ -18,18 +18,82 @@
|
|
|
bca718 |
<http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
|
|
|
bca718 |
#define TEST_MAIN
|
|
|
bca718 |
-#define TEST_NAME "strncmp"
|
|
|
bca718 |
+#ifdef WIDE
|
|
|
bca718 |
+# define TEST_NAME "wcsncmp"
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# define TEST_NAME "strncmp"
|
|
|
bca718 |
+#endif
|
|
|
bca718 |
#include "test-string.h"
|
|
|
bca718 |
|
|
|
bca718 |
-typedef int (*proto_t) (const char *, const char *, size_t);
|
|
|
bca718 |
-int simple_strncmp (const char *, const char *, size_t);
|
|
|
bca718 |
-int stupid_strncmp (const char *, const char *, size_t);
|
|
|
bca718 |
+#ifdef WIDE
|
|
|
bca718 |
+# include <wchar.h>
|
|
|
bca718 |
+
|
|
|
bca718 |
+# define L(str) L##str
|
|
|
bca718 |
+# define STRNCMP wcsncmp
|
|
|
bca718 |
+# define STRCPY wcscpy
|
|
|
bca718 |
+# define STRDUP wcsdup
|
|
|
bca718 |
+# define MEMCPY wmemcpy
|
|
|
bca718 |
+# define SIMPLE_STRNCMP simple_wcsncmp
|
|
|
bca718 |
+# define STUPID_STRNCMP stupid_wcsncmp
|
|
|
bca718 |
+# define CHAR wchar_t
|
|
|
bca718 |
+# define UCHAR wchar_t
|
|
|
bca718 |
+# define CHARBYTES 4
|
|
|
bca718 |
+# define CHAR__MAX WCHAR_MAX
|
|
|
bca718 |
+# define CHAR__MIN WCHAR_MIN
|
|
|
bca718 |
+
|
|
|
bca718 |
+/* Wcsncmp uses signed semantics for comparison, not unsigned.
|
|
|
bca718 |
+ Avoid using substraction since possible overflow */
|
|
|
bca718 |
+int
|
|
|
bca718 |
+simple_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
|
|
|
bca718 |
+{
|
|
|
bca718 |
+ wchar_t c1, c2;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ while (n--)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
+ if (c1 == L('\0') || c1 != c2)
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ return 0;
|
|
|
bca718 |
+}
|
|
|
bca718 |
|
|
|
bca718 |
-IMPL (stupid_strncmp, 0)
|
|
|
bca718 |
-IMPL (simple_strncmp, 0)
|
|
|
bca718 |
-IMPL (strncmp, 1)
|
|
|
bca718 |
|
|
|
bca718 |
int
|
|
|
bca718 |
+stupid_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
|
|
|
bca718 |
+{
|
|
|
bca718 |
+ wchar_t c1, c2;
|
|
|
bca718 |
+ size_t ns1 = wcsnlen (s1, n) + 1, ns2 = wcsnlen (s2, n) + 1;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ n = ns1 < n ? ns1 : n;
|
|
|
bca718 |
+ n = ns2 < n ? ns2 : n;
|
|
|
bca718 |
+
|
|
|
bca718 |
+ while (n--)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
+ if (c1 != c2)
|
|
|
bca718 |
+ return c1 > c2 ? 1 : -1;
|
|
|
bca718 |
+ }
|
|
|
bca718 |
+ return 0;
|
|
|
bca718 |
+}
|
|
|
bca718 |
+
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# define L(str) str
|
|
|
bca718 |
+# define STRNCMP strncmp
|
|
|
bca718 |
+# define STRCPY strcpy
|
|
|
bca718 |
+# define STRDUP strdup
|
|
|
bca718 |
+# define MEMCPY memcpy
|
|
|
bca718 |
+# define SIMPLE_STRNCMP simple_strncmp
|
|
|
bca718 |
+# define STUPID_STRNCMP stupid_strncmp
|
|
|
bca718 |
+# define CHAR char
|
|
|
bca718 |
+# define UCHAR unsigned char
|
|
|
bca718 |
+# define CHARBYTES 1
|
|
|
bca718 |
+# define CHAR__MAX CHAR_MAX
|
|
|
bca718 |
+# define CHAR__MIN CHAR_MIN
|
|
|
bca718 |
+
|
|
|
bca718 |
+/* Strncmp uses unsigned semantics for comparison. */
|
|
|
bca718 |
+int
|
|
|
bca718 |
simple_strncmp (const char *s1, const char *s2, size_t n)
|
|
|
bca718 |
{
|
|
|
bca718 |
int ret = 0;
|
|
|
bca718 |
@@ -50,9 +114,16 @@ stupid_strncmp (const char *s1, const char *s2, size_t n)
|
|
|
bca718 |
while (n-- && (ret = *(unsigned char *) s1++ - * (unsigned char *) s2++) == 0);
|
|
|
bca718 |
return ret;
|
|
|
bca718 |
}
|
|
|
bca718 |
+#endif
|
|
|
bca718 |
+
|
|
|
bca718 |
+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
|
|
|
bca718 |
+
|
|
|
bca718 |
+IMPL (STUPID_STRNCMP, 0)
|
|
|
bca718 |
+IMPL (SIMPLE_STRNCMP, 0)
|
|
|
bca718 |
+IMPL (STRNCMP, 1)
|
|
|
bca718 |
|
|
|
bca718 |
static int
|
|
|
bca718 |
-check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
|
|
|
bca718 |
+check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
int result = CALL (impl, s1, s2, n);
|
|
|
bca718 |
@@ -70,7 +141,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
static void
|
|
|
bca718 |
-do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
|
|
|
bca718 |
+do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
if (check_result (impl, s1, s2, n, exp_result) < 0)
|
|
|
bca718 |
@@ -82,12 +153,12 @@ do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i, align_n;
|
|
|
bca718 |
- char *s1, *s2;
|
|
|
bca718 |
+ CHAR *s1, *s2;
|
|
|
bca718 |
|
|
|
bca718 |
if (n == 0)
|
|
|
bca718 |
{
|
|
|
bca718 |
- s1 = (char*)(buf1 + page_size);
|
|
|
bca718 |
- s2 = (char*)(buf2 + page_size);
|
|
|
bca718 |
+ s1 = (CHAR*) (buf1 + page_size);
|
|
|
bca718 |
+ s2 = (CHAR*) (buf2 + page_size);
|
|
|
bca718 |
|
|
|
bca718 |
FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
do_one_test (impl, s1, s2, n, 0);
|
|
|
bca718 |
@@ -97,16 +168,16 @@ do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
|
|
|
bca718 |
align1 &= 15;
|
|
|
bca718 |
align2 &= 15;
|
|
|
bca718 |
- align_n = (page_size - n) & 15;
|
|
|
bca718 |
+ align_n = (page_size - n * CHARBYTES) & 15;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char*)(buf1 + page_size - n);
|
|
|
bca718 |
- s2 = (char*)(buf2 + page_size - n);
|
|
|
bca718 |
+ s1 = (CHAR*) (buf1 + page_size - n * CHARBYTES);
|
|
|
bca718 |
+ s2 = (CHAR*) (buf2 + page_size - n * CHARBYTES);
|
|
|
bca718 |
|
|
|
bca718 |
if (align1 < align_n)
|
|
|
bca718 |
- s1 -= (align_n - align1);
|
|
|
bca718 |
+ s1 = (CHAR *) ((char *) s1 - (align_n - align1));
|
|
|
bca718 |
|
|
|
bca718 |
if (align2 < align_n)
|
|
|
bca718 |
- s2 -= (align_n - align2);
|
|
|
bca718 |
+ s2 = (CHAR *) ((char *) s2 - (align_n - align2));
|
|
|
bca718 |
|
|
|
bca718 |
for (i = 0; i < n; i++)
|
|
|
bca718 |
s1[i] = s2[i] = 1 + 23 * i % max_char;
|
|
|
bca718 |
@@ -130,24 +201,24 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
int exp_result)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i;
|
|
|
bca718 |
- char *s1, *s2;
|
|
|
bca718 |
+ CHAR *s1, *s2;
|
|
|
bca718 |
|
|
|
bca718 |
if (n == 0)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
- align1 &= 7;
|
|
|
bca718 |
- if (align1 + n + 1 >= page_size)
|
|
|
bca718 |
+ align1 &= 63;
|
|
|
bca718 |
+ if (align1 + (n + 1) * CHARBYTES >= page_size)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
align2 &= 7;
|
|
|
bca718 |
- if (align2 + n + 1 >= page_size)
|
|
|
bca718 |
+ if (align2 + (n + 1) * CHARBYTES >= page_size)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char*)(buf1 + align1);
|
|
|
bca718 |
- s2 = (char*)(buf2 + align2);
|
|
|
bca718 |
+ s1 = (CHAR*) (buf1 + align1);
|
|
|
bca718 |
+ s2 = (CHAR*) (buf2 + align2);
|
|
|
bca718 |
|
|
|
bca718 |
for (i = 0; i < n; i++)
|
|
|
bca718 |
- s1[i] = s2[i] = 1 + 23 * i % max_char;
|
|
|
bca718 |
+ s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
|
|
|
bca718 |
|
|
|
bca718 |
s1[n] = 24 + exp_result;
|
|
|
bca718 |
s2[n] = 23;
|
|
|
bca718 |
@@ -161,19 +232,20 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
|
|
|
bca718 |
s2[n - 1] -= exp_result;
|
|
|
bca718 |
|
|
|
bca718 |
FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
- do_one_test (impl, (char*)s1, (char*)s2, n, exp_result);
|
|
|
bca718 |
+ do_one_test (impl, s1, s2, n, exp_result);
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
static void
|
|
|
bca718 |
-do_page_test (size_t offset1, size_t offset2, char *s2)
|
|
|
bca718 |
+do_page_test (size_t offset1, size_t offset2, CHAR *s2)
|
|
|
bca718 |
{
|
|
|
bca718 |
- char *s1;
|
|
|
bca718 |
+ CHAR *s1;
|
|
|
bca718 |
int exp_result;
|
|
|
bca718 |
|
|
|
bca718 |
- if (offset1 >= page_size || offset2 >= page_size)
|
|
|
bca718 |
+ if (offset1 * CHARBYTES >= page_size || offset2 * CHARBYTES >= page_size)
|
|
|
bca718 |
return;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char *) (buf1 + offset1);
|
|
|
bca718 |
+ s1 = (CHAR *) buf1;
|
|
|
bca718 |
+ s1 += offset1;
|
|
|
bca718 |
s2 += offset2;
|
|
|
bca718 |
|
|
|
bca718 |
exp_result= *s1;
|
|
|
bca718 |
@@ -191,8 +263,8 @@ do_random_tests (void)
|
|
|
bca718 |
size_t i, j, n, align1, align2, pos, len1, len2, size;
|
|
|
bca718 |
int result;
|
|
|
bca718 |
long r;
|
|
|
bca718 |
- unsigned char *p1 = buf1 + page_size - 512;
|
|
|
bca718 |
- unsigned char *p2 = buf2 + page_size - 512;
|
|
|
bca718 |
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
|
|
|
bca718 |
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
|
|
|
bca718 |
|
|
|
bca718 |
for (n = 0; n < ITERATIONS; n++)
|
|
|
bca718 |
{
|
|
|
bca718 |
@@ -240,7 +312,7 @@ do_random_tests (void)
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
result = 0;
|
|
|
bca718 |
- memcpy (p2 + align2, p1 + align1, pos);
|
|
|
bca718 |
+ MEMCPY (p2 + align2, p1 + align1, pos);
|
|
|
bca718 |
if (pos < len1)
|
|
|
bca718 |
{
|
|
|
bca718 |
if (p2[align2 + pos] == p1[align1 + pos])
|
|
|
bca718 |
@@ -263,7 +335,7 @@ do_random_tests (void)
|
|
|
bca718 |
|
|
|
bca718 |
FOR_EACH_IMPL (impl, 1)
|
|
|
bca718 |
{
|
|
|
bca718 |
- r = CALL (impl, (char*)(p1 + align1), (char*)(p2 + align2), size);
|
|
|
bca718 |
+ r = CALL (impl, (CHAR *)(p1 + align1), (CHAR *)(p2 + align2), size);
|
|
|
bca718 |
/* Test whether on 64-bit architectures where ABI requires
|
|
|
bca718 |
callee to promote has the promotion been done. */
|
|
|
bca718 |
asm ("" : "=g" (r) : "0" (r));
|
|
|
bca718 |
@@ -282,19 +354,26 @@ do_random_tests (void)
|
|
|
bca718 |
static void
|
|
|
bca718 |
check1 (void)
|
|
|
bca718 |
{
|
|
|
bca718 |
- char *s1 = (char *)(buf1 + 0xb2c);
|
|
|
bca718 |
- char *s2 = (char *)(buf1 + 0xfd8);
|
|
|
bca718 |
- size_t i;
|
|
|
bca718 |
+ CHAR *s1 = (CHAR *)(buf1 + 0xb2c);
|
|
|
bca718 |
+ CHAR *s2 = (CHAR *)(buf1 + 0xfd8);
|
|
|
bca718 |
+ size_t i, offset;
|
|
|
bca718 |
int exp_result;
|
|
|
bca718 |
|
|
|
bca718 |
- strcpy(s1, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs");
|
|
|
bca718 |
- strcpy(s2, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV");
|
|
|
bca718 |
+ strcpy(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"));
|
|
|
bca718 |
+ strcpy(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV"));
|
|
|
bca718 |
+
|
|
|
bca718 |
+ /* Check possible overflow bug for wcsncmp */
|
|
|
bca718 |
+ s1[4] = CHAR__MAX;
|
|
|
bca718 |
+ s2[4] = CHAR__MIN;
|
|
|
bca718 |
|
|
|
bca718 |
- for (i = 0; i < 80; i++)
|
|
|
bca718 |
+ for (offset = 0; offset < 6; offset++)
|
|
|
bca718 |
{
|
|
|
bca718 |
- exp_result = simple_strncmp (s1, s2, i);
|
|
|
bca718 |
- FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
- check_result (impl, s1, s2, i, exp_result);
|
|
|
bca718 |
+ for (i = 0; i < 80; i++)
|
|
|
bca718 |
+ {
|
|
|
bca718 |
+ exp_result = SIMPLE_STRNCMP (s1 + offset, s2 + offset, i);
|
|
|
bca718 |
+ FOR_EACH_IMPL (impl, 0)
|
|
|
bca718 |
+ check_result (impl, s1 + offset, s2 + offset, i, exp_result);
|
|
|
bca718 |
+ }
|
|
|
bca718 |
}
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
@@ -302,17 +381,17 @@ static void
|
|
|
bca718 |
check2 (void)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t i;
|
|
|
bca718 |
- char *s1, *s2;
|
|
|
bca718 |
+ CHAR *s1, *s2;
|
|
|
bca718 |
|
|
|
bca718 |
- s1 = (char *) buf1;
|
|
|
bca718 |
- for (i = 0; i < page_size - 1; i++)
|
|
|
bca718 |
+ s1 = (CHAR *) buf1;
|
|
|
bca718 |
+ for (i = 0; i < (page_size / CHARBYTES) - 1; i++)
|
|
|
bca718 |
s1[i] = 23;
|
|
|
bca718 |
s1[i] = 0;
|
|
|
bca718 |
|
|
|
bca718 |
- s2 = strdup (s1);
|
|
|
bca718 |
+ s2 = STRDUP (s1);
|
|
|
bca718 |
|
|
|
bca718 |
for (i = 0; i < 64; ++i)
|
|
|
bca718 |
- do_page_test (3990 + i, 2635, s2);
|
|
|
bca718 |
+ do_page_test ((3988 / CHARBYTES) + i, (2636 / CHARBYTES), s2);
|
|
|
bca718 |
|
|
|
bca718 |
free (s2);
|
|
|
bca718 |
}
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile
|
|
|
bca718 |
index d8fbd55..d77bee5 100644
|
|
|
bca718 |
--- a/sysdeps/s390/multiarch/Makefile
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/Makefile
|
|
|
bca718 |
@@ -7,7 +7,8 @@ sysdep_routines += strlen strlen-vx strlen-c \
|
|
|
bca718 |
stpncpy stpncpy-vx stpncpy-c \
|
|
|
bca718 |
strcat strcat-vx strcat-c \
|
|
|
bca718 |
strncat strncat-vx strncat-c \
|
|
|
bca718 |
- strcmp strcmp-vx
|
|
|
bca718 |
+ strcmp strcmp-vx \
|
|
|
bca718 |
+ strncmp strncmp-vx strncmp-c
|
|
|
bca718 |
endif
|
|
|
bca718 |
|
|
|
bca718 |
ifeq ($(subdir),wcsmbs)
|
|
|
bca718 |
@@ -19,5 +20,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \
|
|
|
bca718 |
wcpncpy wcpncpy-vx wcpncpy-c \
|
|
|
bca718 |
wcscat wcscat-vx wcscat-c \
|
|
|
bca718 |
wcsncat wcsncat-vx wcsncat-c \
|
|
|
bca718 |
- wcscmp wcscmp-vx wcscmp-c
|
|
|
bca718 |
+ wcscmp wcscmp-vx wcscmp-c \
|
|
|
bca718 |
+ wcsncmp wcsncmp-vx wcsncmp-c
|
|
|
bca718 |
endif
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
|
|
bca718 |
index 196d3ec..5bfc493 100644
|
|
|
bca718 |
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
|
|
bca718 |
@@ -106,6 +106,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
|
|
bca718 |
IFUNC_VX_IMPL (strcmp);
|
|
|
bca718 |
IFUNC_VX_IMPL (wcscmp);
|
|
|
bca718 |
|
|
|
bca718 |
+ IFUNC_VX_IMPL (strncmp);
|
|
|
bca718 |
+ IFUNC_VX_IMPL (wcsncmp);
|
|
|
bca718 |
+
|
|
|
bca718 |
#endif /* HAVE_S390_VX_ASM_SUPPORT */
|
|
|
bca718 |
|
|
|
bca718 |
return i;
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/strncmp-c.c b/sysdeps/s390/multiarch/strncmp-c.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..75da859
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/strncmp-c.c
|
|
|
bca718 |
@@ -0,0 +1,28 @@
|
|
|
bca718 |
+/* Default strncmp implementation for S/390.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+# define STRNCMP __strncmp_c
|
|
|
bca718 |
+# ifdef SHARED
|
|
|
bca718 |
+# undef libc_hidden_builtin_def
|
|
|
bca718 |
+# define libc_hidden_builtin_def(name) \
|
|
|
bca718 |
+ __hidden_ver1 (__strncmp_c, __GI_strncmp, __strncmp_c);
|
|
|
bca718 |
+# endif /* SHARED */
|
|
|
bca718 |
+
|
|
|
bca718 |
+# include <string/strncmp.c>
|
|
|
bca718 |
+#endif /* HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc */
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/strncmp-vx.S b/sysdeps/s390/multiarch/strncmp-vx.S
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..36e99b8
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/strncmp-vx.S
|
|
|
bca718 |
@@ -0,0 +1,137 @@
|
|
|
bca718 |
+/* Vector optimized 32/64 bit S/390 version of strncmp.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+
|
|
|
bca718 |
+# include "sysdep.h"
|
|
|
bca718 |
+# include "asm-syntax.h"
|
|
|
bca718 |
+
|
|
|
bca718 |
+ .text
|
|
|
bca718 |
+
|
|
|
bca718 |
+/* int strncmp (const char *s1, const char *s2, size_t n)
|
|
|
bca718 |
+ Compare at most n characters of two strings.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ Register usage:
|
|
|
bca718 |
+ -r0=tmp
|
|
|
bca718 |
+ -r1=tmp
|
|
|
bca718 |
+ -r2=s1
|
|
|
bca718 |
+ -r3=s2
|
|
|
bca718 |
+ -r4=n
|
|
|
bca718 |
+ -r5=current_len
|
|
|
bca718 |
+ -v16=part of s1
|
|
|
bca718 |
+ -v17=part of s2
|
|
|
bca718 |
+ -v18=index of unequal
|
|
|
bca718 |
+*/
|
|
|
bca718 |
+ENTRY(__strncmp_vx)
|
|
|
bca718 |
+ .machine "z13"
|
|
|
bca718 |
+ .machinemode "zarch_nohighgprs"
|
|
|
bca718 |
+
|
|
|
bca718 |
+# if !defined __s390x__
|
|
|
bca718 |
+ llgfr %r4,%r4
|
|
|
bca718 |
+# endif /* !defined __s390x__ */
|
|
|
bca718 |
+
|
|
|
bca718 |
+ clgije %r4,0,.Lend_equal /* Nothing to do if n == 0, */
|
|
|
bca718 |
+ lghi %r5,0 /* current_len = 0. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Lloop:
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6 /* Get loaded byte count of s1. */
|
|
|
bca718 |
+ jo .Llt16_1 /* Jump away if vr is not fully loaded. */
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */
|
|
|
bca718 |
+ jo .Llt16_2 /* Jump away if vr is not fully loaded. */
|
|
|
bca718 |
+ aghi %r5,16 /* Both vrs are fully loaded. */
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp /* If current_len >= n ->last compare. */
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+ j .Lloop
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Llt16_1:
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count ofs2. */
|
|
|
bca718 |
+.Llt16_2:
|
|
|
bca718 |
+ clr %r0,%r1 /* Compare logical. */
|
|
|
bca718 |
+ locrh %r0,%r1 /* Compute minimum of bytes loaded. */
|
|
|
bca718 |
+ algfr %r5,%r0 /* Add smallest loaded bytes to current_len. */
|
|
|
bca718 |
+ clgrj %r5,%r4,10,.Llastcmp /* If current_len >= n ->last compare. */
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */
|
|
|
bca718 |
+ vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */
|
|
|
bca718 |
+ clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within
|
|
|
bca718 |
+ loaded bytes (index < loaded-bytes) */
|
|
|
bca718 |
+ j .Lloop
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Llastcmp:
|
|
|
bca718 |
+ /* Use comparision result only if located within first n characters.
|
|
|
bca718 |
+ %r0: loaded byte count in vreg;
|
|
|
bca718 |
+ %r5: current_len;
|
|
|
bca718 |
+ %r4: n;
|
|
|
bca718 |
+ (current_len - n): [0...16[
|
|
|
bca718 |
+ First ignored match index: loaded bytes - (current_len-n): ]0...16]
|
|
|
bca718 |
+ */
|
|
|
bca718 |
+ slgr %r5,%r4 /* %r5 = current_len - n. */
|
|
|
bca718 |
+ slr %r0,%r5 /* %r0 = first ignored match index. */
|
|
|
bca718 |
+ vfenezbs %v18,%v16,%v17 /* Compare not equal with zero search. */
|
|
|
bca718 |
+ vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */
|
|
|
bca718 |
+ clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within
|
|
|
bca718 |
+ loaded bytes and below n bytes. */
|
|
|
bca718 |
+ j .Lend_equal /* Miscompare after n-bytes -> end equal. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Lfound:
|
|
|
bca718 |
+ /* Difference or end of string. */
|
|
|
bca718 |
+ je .Lend_equal
|
|
|
bca718 |
+ lghi %r2,1
|
|
|
bca718 |
+ lghi %r1,-1
|
|
|
bca718 |
+ locgrl %r2,%r1
|
|
|
bca718 |
+ br %r14
|
|
|
bca718 |
+.Lend_equal:
|
|
|
bca718 |
+ lghi %r2,0
|
|
|
bca718 |
+ br %r14
|
|
|
bca718 |
+END(__strncmp_vx)
|
|
|
bca718 |
+#endif /* HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc */
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/strncmp.c b/sysdeps/s390/multiarch/strncmp.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..1e1e05a
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/strncmp.c
|
|
|
bca718 |
@@ -0,0 +1,30 @@
|
|
|
bca718 |
+/* Multiple versions of strncmp.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+# include <string.h>
|
|
|
bca718 |
+# include <ifunc-resolve.h>
|
|
|
bca718 |
+
|
|
|
bca718 |
+
|
|
|
bca718 |
+# undef strcmp
|
|
|
bca718 |
+extern __typeof (strncmp) __strncmp;
|
|
|
bca718 |
+s390_vx_libc_ifunc2 (__strncmp, strncmp)
|
|
|
bca718 |
+
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# include <string/strncmp.c>
|
|
|
bca718 |
+#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc) */
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/wcsncmp-c.c b/sysdeps/s390/multiarch/wcsncmp-c.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..058cd0c
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/wcsncmp-c.c
|
|
|
bca718 |
@@ -0,0 +1,25 @@
|
|
|
bca718 |
+/* Default wcsncmp implementation for S/390.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+# define WCSNCMP __wcsncmp_c
|
|
|
bca718 |
+
|
|
|
bca718 |
+# include <wchar.h>
|
|
|
bca718 |
+extern __typeof (wcsncmp) __wcsncmp_c;
|
|
|
bca718 |
+# include <wcsmbs/wcsncmp.c>
|
|
|
bca718 |
+#endif
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/wcsncmp-vx.S b/sysdeps/s390/multiarch/wcsncmp-vx.S
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..9a44424
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/wcsncmp-vx.S
|
|
|
bca718 |
@@ -0,0 +1,177 @@
|
|
|
bca718 |
+/* Vector optimized 32/64 bit S/390 version of wcsncmp.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+
|
|
|
bca718 |
+# include "sysdep.h"
|
|
|
bca718 |
+# include "asm-syntax.h"
|
|
|
bca718 |
+
|
|
|
bca718 |
+ .text
|
|
|
bca718 |
+
|
|
|
bca718 |
+/* int wcsncmp (const wchar_t *s1, const wchar_t *s2, size_t n)
|
|
|
bca718 |
+ Compare at most n characters of two strings.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ Register usage:
|
|
|
bca718 |
+ -r0=tmp
|
|
|
bca718 |
+ -r1=tmp
|
|
|
bca718 |
+ -r2=s1
|
|
|
bca718 |
+ -r3=s2
|
|
|
bca718 |
+ -r4=n
|
|
|
bca718 |
+ -r5=current_len
|
|
|
bca718 |
+ -v16=part of s1
|
|
|
bca718 |
+ -v17=part of s2
|
|
|
bca718 |
+ -v18=index of unequal
|
|
|
bca718 |
+*/
|
|
|
bca718 |
+ENTRY(__wcsncmp_vx)
|
|
|
bca718 |
+ .machine "z13"
|
|
|
bca718 |
+ .machinemode "zarch_nohighgprs"
|
|
|
bca718 |
+
|
|
|
bca718 |
+# if !defined __s390x__
|
|
|
bca718 |
+ llgfr %r4,%r4
|
|
|
bca718 |
+# endif /* !defined __s390x__ */
|
|
|
bca718 |
+
|
|
|
bca718 |
+ clgije %r4,0,.Lend_equal /* Nothing to do if n == 0. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+ /* Check range of n and convert to byte-count. */
|
|
|
bca718 |
+# ifdef __s390x__
|
|
|
bca718 |
+ tmhh %r4,49152 /* Test bit 0 or 1 of maxlen. */
|
|
|
bca718 |
+ lghi %r1,-4 /* Max byte-count is 18446744073709551612. */
|
|
|
bca718 |
+# else
|
|
|
bca718 |
+ tmlh %r4,49152 /* Test bit 0 or 1 of maxlen. */
|
|
|
bca718 |
+ llilf %r1,4294967292 /* Max byte-count is 4294967292. */
|
|
|
bca718 |
+# endif /* !__s390x__ */
|
|
|
bca718 |
+ sllg %r4,%r4,2 /* Convert character-count to byte-count. */
|
|
|
bca718 |
+ locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+ /* Check first character without vector load. */
|
|
|
bca718 |
+ lghi %r5,4 /* current_len = 4 bytes. */
|
|
|
bca718 |
+ /* Check s1/2[0]. */
|
|
|
bca718 |
+ lt %r0,0(%r2)
|
|
|
bca718 |
+ l %r1,0(%r3)
|
|
|
bca718 |
+ je .Lend_cmp_one_char
|
|
|
bca718 |
+ crjne %r0,%r1,.Lend_cmp_one_char
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Lloop:
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6 /* Get loaded byte count of s1. */
|
|
|
bca718 |
+ jo .Llt16_1 /* Jump away if vector not fully loaded. */
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */
|
|
|
bca718 |
+ jo .Llt16_2 /* Jump away if vector not fully loaded. */
|
|
|
bca718 |
+ aghi %r5,16 /* Both vectors are fully loaded. */
|
|
|
bca718 |
+ vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp /* If current_len >= n ->last compare. */
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ vfenezfs %v18,%v16,%v17
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ vfenezfs %v18,%v16,%v17
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ vlbb %v17,0(%r5,%r3),6
|
|
|
bca718 |
+ vlbb %v16,0(%r5,%r2),6
|
|
|
bca718 |
+ lcbb %r0,0(%r5,%r2),6
|
|
|
bca718 |
+ jo .Llt16_1
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6
|
|
|
bca718 |
+ jo .Llt16_2
|
|
|
bca718 |
+ aghi %r5,16
|
|
|
bca718 |
+ vfenezfs %v18,%v16,%v17
|
|
|
bca718 |
+ clgrjhe %r5,%r4,.Llastcmp
|
|
|
bca718 |
+ jno .Lfound
|
|
|
bca718 |
+
|
|
|
bca718 |
+ j .Lloop
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Llt16_1:
|
|
|
bca718 |
+ lcbb %r1,0(%r5,%r3),6 /* Get loaded byte count of s2. */
|
|
|
bca718 |
+.Llt16_2:
|
|
|
bca718 |
+ clr %r0,%r1 /* Compare logical. */
|
|
|
bca718 |
+ locrh %r0,%r1 /* Compute minimum of bytes loaded. */
|
|
|
bca718 |
+ nill %r0,65532 /* Align bytes loaded to full characters. */
|
|
|
bca718 |
+ jz .Lcmp_one_char /* Jump away if no full char is available. */
|
|
|
bca718 |
+.Llt_cmp:
|
|
|
bca718 |
+ algfr %r5,%r0 /* Add smallest loaded bytes to current_len. */
|
|
|
bca718 |
+ vfenezfs %v18,%v16,%v17 /* Compare not equal with zero search. */
|
|
|
bca718 |
+ clgrj %r5,%r4,10,.Llastcmp /* If current_len >= n -> last compare */
|
|
|
bca718 |
+ vlgvb %r1,%v18,7 /* Get not equal index or 16 if all equal. */
|
|
|
bca718 |
+ clrjl %r1,%r0,.Lfound /* Jump away if miscompare is within
|
|
|
bca718 |
+ loaded bytes; (index < loaded-bytes) */
|
|
|
bca718 |
+ j .Lloop
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Lcmp_one_char:
|
|
|
bca718 |
+ /* At least one of both strings is not 4-byte aligned
|
|
|
bca718 |
+ and there is no full character before next block-boundary.
|
|
|
bca718 |
+ Compare one character to get over the boundary and
|
|
|
bca718 |
+ proceed with normal loop! */
|
|
|
bca718 |
+ vlef %v16,0(%r5,%r2),0 /* Load one character. */
|
|
|
bca718 |
+ lghi %r0,4 /* Loaded byte count is 4. */
|
|
|
bca718 |
+ vlef %v17,0(%r5,%r3),0
|
|
|
bca718 |
+ j .Llt_cmp /* Proceed with comparision. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Llastcmp:
|
|
|
bca718 |
+ /* Use comparision result only if located within first n characters.
|
|
|
bca718 |
+ %r0: loaded byte count in vreg;
|
|
|
bca718 |
+ %r5: current_len;
|
|
|
bca718 |
+ %r4: n;
|
|
|
bca718 |
+ (current_len - n): [0...16[
|
|
|
bca718 |
+ First ignored match index: loaded bytes - (current_len-n): ]0...16]
|
|
|
bca718 |
+ */
|
|
|
bca718 |
+ slgr %r5,%r4 /* %r5 = current_len - n. */
|
|
|
bca718 |
+ slr %r0,%r5 /* %r0 = first ignored match index. */
|
|
|
bca718 |
+ vlgvb %r4,%v18,7 /* Get not equal index or 16 if all equal. */
|
|
|
bca718 |
+ clrjl %r4,%r0,.Lfound2 /* Jump away if miscompare is within
|
|
|
bca718 |
+ loaded bytes and below n bytes. */
|
|
|
bca718 |
+.Lend_equal:
|
|
|
bca718 |
+ lghi %r2,0
|
|
|
bca718 |
+ br %r14
|
|
|
bca718 |
+
|
|
|
bca718 |
+.Lfound:
|
|
|
bca718 |
+ /* Difference or end of string. */
|
|
|
bca718 |
+ /* vfenezf found an unequal element or zero.
|
|
|
bca718 |
+ This instruction compares unsigned words, but wchar_t is signed.
|
|
|
bca718 |
+ Thus we have to compare the found element again. */
|
|
|
bca718 |
+ vlgvb %r4,%v18,7 /* Extract not equal byte-index. */
|
|
|
bca718 |
+.Lfound2:
|
|
|
bca718 |
+ srl %r4,2 /* And convert it to character-index. */
|
|
|
bca718 |
+ vlgvf %r0,%v16,0(%r4) /* Load character-values. */
|
|
|
bca718 |
+ vlgvf %r1,%v17,0(%r4)
|
|
|
bca718 |
+.Lend_cmp_one_char:
|
|
|
bca718 |
+ cr %r0,%r1
|
|
|
bca718 |
+ je .Lend_equal
|
|
|
bca718 |
+ lghi %r2,1
|
|
|
bca718 |
+ lghi %r1,-1
|
|
|
bca718 |
+ locgrl %r2,%r1
|
|
|
bca718 |
+ br %r14
|
|
|
bca718 |
+END(__wcsncmp_vx)
|
|
|
bca718 |
+#endif /* HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc */
|
|
|
bca718 |
diff --git a/sysdeps/s390/multiarch/wcsncmp.c b/sysdeps/s390/multiarch/wcsncmp.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..0d79661
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/sysdeps/s390/multiarch/wcsncmp.c
|
|
|
bca718 |
@@ -0,0 +1,27 @@
|
|
|
bca718 |
+/* Multiple versions of wcsncmp.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#if defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc
|
|
|
bca718 |
+# include <wchar.h>
|
|
|
bca718 |
+# include <ifunc-resolve.h>
|
|
|
bca718 |
+
|
|
|
bca718 |
+s390_vx_libc_ifunc2 (__wcsncmp, wcsncmp)
|
|
|
bca718 |
+
|
|
|
bca718 |
+#else
|
|
|
bca718 |
+# include <wcsmbs/wcsncmp.c>
|
|
|
bca718 |
+#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && !defined NOT_IN_libc) */
|
|
|
bca718 |
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
|
|
|
bca718 |
index 44b1502..611b2c9 100644
|
|
|
bca718 |
--- a/wcsmbs/Makefile
|
|
|
bca718 |
+++ b/wcsmbs/Makefile
|
|
|
bca718 |
@@ -41,7 +41,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
|
|
|
bca718 |
isoc99_swscanf isoc99_vswscanf \
|
|
|
bca718 |
mbrtoc16 c16rtomb
|
|
|
bca718 |
|
|
|
bca718 |
-strop-tests := wcscmp wmemcmp wcslen wcschr wcsrchr wcscpy wcsnlen \
|
|
|
bca718 |
+strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy wcsnlen \
|
|
|
bca718 |
wcpcpy wcsncpy wcpncpy wcscat wcsncat
|
|
|
bca718 |
tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
|
|
|
bca718 |
tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
|
|
|
bca718 |
diff --git a/wcsmbs/test-wcsncmp-ifunc.c b/wcsmbs/test-wcsncmp-ifunc.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..35176f0
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/wcsmbs/test-wcsncmp-ifunc.c
|
|
|
bca718 |
@@ -0,0 +1,20 @@
|
|
|
bca718 |
+/* Test and measure IFUNC implementations of wcsncmp function.
|
|
|
bca718 |
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
|
bca718 |
+ This file is part of the GNU C Library.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
bca718 |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
bca718 |
+ License as published by the Free Software Foundation; either
|
|
|
bca718 |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
bca718 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bca718 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bca718 |
+ Lesser General Public License for more details.
|
|
|
bca718 |
+
|
|
|
bca718 |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
bca718 |
+ License along with the GNU C Library; if not, see
|
|
|
bca718 |
+ <http://www.gnu.org/licenses/>. */
|
|
|
bca718 |
+
|
|
|
bca718 |
+#define TEST_IFUNC 1
|
|
|
bca718 |
+#include "test-wcsncmp.c"
|
|
|
bca718 |
diff --git a/wcsmbs/test-wcsncmp.c b/wcsmbs/test-wcsncmp.c
|
|
|
bca718 |
new file mode 100644
|
|
|
bca718 |
index 0000000..07757d8
|
|
|
bca718 |
--- /dev/null
|
|
|
bca718 |
+++ b/wcsmbs/test-wcsncmp.c
|
|
|
bca718 |
@@ -0,0 +1,2 @@
|
|
|
bca718 |
+#define WIDE 1
|
|
|
bca718 |
+#include "../string/test-strncmp.c"
|
|
|
bca718 |
diff --git a/wcsmbs/wcsncmp.c b/wcsmbs/wcsncmp.c
|
|
|
bca718 |
index 7f1704f..1522b6f 100644
|
|
|
bca718 |
--- a/wcsmbs/wcsncmp.c
|
|
|
bca718 |
+++ b/wcsmbs/wcsncmp.c
|
|
|
bca718 |
@@ -18,53 +18,56 @@
|
|
|
bca718 |
|
|
|
bca718 |
#include <wchar.h>
|
|
|
bca718 |
|
|
|
bca718 |
+#ifndef WCSNCMP
|
|
|
bca718 |
+# define WCSNCMP wcsncmp
|
|
|
bca718 |
+#endif
|
|
|
bca718 |
|
|
|
bca718 |
/* Compare no more than N characters of S1 and S2,
|
|
|
bca718 |
returning less than, equal to or greater than zero
|
|
|
bca718 |
if S1 is lexicographically less than, equal to or
|
|
|
bca718 |
greater than S2. */
|
|
|
bca718 |
int
|
|
|
bca718 |
-wcsncmp (s1, s2, n)
|
|
|
bca718 |
+WCSNCMP (s1, s2, n)
|
|
|
bca718 |
const wchar_t *s1;
|
|
|
bca718 |
const wchar_t *s2;
|
|
|
bca718 |
size_t n;
|
|
|
bca718 |
{
|
|
|
bca718 |
- wint_t c1 = L'\0';
|
|
|
bca718 |
- wint_t c2 = L'\0';
|
|
|
bca718 |
+ wchar_t c1 = L'\0';
|
|
|
bca718 |
+ wchar_t c2 = L'\0';
|
|
|
bca718 |
|
|
|
bca718 |
if (n >= 4)
|
|
|
bca718 |
{
|
|
|
bca718 |
size_t n4 = n >> 2;
|
|
|
bca718 |
do
|
|
|
bca718 |
{
|
|
|
bca718 |
- c1 = (wint_t) *s1++;
|
|
|
bca718 |
- c2 = (wint_t) *s2++;
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
if (c1 == L'\0' || c1 != c2)
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
- c1 = (wint_t) *s1++;
|
|
|
bca718 |
- c2 = (wint_t) *s2++;
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
if (c1 == L'\0' || c1 != c2)
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
- c1 = (wint_t) *s1++;
|
|
|
bca718 |
- c2 = (wint_t) *s2++;
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
if (c1 == L'\0' || c1 != c2)
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
- c1 = (wint_t) *s1++;
|
|
|
bca718 |
- c2 = (wint_t) *s2++;
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
if (c1 == L'\0' || c1 != c2)
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
} while (--n4 > 0);
|
|
|
bca718 |
n &= 3;
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
while (n > 0)
|
|
|
bca718 |
{
|
|
|
bca718 |
- c1 = (wint_t) *s1++;
|
|
|
bca718 |
- c2 = (wint_t) *s2++;
|
|
|
bca718 |
+ c1 = *s1++;
|
|
|
bca718 |
+ c2 = *s2++;
|
|
|
bca718 |
if (c1 == L'\0' || c1 != c2)
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
|
|
|
bca718 |
n--;
|
|
|
bca718 |
}
|
|
|
bca718 |
|
|
|
bca718 |
- return c1 - c2;
|
|
|
bca718 |
+ return 0;
|
|
|
bca718 |
}
|
|
|
bca718 |
--
|
|
|
bca718 |
2.3.0
|
|
|
bca718 |
|