1/*
2 *  linux/arch/arm/lib/memset.S
3 *
4 *  Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 *  ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15	.text
16	.align	5
17
18ENTRY(memset)
19	ands	r3, r0, #3		@ 1 unaligned?
20	mov	ip, r0			@ preserve r0 as return value
21	bne	6f			@ 1
22/*
23 * we know that the pointer in ip is aligned to a word boundary.
24 */
251:	orr	r1, r1, r1, lsl #8
26	orr	r1, r1, r1, lsl #16
27	mov	r3, r1
28	cmp	r2, #16
29	blt	4f
30
31#if ! CALGN(1)+0
32
33/*
34 * We need 2 extra registers for this loop - use r8 and the LR
35 */
36	stmfd	sp!, {r8, lr}
37	mov	r8, r1
38	mov	lr, r1
39
402:	subs	r2, r2, #64
41	stmgeia	ip!, {r1, r3, r8, lr}	@ 64 bytes at a time.
42	stmgeia	ip!, {r1, r3, r8, lr}
43	stmgeia	ip!, {r1, r3, r8, lr}
44	stmgeia	ip!, {r1, r3, r8, lr}
45	bgt	2b
46	ldmeqfd	sp!, {r8, pc}		@ Now <64 bytes to go.
47/*
48 * No need to correct the count; we're only testing bits from now on
49 */
50	tst	r2, #32
51	stmneia	ip!, {r1, r3, r8, lr}
52	stmneia	ip!, {r1, r3, r8, lr}
53	tst	r2, #16
54	stmneia	ip!, {r1, r3, r8, lr}
55	ldmfd	sp!, {r8, lr}
56
57#else
58
59/*
60 * This version aligns the destination pointer in order to write
61 * whole cache lines at once.
62 */
63
64	stmfd	sp!, {r4-r8, lr}
65	mov	r4, r1
66	mov	r5, r1
67	mov	r6, r1
68	mov	r7, r1
69	mov	r8, r1
70	mov	lr, r1
71
72	cmp	r2, #96
73	tstgt	ip, #31
74	ble	3f
75
76	and	r8, ip, #31
77	rsb	r8, r8, #32
78	sub	r2, r2, r8
79	movs	r8, r8, lsl #(32 - 4)
80	stmcsia	ip!, {r4, r5, r6, r7}
81	stmmiia	ip!, {r4, r5}
82	tst	r8, #(1 << 30)
83	mov	r8, r1
84	strne	r1, [ip], #4
85
863:	subs	r2, r2, #64
87	stmgeia	ip!, {r1, r3-r8, lr}
88	stmgeia	ip!, {r1, r3-r8, lr}
89	bgt	3b
90	ldmeqfd	sp!, {r4-r8, pc}
91
92	tst	r2, #32
93	stmneia	ip!, {r1, r3-r8, lr}
94	tst	r2, #16
95	stmneia	ip!, {r4-r7}
96	ldmfd	sp!, {r4-r8, lr}
97
98#endif
99
1004:	tst	r2, #8
101	stmneia	ip!, {r1, r3}
102	tst	r2, #4
103	strne	r1, [ip], #4
104/*
105 * When we get here, we've got less than 4 bytes to zero.  We
106 * may have an unaligned pointer as well.
107 */
1085:	tst	r2, #2
109	strneb	r1, [ip], #1
110	strneb	r1, [ip], #1
111	tst	r2, #1
112	strneb	r1, [ip], #1
113	mov	pc, lr
114
1156:	subs	r2, r2, #4		@ 1 do we have enough
116	blt	5b			@ 1 bytes to align with?
117	cmp	r3, #2			@ 1
118	strltb	r1, [ip], #1		@ 1
119	strleb	r1, [ip], #1		@ 1
120	strb	r1, [ip], #1		@ 1
121	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
122	b	1b
123ENDPROC(memset)
124