Merge remote-tracking branch 'vfio/next'
[deliverable/linux.git] / arch / arm / lib / memset.S
CommitLineData
1da177e4
LT
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>
c2459d35 14#include <asm/unwind.h>
4dd1837d 15#include <asm/export.h>
1da177e4
LT
16
17 .text
18 .align 5
1da177e4 19
1bd46782 20ENTRY(mmioset)
1da177e4 21ENTRY(memset)
c2459d35 22UNWIND( .fnstart )
418df63a
NP
23 ands r3, r0, #3 @ 1 unaligned?
24 mov ip, r0 @ preserve r0 as return value
25 bne 6f @ 1
1da177e4 26/*
455bd4c4 27 * we know that the pointer in ip is aligned to a word boundary.
1da177e4 28 */
418df63a 291: orr r1, r1, r1, lsl #8
1da177e4
LT
30 orr r1, r1, r1, lsl #16
31 mov r3, r1
32 cmp r2, #16
33 blt 4f
f91a8dcc
NP
34
35#if ! CALGN(1)+0
36
1da177e4 37/*
455bd4c4 38 * We need 2 extra registers for this loop - use r8 and the LR
1da177e4 39 */
455bd4c4 40 stmfd sp!, {r8, lr}
c2459d35
LY
41UNWIND( .fnend )
42UNWIND( .fnstart )
43UNWIND( .save {r8, lr} )
455bd4c4 44 mov r8, r1
1da177e4
LT
45 mov lr, r1
46
472: subs r2, r2, #64
455bd4c4
ID
48 stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
49 stmgeia ip!, {r1, r3, r8, lr}
50 stmgeia ip!, {r1, r3, r8, lr}
51 stmgeia ip!, {r1, r3, r8, lr}
1da177e4 52 bgt 2b
455bd4c4 53 ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
1da177e4
LT
54/*
55 * No need to correct the count; we're only testing bits from now on
56 */
57 tst r2, #32
455bd4c4
ID
58 stmneia ip!, {r1, r3, r8, lr}
59 stmneia ip!, {r1, r3, r8, lr}
1da177e4 60 tst r2, #16
455bd4c4
ID
61 stmneia ip!, {r1, r3, r8, lr}
62 ldmfd sp!, {r8, lr}
c2459d35 63UNWIND( .fnend )
1da177e4 64
f91a8dcc
NP
65#else
66
67/*
68 * This version aligns the destination pointer in order to write
69 * whole cache lines at once.
70 */
71
455bd4c4 72 stmfd sp!, {r4-r8, lr}
c2459d35
LY
73UNWIND( .fnend )
74UNWIND( .fnstart )
75UNWIND( .save {r4-r8, lr} )
f91a8dcc
NP
76 mov r4, r1
77 mov r5, r1
78 mov r6, r1
79 mov r7, r1
455bd4c4 80 mov r8, r1
f91a8dcc
NP
81 mov lr, r1
82
83 cmp r2, #96
455bd4c4 84 tstgt ip, #31
f91a8dcc
NP
85 ble 3f
86
455bd4c4
ID
87 and r8, ip, #31
88 rsb r8, r8, #32
89 sub r2, r2, r8
90 movs r8, r8, lsl #(32 - 4)
91 stmcsia ip!, {r4, r5, r6, r7}
92 stmmiia ip!, {r4, r5}
93 tst r8, #(1 << 30)
94 mov r8, r1
95 strne r1, [ip], #4
f91a8dcc
NP
96
973: subs r2, r2, #64
455bd4c4
ID
98 stmgeia ip!, {r1, r3-r8, lr}
99 stmgeia ip!, {r1, r3-r8, lr}
f91a8dcc 100 bgt 3b
455bd4c4 101 ldmeqfd sp!, {r4-r8, pc}
f91a8dcc
NP
102
103 tst r2, #32
455bd4c4 104 stmneia ip!, {r1, r3-r8, lr}
f91a8dcc 105 tst r2, #16
455bd4c4
ID
106 stmneia ip!, {r4-r7}
107 ldmfd sp!, {r4-r8, lr}
c2459d35 108UNWIND( .fnend )
f91a8dcc
NP
109
110#endif
111
c2459d35 112UNWIND( .fnstart )
1da177e4 1134: tst r2, #8
455bd4c4 114 stmneia ip!, {r1, r3}
1da177e4 115 tst r2, #4
455bd4c4 116 strne r1, [ip], #4
1da177e4
LT
117/*
118 * When we get here, we've got less than 4 bytes to zero. We
119 * may have an unaligned pointer as well.
120 */
1215: tst r2, #2
455bd4c4
ID
122 strneb r1, [ip], #1
123 strneb r1, [ip], #1
1da177e4 124 tst r2, #1
455bd4c4 125 strneb r1, [ip], #1
6ebbf2ce 126 ret lr
418df63a
NP
127
1286: subs r2, r2, #4 @ 1 do we have enough
129 blt 5b @ 1 bytes to align with?
130 cmp r3, #2 @ 1
131 strltb r1, [ip], #1 @ 1
132 strleb r1, [ip], #1 @ 1
133 strb r1, [ip], #1 @ 1
134 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
135 b 1b
c2459d35 136UNWIND( .fnend )
93ed3970 137ENDPROC(memset)
1bd46782 138ENDPROC(mmioset)
4dd1837d
AV
139EXPORT_SYMBOL(memset)
140EXPORT_SYMBOL(mmioset)
This page took 0.783534 seconds and 5 git commands to generate.