memset.S 2.9 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0-only */
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10
/*
 *  linux/arch/arm/lib/memset.S
 *
 *  Copyright (C) 1995-2000 Russell King
 *
 *  ASM optimised string functions
 */
#include <linux/linkage.h>
#include <asm/assembler.h>
11
#include <asm/unwind.h>
L
Linus Torvalds 已提交
12 13 14 15

	.text
	.align	5

16 17
.weak memset
ENTRY(__memset)
18
ENTRY(mmioset)
L
Linus Torvalds 已提交
19
ENTRY(memset)
20
UNWIND( .fnstart         )
N
Nicolas Pitre 已提交
21 22 23
	ands	r3, r0, #3		@ 1 unaligned?
	mov	ip, r0			@ preserve r0 as return value
	bne	6f			@ 1
L
Linus Torvalds 已提交
24
/*
25
 * we know that the pointer in ip is aligned to a word boundary.
L
Linus Torvalds 已提交
26
 */
N
Nicolas Pitre 已提交
27
1:	orr	r1, r1, r1, lsl #8
L
Linus Torvalds 已提交
28 29
	orr	r1, r1, r1, lsl #16
	mov	r3, r1
30
7:	cmp	r2, #16
L
Linus Torvalds 已提交
31
	blt	4f
32 33 34

#if ! CALGN(1)+0

L
Linus Torvalds 已提交
35
/*
36
 * We need 2 extra registers for this loop - use r8 and the LR
L
Linus Torvalds 已提交
37
 */
38
	stmfd	sp!, {r8, lr}
39 40 41
UNWIND( .fnend              )
UNWIND( .fnstart            )
UNWIND( .save {r8, lr}      )
42
	mov	r8, r1
43
	mov	lr, r3
L
Linus Torvalds 已提交
44 45

2:	subs	r2, r2, #64
46 47 48 49
	stmiage	ip!, {r1, r3, r8, lr}	@ 64 bytes at a time.
	stmiage	ip!, {r1, r3, r8, lr}
	stmiage	ip!, {r1, r3, r8, lr}
	stmiage	ip!, {r1, r3, r8, lr}
L
Linus Torvalds 已提交
50
	bgt	2b
51
	ldmfdeq	sp!, {r8, pc}		@ Now <64 bytes to go.
L
Linus Torvalds 已提交
52 53 54 55
/*
 * No need to correct the count; we're only testing bits from now on
 */
	tst	r2, #32
56 57
	stmiane	ip!, {r1, r3, r8, lr}
	stmiane	ip!, {r1, r3, r8, lr}
L
Linus Torvalds 已提交
58
	tst	r2, #16
59
	stmiane	ip!, {r1, r3, r8, lr}
60
	ldmfd	sp!, {r8, lr}
61
UNWIND( .fnend              )
L
Linus Torvalds 已提交
62

63 64 65 66 67 68 69
#else

/*
 * This version aligns the destination pointer in order to write
 * whole cache lines at once.
 */

70
	stmfd	sp!, {r4-r8, lr}
71 72 73
UNWIND( .fnend                 )
UNWIND( .fnstart               )
UNWIND( .save {r4-r8, lr}      )
74
	mov	r4, r1
75
	mov	r5, r3
76
	mov	r6, r1
77
	mov	r7, r3
78
	mov	r8, r1
79
	mov	lr, r3
80 81

	cmp	r2, #96
82
	tstgt	ip, #31
83 84
	ble	3f

85 86 87 88
	and	r8, ip, #31
	rsb	r8, r8, #32
	sub	r2, r2, r8
	movs	r8, r8, lsl #(32 - 4)
89 90
	stmiacs	ip!, {r4, r5, r6, r7}
	stmiami	ip!, {r4, r5}
91 92 93
	tst	r8, #(1 << 30)
	mov	r8, r1
	strne	r1, [ip], #4
94 95

3:	subs	r2, r2, #64
96 97
	stmiage	ip!, {r1, r3-r8, lr}
	stmiage	ip!, {r1, r3-r8, lr}
98
	bgt	3b
99
	ldmfdeq	sp!, {r4-r8, pc}
100 101

	tst	r2, #32
102
	stmiane	ip!, {r1, r3-r8, lr}
103
	tst	r2, #16
104
	stmiane	ip!, {r4-r7}
105
	ldmfd	sp!, {r4-r8, lr}
106
UNWIND( .fnend                 )
107 108 109

#endif

110
UNWIND( .fnstart            )
L
Linus Torvalds 已提交
111
4:	tst	r2, #8
112
	stmiane	ip!, {r1, r3}
L
Linus Torvalds 已提交
113
	tst	r2, #4
114
	strne	r1, [ip], #4
L
Linus Torvalds 已提交
115
/*
116
 * When we get here, we've got less than 4 bytes to set.  We
L
Linus Torvalds 已提交
117 118 119
 * may have an unaligned pointer as well.
 */
5:	tst	r2, #2
120 121
	strbne	r1, [ip], #1
	strbne	r1, [ip], #1
L
Linus Torvalds 已提交
122
	tst	r2, #1
123
	strbne	r1, [ip], #1
124
	ret	lr
N
Nicolas Pitre 已提交
125 126 127 128

6:	subs	r2, r2, #4		@ 1 do we have enough
	blt	5b			@ 1 bytes to align with?
	cmp	r3, #2			@ 1
129 130
	strblt	r1, [ip], #1		@ 1
	strble	r1, [ip], #1		@ 1
N
Nicolas Pitre 已提交
131 132 133
	strb	r1, [ip], #1		@ 1
	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
	b	1b
134
UNWIND( .fnend   )
135
ENDPROC(memset)
136
ENDPROC(mmioset)
137
ENDPROC(__memset)
138 139 140 141 142 143 144 145 146 147 148 149

ENTRY(__memset32)
UNWIND( .fnstart         )
	mov	r3, r1			@ copy r1 to r3 and fall into memset64
UNWIND( .fnend   )
ENDPROC(__memset32)
ENTRY(__memset64)
UNWIND( .fnstart         )
	mov	ip, r0			@ preserve r0 as return value
	b	7b			@ jump into the middle of memset
UNWIND( .fnend   )
ENDPROC(__memset64)