aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lib/memset.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/lib/memset.S')
-rw-r--r--arch/mips/lib/memset.S146
1 files changed, 95 insertions, 51 deletions
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 0580194e7402..7b0e5462ca51 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -34,13 +34,27 @@
34#define FILLPTRG t0 34#define FILLPTRG t0
35#endif 35#endif
36 36
37#define LEGACY_MODE 1
38#define EVA_MODE 2
39
40/*
41 * No need to protect it with EVA #ifdefery. The generated block of code
42 * will never be assembled if EVA is not enabled.
43 */
44#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
45#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
46
37#define EX(insn,reg,addr,handler) \ 47#define EX(insn,reg,addr,handler) \
389: insn reg, addr; \ 48 .if \mode == LEGACY_MODE; \
499: insn reg, addr; \
50 .else; \
519: ___BUILD_EVA_INSN(insn, reg, addr); \
52 .endif; \
39 .section __ex_table,"a"; \ 53 .section __ex_table,"a"; \
40 PTR 9b, handler; \ 54 PTR 9b, handler; \
41 .previous 55 .previous
42 56
43 .macro f_fill64 dst, offset, val, fixup 57 .macro f_fill64 dst, offset, val, fixup, mode
44 EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) 58 EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup)
45 EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) 59 EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup)
46 EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) 60 EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup)
@@ -63,34 +77,24 @@
63#endif 77#endif
64 .endm 78 .endm
65 79
66/*
67 * memset(void *s, int c, size_t n)
68 *
69 * a0: start of area to clear
70 * a1: char to fill with
71 * a2: size of area to clear
72 */
73 .set noreorder 80 .set noreorder
74 .align 5 81 .align 5
75LEAF(memset)
76 beqz a1, 1f
77 move v0, a0 /* result */
78 82
79 andi a1, 0xff /* spread fillword */ 83 /*
80 LONG_SLL t1, a1, 8 84 * Macro to generate the __bzero{,_user} symbol
81 or a1, t1 85 * Arguments:
82 LONG_SLL t1, a1, 16 86 * mode: LEGACY_MODE or EVA_MODE
83#if LONGSIZE == 8 87 */
84 or a1, t1 88 .macro __BUILD_BZERO mode
85 LONG_SLL t1, a1, 32 89 /* Initialize __memset if this is the first time we call this macro */
86#endif 90 .ifnotdef __memset
87 or a1, t1 91 .set __memset, 1
881: 92 .hidden __memset /* Make sure it does not leak */
93 .endif
89 94
90FEXPORT(__bzero)
91 sltiu t0, a2, STORSIZE /* very small region? */ 95 sltiu t0, a2, STORSIZE /* very small region? */
92 bnez t0, .Lsmall_memset 96 bnez t0, .Lsmall_memset\@
93 andi t0, a0, STORMASK /* aligned? */ 97 andi t0, a0, STORMASK /* aligned? */
94 98
95#ifdef CONFIG_CPU_MICROMIPS 99#ifdef CONFIG_CPU_MICROMIPS
96 move t8, a1 /* used by 'swp' instruction */ 100 move t8, a1 /* used by 'swp' instruction */
@@ -98,39 +102,39 @@ FEXPORT(__bzero)
98#endif 102#endif
99#ifndef CONFIG_CPU_DADDI_WORKAROUNDS 103#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
100 beqz t0, 1f 104 beqz t0, 1f
101 PTR_SUBU t0, STORSIZE /* alignment in bytes */ 105 PTR_SUBU t0, STORSIZE /* alignment in bytes */
102#else 106#else
103 .set noat 107 .set noat
104 li AT, STORSIZE 108 li AT, STORSIZE
105 beqz t0, 1f 109 beqz t0, 1f
106 PTR_SUBU t0, AT /* alignment in bytes */ 110 PTR_SUBU t0, AT /* alignment in bytes */
107 .set at 111 .set at
108#endif 112#endif
109 113
110 R10KCBARRIER(0(ra)) 114 R10KCBARRIER(0(ra))
111#ifdef __MIPSEB__ 115#ifdef __MIPSEB__
112 EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ 116 EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
113#endif 117#endif
114#ifdef __MIPSEL__ 118#ifdef __MIPSEL__
115 EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ 119 EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
116#endif 120#endif
117 PTR_SUBU a0, t0 /* long align ptr */ 121 PTR_SUBU a0, t0 /* long align ptr */
118 PTR_ADDU a2, t0 /* correct size */ 122 PTR_ADDU a2, t0 /* correct size */
119 123
1201: ori t1, a2, 0x3f /* # of full blocks */ 1241: ori t1, a2, 0x3f /* # of full blocks */
121 xori t1, 0x3f 125 xori t1, 0x3f
122 beqz t1, .Lmemset_partial /* no block to fill */ 126 beqz t1, .Lmemset_partial\@ /* no block to fill */
123 andi t0, a2, 0x40-STORSIZE 127 andi t0, a2, 0x40-STORSIZE
124 128
125 PTR_ADDU t1, a0 /* end address */ 129 PTR_ADDU t1, a0 /* end address */
126 .set reorder 130 .set reorder
1271: PTR_ADDIU a0, 64 1311: PTR_ADDIU a0, 64
128 R10KCBARRIER(0(ra)) 132 R10KCBARRIER(0(ra))
129 f_fill64 a0, -64, FILL64RG, .Lfwd_fixup 133 f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
130 bne t1, a0, 1b 134 bne t1, a0, 1b
131 .set noreorder 135 .set noreorder
132 136
133.Lmemset_partial: 137.Lmemset_partial\@:
134 R10KCBARRIER(0(ra)) 138 R10KCBARRIER(0(ra))
135 PTR_LA t1, 2f /* where to start */ 139 PTR_LA t1, 2f /* where to start */
136#ifdef CONFIG_CPU_MICROMIPS 140#ifdef CONFIG_CPU_MICROMIPS
@@ -145,60 +149,100 @@ FEXPORT(__bzero)
145 .set at 149 .set at
146#endif 150#endif
147 jr t1 151 jr t1
148 PTR_ADDU a0, t0 /* dest ptr */ 152 PTR_ADDU a0, t0 /* dest ptr */
149 153
150 .set push 154 .set push
151 .set noreorder 155 .set noreorder
152 .set nomacro 156 .set nomacro
153 f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */ 157 /* ... but first do longs ... */
158 f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
1542: .set pop 1592: .set pop
155 andi a2, STORMASK /* At most one long to go */ 160 andi a2, STORMASK /* At most one long to go */
156 161
157 beqz a2, 1f 162 beqz a2, 1f
158 PTR_ADDU a0, a2 /* What's left */ 163 PTR_ADDU a0, a2 /* What's left */
159 R10KCBARRIER(0(ra)) 164 R10KCBARRIER(0(ra))
160#ifdef __MIPSEB__ 165#ifdef __MIPSEB__
161 EX(LONG_S_R, a1, -1(a0), .Llast_fixup) 166 EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
162#endif 167#endif
163#ifdef __MIPSEL__ 168#ifdef __MIPSEL__
164 EX(LONG_S_L, a1, -1(a0), .Llast_fixup) 169 EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
165#endif 170#endif
1661: jr ra 1711: jr ra
167 move a2, zero 172 move a2, zero
168 173
169.Lsmall_memset: 174.Lsmall_memset\@:
170 beqz a2, 2f 175 beqz a2, 2f
171 PTR_ADDU t1, a0, a2 176 PTR_ADDU t1, a0, a2
172 177
1731: PTR_ADDIU a0, 1 /* fill bytewise */ 1781: PTR_ADDIU a0, 1 /* fill bytewise */
174 R10KCBARRIER(0(ra)) 179 R10KCBARRIER(0(ra))
175 bne t1, a0, 1b 180 bne t1, a0, 1b
176 sb a1, -1(a0) 181 sb a1, -1(a0)
177 182
1782: jr ra /* done */ 1832: jr ra /* done */
179 move a2, zero 184 move a2, zero
185 .if __memset == 1
180 END(memset) 186 END(memset)
187 .set __memset, 0
188 .hidden __memset
189 .endif
181 190
182.Lfirst_fixup: 191.Lfirst_fixup\@:
183 jr ra 192 jr ra
184 nop 193 nop
185 194
186.Lfwd_fixup: 195.Lfwd_fixup\@:
187 PTR_L t0, TI_TASK($28) 196 PTR_L t0, TI_TASK($28)
188 andi a2, 0x3f 197 andi a2, 0x3f
189 LONG_L t0, THREAD_BUADDR(t0) 198 LONG_L t0, THREAD_BUADDR(t0)
190 LONG_ADDU a2, t1 199 LONG_ADDU a2, t1
191 jr ra 200 jr ra
192 LONG_SUBU a2, t0 201 LONG_SUBU a2, t0
193 202
194.Lpartial_fixup: 203.Lpartial_fixup\@:
195 PTR_L t0, TI_TASK($28) 204 PTR_L t0, TI_TASK($28)
196 andi a2, STORMASK 205 andi a2, STORMASK
197 LONG_L t0, THREAD_BUADDR(t0) 206 LONG_L t0, THREAD_BUADDR(t0)
198 LONG_ADDU a2, t1 207 LONG_ADDU a2, t1
199 jr ra 208 jr ra
200 LONG_SUBU a2, t0 209 LONG_SUBU a2, t0
201 210
202.Llast_fixup: 211.Llast_fixup\@:
203 jr ra 212 jr ra
204 andi v1, a2, STORMASK 213 andi v1, a2, STORMASK
214
215 .endm
216
217/*
218 * memset(void *s, int c, size_t n)
219 *
220 * a0: start of area to clear
221 * a1: char to fill with
222 * a2: size of area to clear
223 */
224
225LEAF(memset)
226 beqz a1, 1f
227 move v0, a0 /* result */
228
229 andi a1, 0xff /* spread fillword */
230 LONG_SLL t1, a1, 8
231 or a1, t1
232 LONG_SLL t1, a1, 16
233#if LONGSIZE == 8
234 or a1, t1
235 LONG_SLL t1, a1, 32
236#endif
237 or a1, t1
2381:
239#ifndef CONFIG_EVA
240FEXPORT(__bzero)
241#endif
242 __BUILD_BZERO LEGACY_MODE
243
244#ifdef CONFIG_EVA
245LEAF(__bzero)
246 __BUILD_BZERO EVA_MODE
247END(__bzero)
248#endif