aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2019-02-06 17:21:10 -0500
committerHelge Deller <deller@gmx.de>2019-08-03 02:56:57 -0400
commit83af58f8068ea3f7b3c537c37a30887bfa585069 (patch)
treece1b09ba9adda2675dd7486bc53e4a2fb79f6853 /arch/parisc
parentec4d396b635070e0caf5888d58cb9eedc8dd73d9 (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.h15
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c4
-rw-r--r--arch/parisc/lib/Makefile4
-rw-r--r--arch/parisc/lib/memset.c91
-rw-r--r--arch/parisc/lib/string.S136
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
9void * memcpy(void * dest,const void *src,size_t count); 9void * memcpy(void * dest,const void *src,size_t count);
10 10
11#define __HAVE_ARCH_STRLEN
12extern size_t strlen(const char *s);
13
14#define __HAVE_ARCH_STRCPY
15extern char *strcpy(char *dest, const char *src);
16
17#define __HAVE_ARCH_STRNCPY
18extern char *strncpy(char *dest, const char *src, size_t count);
19
20#define __HAVE_ARCH_STRCAT
21extern char *strcat(char *dest, const char *src);
22
23#define __HAVE_ARCH_MEMSET
24extern 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>
19EXPORT_SYMBOL(memset); 19EXPORT_SYMBOL(memset);
20EXPORT_SYMBOL(strlen);
21EXPORT_SYMBOL(strcpy);
22EXPORT_SYMBOL(strncpy);
23EXPORT_SYMBOL(strcat);
20 24
21#include <linux/atomic.h> 25#include <linux/atomic.h>
22EXPORT_SYMBOL(__xchg8); 26EXPORT_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
6lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \ 6lib-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
9obj-y := iomap.o 9obj-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)
25typedef unsigned long op_t;
26
27void *
28memset (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
18ENTRY_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)
49ENDPROC_CFI(strlen)
50
51
52ENTRY_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
591: ldb 0(t1),arg1
60 stb arg1,0(t2)
61 ldo 1(t1),t1
62 cmpb,<> r0,arg1,1b
63 ldo 1(t2),t2
642: bv,n r0(rp)
65ENDPROC_CFI(strcpy)
66
67
68ENTRY_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
751: 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
822: bv,n r0(rp)
83ENDPROC_CFI(strncpy)
84
85
86ENTRY_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
911: ldb 0(arg0),t1
92 cmpb,<>,n r0,t1,1b
93 ldo 1(arg0),arg0
942: 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)
101ENDPROC_CFI(strcat)
102
103
104ENTRY_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
1152: 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
1273: 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
1334: bv,n r0(rp)
134ENDPROC_CFI(memset)
135
136 .end