diff options
author | Helge Deller <deller@gmx.de> | 2019-02-06 17:21:10 -0500 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2019-08-03 02:56:57 -0400 |
commit | 83af58f8068ea3f7b3c537c37a30887bfa585069 (patch) | |
tree | ce1b09ba9adda2675dd7486bc53e4a2fb79f6853 /arch/parisc | |
parent | ec4d396b635070e0caf5888d58cb9eedc8dd73d9 (diff) |
parisc: Add assembly implementations for memset, strlen, strcpy, strncpy and strcat
Add performance-optimized versions of some string functions.
Signed-off-by: Helge Deller <deller@gmx.de>
Tested-by: Sven Schnelle <svens@stackframe.org>
Diffstat (limited to 'arch/parisc')
-rw-r--r-- | arch/parisc/include/asm/string.h | 15 | ||||
-rw-r--r-- | arch/parisc/kernel/parisc_ksyms.c | 4 | ||||
-rw-r--r-- | arch/parisc/lib/Makefile | 4 | ||||
-rw-r--r-- | arch/parisc/lib/memset.c | 91 | ||||
-rw-r--r-- | arch/parisc/lib/string.S | 136 |
5 files changed, 157 insertions, 93 deletions
diff --git a/arch/parisc/include/asm/string.h b/arch/parisc/include/asm/string.h index f6e1132f4e35..4a0c9dbd62fd 100644 --- a/arch/parisc/include/asm/string.h +++ b/arch/parisc/include/asm/string.h | |||
@@ -8,4 +8,19 @@ extern void * memset(void *, int, size_t); | |||
8 | #define __HAVE_ARCH_MEMCPY | 8 | #define __HAVE_ARCH_MEMCPY |
9 | void * memcpy(void * dest,const void *src,size_t count); | 9 | void * memcpy(void * dest,const void *src,size_t count); |
10 | 10 | ||
11 | #define __HAVE_ARCH_STRLEN | ||
12 | extern size_t strlen(const char *s); | ||
13 | |||
14 | #define __HAVE_ARCH_STRCPY | ||
15 | extern char *strcpy(char *dest, const char *src); | ||
16 | |||
17 | #define __HAVE_ARCH_STRNCPY | ||
18 | extern char *strncpy(char *dest, const char *src, size_t count); | ||
19 | |||
20 | #define __HAVE_ARCH_STRCAT | ||
21 | extern char *strcat(char *dest, const char *src); | ||
22 | |||
23 | #define __HAVE_ARCH_MEMSET | ||
24 | extern void *memset(void *, int, size_t); | ||
25 | |||
11 | #endif | 26 | #endif |
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index e8a6a751dfd8..8ed409ecec93 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
@@ -17,6 +17,10 @@ | |||
17 | 17 | ||
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | EXPORT_SYMBOL(memset); | 19 | EXPORT_SYMBOL(memset); |
20 | EXPORT_SYMBOL(strlen); | ||
21 | EXPORT_SYMBOL(strcpy); | ||
22 | EXPORT_SYMBOL(strncpy); | ||
23 | EXPORT_SYMBOL(strcat); | ||
20 | 24 | ||
21 | #include <linux/atomic.h> | 25 | #include <linux/atomic.h> |
22 | EXPORT_SYMBOL(__xchg8); | 26 | EXPORT_SYMBOL(__xchg8); |
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 7b197667faf6..2d7a9974dbae 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # Makefile for parisc-specific library files | 3 | # Makefile for parisc-specific library files |
4 | # | 4 | # |
5 | 5 | ||
6 | lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \ | 6 | lib-y := lusercopy.o bitops.o checksum.o io.o memcpy.o \ |
7 | ucmpdi2.o delay.o | 7 | ucmpdi2.o delay.o string.o |
8 | 8 | ||
9 | obj-y := iomap.o | 9 | obj-y := iomap.o |
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c deleted file mode 100644 index 1d7929bd7642..000000000000 --- a/arch/parisc/lib/memset.c +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /* Copyright (C) 1991, 1997 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | |||
4 | The GNU C Library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 2.1 of the License, or (at your option) any later version. | ||
8 | |||
9 | The GNU C Library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with the GNU C Library; if not, write to the Free | ||
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
17 | 02111-1307 USA. */ | ||
18 | |||
19 | /* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <asm/string.h> | ||
23 | |||
24 | #define OPSIZ (BITS_PER_LONG/8) | ||
25 | typedef unsigned long op_t; | ||
26 | |||
27 | void * | ||
28 | memset (void *dstpp, int sc, size_t len) | ||
29 | { | ||
30 | unsigned int c = sc; | ||
31 | long int dstp = (long int) dstpp; | ||
32 | |||
33 | if (len >= 8) | ||
34 | { | ||
35 | size_t xlen; | ||
36 | op_t cccc; | ||
37 | |||
38 | cccc = (unsigned char) c; | ||
39 | cccc |= cccc << 8; | ||
40 | cccc |= cccc << 16; | ||
41 | if (OPSIZ > 4) | ||
42 | /* Do the shift in two steps to avoid warning if long has 32 bits. */ | ||
43 | cccc |= (cccc << 16) << 16; | ||
44 | |||
45 | /* There are at least some bytes to set. | ||
46 | No need to test for LEN == 0 in this alignment loop. */ | ||
47 | while (dstp % OPSIZ != 0) | ||
48 | { | ||
49 | ((unsigned char *) dstp)[0] = c; | ||
50 | dstp += 1; | ||
51 | len -= 1; | ||
52 | } | ||
53 | |||
54 | /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ | ||
55 | xlen = len / (OPSIZ * 8); | ||
56 | while (xlen > 0) | ||
57 | { | ||
58 | ((op_t *) dstp)[0] = cccc; | ||
59 | ((op_t *) dstp)[1] = cccc; | ||
60 | ((op_t *) dstp)[2] = cccc; | ||
61 | ((op_t *) dstp)[3] = cccc; | ||
62 | ((op_t *) dstp)[4] = cccc; | ||
63 | ((op_t *) dstp)[5] = cccc; | ||
64 | ((op_t *) dstp)[6] = cccc; | ||
65 | ((op_t *) dstp)[7] = cccc; | ||
66 | dstp += 8 * OPSIZ; | ||
67 | xlen -= 1; | ||
68 | } | ||
69 | len %= OPSIZ * 8; | ||
70 | |||
71 | /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ | ||
72 | xlen = len / OPSIZ; | ||
73 | while (xlen > 0) | ||
74 | { | ||
75 | ((op_t *) dstp)[0] = cccc; | ||
76 | dstp += OPSIZ; | ||
77 | xlen -= 1; | ||
78 | } | ||
79 | len %= OPSIZ; | ||
80 | } | ||
81 | |||
82 | /* Write the last few bytes. */ | ||
83 | while (len > 0) | ||
84 | { | ||
85 | ((unsigned char *) dstp)[0] = c; | ||
86 | dstp += 1; | ||
87 | len -= 1; | ||
88 | } | ||
89 | |||
90 | return dstpp; | ||
91 | } | ||
diff --git a/arch/parisc/lib/string.S b/arch/parisc/lib/string.S new file mode 100644 index 000000000000..4a64264427a6 --- /dev/null +++ b/arch/parisc/lib/string.S | |||
@@ -0,0 +1,136 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * PA-RISC assembly string functions | ||
4 | * | ||
5 | * Copyright (C) 2019 Helge Deller <deller@gmx.de> | ||
6 | */ | ||
7 | |||
8 | #include <asm/assembly.h> | ||
9 | #include <linux/linkage.h> | ||
10 | |||
11 | .section .text.hot | ||
12 | .level PA_ASM_LEVEL | ||
13 | |||
14 | t0 = r20 | ||
15 | t1 = r21 | ||
16 | t2 = r22 | ||
17 | |||
18 | ENTRY_CFI(strlen, frame=0,no_calls) | ||
19 | or,COND(<>) arg0,r0,ret0 | ||
20 | b,l,n .Lstrlen_null_ptr,r0 | ||
21 | depwi 0,31,2,ret0 | ||
22 | cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned | ||
23 | ldw,ma 4(ret0),t0 | ||
24 | cmpib,tr 0,r0,.Lstrlen_loop | ||
25 | uxor,nbz r0,t0,r0 | ||
26 | .Lstrlen_not_aligned: | ||
27 | uaddcm arg0,ret0,t1 | ||
28 | shladd t1,3,r0,t1 | ||
29 | mtsar t1 | ||
30 | depwi -1,%sar,32,t0 | ||
31 | uxor,nbz r0,t0,r0 | ||
32 | .Lstrlen_loop: | ||
33 | b,l,n .Lstrlen_end_loop,r0 | ||
34 | ldw,ma 4(ret0),t0 | ||
35 | cmpib,tr 0,r0,.Lstrlen_loop | ||
36 | uxor,nbz r0,t0,r0 | ||
37 | .Lstrlen_end_loop: | ||
38 | extrw,u,<> t0,7,8,r0 | ||
39 | addib,tr,n -3,ret0,.Lstrlen_out | ||
40 | extrw,u,<> t0,15,8,r0 | ||
41 | addib,tr,n -2,ret0,.Lstrlen_out | ||
42 | extrw,u,<> t0,23,8,r0 | ||
43 | addi -1,ret0,ret0 | ||
44 | .Lstrlen_out: | ||
45 | bv r0(rp) | ||
46 | uaddcm ret0,arg0,ret0 | ||
47 | .Lstrlen_null_ptr: | ||
48 | bv,n r0(rp) | ||
49 | ENDPROC_CFI(strlen) | ||
50 | |||
51 | |||
52 | ENTRY_CFI(strcpy, frame=0,no_calls) | ||
53 | ldb 0(arg1),t0 | ||
54 | stb t0,0(arg0) | ||
55 | ldo 0(arg0),ret0 | ||
56 | ldo 1(arg1),t1 | ||
57 | cmpb,= r0,t0,2f | ||
58 | ldo 1(arg0),t2 | ||
59 | 1: ldb 0(t1),arg1 | ||
60 | stb arg1,0(t2) | ||
61 | ldo 1(t1),t1 | ||
62 | cmpb,<> r0,arg1,1b | ||
63 | ldo 1(t2),t2 | ||
64 | 2: bv,n r0(rp) | ||
65 | ENDPROC_CFI(strcpy) | ||
66 | |||
67 | |||
68 | ENTRY_CFI(strncpy, frame=0,no_calls) | ||
69 | ldb 0(arg1),t0 | ||
70 | stb t0,0(arg0) | ||
71 | ldo 1(arg1),t1 | ||
72 | ldo 0(arg0),ret0 | ||
73 | cmpb,= r0,t0,2f | ||
74 | ldo 1(arg0),arg1 | ||
75 | 1: ldo -1(arg2),arg2 | ||
76 | cmpb,COND(=),n r0,arg2,2f | ||
77 | ldb 0(t1),arg0 | ||
78 | stb arg0,0(arg1) | ||
79 | ldo 1(t1),t1 | ||
80 | cmpb,<> r0,arg0,1b | ||
81 | ldo 1(arg1),arg1 | ||
82 | 2: bv,n r0(rp) | ||
83 | ENDPROC_CFI(strncpy) | ||
84 | |||
85 | |||
86 | ENTRY_CFI(strcat, frame=0,no_calls) | ||
87 | ldb 0(arg0),t0 | ||
88 | cmpb,= t0,r0,2f | ||
89 | ldo 0(arg0),ret0 | ||
90 | ldo 1(arg0),arg0 | ||
91 | 1: ldb 0(arg0),t1 | ||
92 | cmpb,<>,n r0,t1,1b | ||
93 | ldo 1(arg0),arg0 | ||
94 | 2: ldb 0(arg1),t2 | ||
95 | stb t2,0(arg0) | ||
96 | ldo 1(arg0),arg0 | ||
97 | ldb 0(arg1),t0 | ||
98 | cmpb,<> r0,t0,2b | ||
99 | ldo 1(arg1),arg1 | ||
100 | bv,n r0(rp) | ||
101 | ENDPROC_CFI(strcat) | ||
102 | |||
103 | |||
104 | ENTRY_CFI(memset, frame=0,no_calls) | ||
105 | copy arg0,ret0 | ||
106 | cmpb,COND(=) r0,arg0,4f | ||
107 | copy arg0,t2 | ||
108 | cmpb,COND(=) r0,arg2,4f | ||
109 | ldo -1(arg2),arg3 | ||
110 | subi -1,arg3,t0 | ||
111 | subi 0,t0,t1 | ||
112 | cmpiclr,COND(>=) 0,t1,arg2 | ||
113 | ldo -1(t1),arg2 | ||
114 | extru arg2,31,2,arg0 | ||
115 | 2: stb arg1,0(t2) | ||
116 | ldo 1(t2),t2 | ||
117 | addib,>= -1,arg0,2b | ||
118 | ldo -1(arg3),arg3 | ||
119 | cmpiclr,COND(<=) 4,arg2,r0 | ||
120 | b,l,n 4f,r0 | ||
121 | #ifdef CONFIG_64BIT | ||
122 | depd,* r0,63,2,arg2 | ||
123 | #else | ||
124 | depw r0,31,2,arg2 | ||
125 | #endif | ||
126 | ldo 1(t2),t2 | ||
127 | 3: stb arg1,-1(t2) | ||
128 | stb arg1,0(t2) | ||
129 | stb arg1,1(t2) | ||
130 | stb arg1,2(t2) | ||
131 | addib,COND(>) -4,arg2,3b | ||
132 | ldo 4(t2),t2 | ||
133 | 4: bv,n r0(rp) | ||
134 | ENDPROC_CFI(memset) | ||
135 | |||
136 | .end | ||