]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 1998, 1999, 2000 by Ralf Baechle | |
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | |
26c5e07d SH |
8 | * Copyright (C) 2007 by Maciej W. Rozycki |
9 | * Copyright (C) 2011, 2012 MIPS Technologies, Inc. | |
1da177e4 LT |
10 | */ |
11 | #include <asm/asm.h> | |
048eb582 | 12 | #include <asm/asm-offsets.h> |
1da177e4 LT |
13 | #include <asm/regdef.h> |
14 | ||
a583158c AN |
15 | #if LONGSIZE == 4 |
16 | #define LONG_S_L swl | |
17 | #define LONG_S_R swr | |
18 | #else | |
19 | #define LONG_S_L sdl | |
20 | #define LONG_S_R sdr | |
21 | #endif | |
22 | ||
26c5e07d SH |
23 | #ifdef CONFIG_CPU_MICROMIPS |
24 | #define STORSIZE (LONGSIZE * 2) | |
25 | #define STORMASK (STORSIZE - 1) | |
26 | #define FILL64RG t8 | |
27 | #define FILLPTRG t7 | |
28 | #undef LONG_S | |
29 | #define LONG_S LONG_SP | |
30 | #else | |
31 | #define STORSIZE LONGSIZE | |
32 | #define STORMASK LONGMASK | |
33 | #define FILL64RG a1 | |
34 | #define FILLPTRG t0 | |
35 | #endif | |
36 | ||
6d5155c2 MC |
37 | #define LEGACY_MODE 1 |
38 | #define EVA_MODE 2 | |
39 | ||
fd9720e9 MC |
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 | ||
1da177e4 | 47 | #define EX(insn,reg,addr,handler) \ |
fd9720e9 MC |
48 | .if \mode == LEGACY_MODE; \ |
49 | 9: insn reg, addr; \ | |
50 | .else; \ | |
51 | 9: ___BUILD_EVA_INSN(insn, reg, addr); \ | |
52 | .endif; \ | |
70342287 RB |
53 | .section __ex_table,"a"; \ |
54 | PTR 9b, handler; \ | |
1da177e4 LT |
55 | .previous |
56 | ||
fd9720e9 | 57 | .macro f_fill64 dst, offset, val, fixup, mode |
26c5e07d SH |
58 | EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) |
59 | EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) | |
60 | EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) | |
61 | EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup) | |
62 | #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS)) | |
63 | EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup) | |
64 | EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup) | |
65 | EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup) | |
66 | EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup) | |
67 | #endif | |
68 | #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) | |
69 | EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup) | |
70 | EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup) | |
71 | EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup) | |
72 | EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup) | |
73 | EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup) | |
74 | EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup) | |
75 | EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup) | |
76 | EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup) | |
a583158c | 77 | #endif |
1da177e4 LT |
78 | .endm |
79 | ||
1da177e4 LT |
80 | .set noreorder |
81 | .align 5 | |
1da177e4 | 82 | |
6d5155c2 MC |
83 | /* |
84 | * Macro to generate the __bzero{,_user} symbol | |
85 | * Arguments: | |
86 | * mode: LEGACY_MODE or EVA_MODE | |
87 | */ | |
88 | .macro __BUILD_BZERO mode | |
89 | /* Initialize __memset if this is the first time we call this macro */ | |
90 | .ifnotdef __memset | |
91 | .set __memset, 1 | |
92 | .hidden __memset /* Make sure it does not leak */ | |
93 | .endif | |
1da177e4 | 94 | |
26c5e07d | 95 | sltiu t0, a2, STORSIZE /* very small region? */ |
6d5155c2 | 96 | bnez t0, .Lsmall_memset\@ |
8483b14a | 97 | andi t0, a0, STORMASK /* aligned? */ |
1da177e4 | 98 | |
26c5e07d SH |
99 | #ifdef CONFIG_CPU_MICROMIPS |
100 | move t8, a1 /* used by 'swp' instruction */ | |
101 | move t9, a1 | |
102 | #endif | |
619b6e18 | 103 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS |
1da177e4 | 104 | beqz t0, 1f |
8483b14a | 105 | PTR_SUBU t0, STORSIZE /* alignment in bytes */ |
619b6e18 MR |
106 | #else |
107 | .set noat | |
26c5e07d | 108 | li AT, STORSIZE |
619b6e18 | 109 | beqz t0, 1f |
8483b14a | 110 | PTR_SUBU t0, AT /* alignment in bytes */ |
619b6e18 MR |
111 | .set at |
112 | #endif | |
1da177e4 | 113 | |
930bff88 | 114 | R10KCBARRIER(0(ra)) |
1da177e4 | 115 | #ifdef __MIPSEB__ |
6d5155c2 | 116 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
1da177e4 LT |
117 | #endif |
118 | #ifdef __MIPSEL__ | |
6d5155c2 | 119 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
1da177e4 LT |
120 | #endif |
121 | PTR_SUBU a0, t0 /* long align ptr */ | |
122 | PTR_ADDU a2, t0 /* correct size */ | |
123 | ||
124 | 1: ori t1, a2, 0x3f /* # of full blocks */ | |
125 | xori t1, 0x3f | |
6d5155c2 | 126 | beqz t1, .Lmemset_partial\@ /* no block to fill */ |
8483b14a | 127 | andi t0, a2, 0x40-STORSIZE |
1da177e4 LT |
128 | |
129 | PTR_ADDU t1, a0 /* end address */ | |
130 | .set reorder | |
131 | 1: PTR_ADDIU a0, 64 | |
930bff88 | 132 | R10KCBARRIER(0(ra)) |
fd9720e9 | 133 | f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode |
1da177e4 LT |
134 | bne t1, a0, 1b |
135 | .set noreorder | |
136 | ||
6d5155c2 | 137 | .Lmemset_partial\@: |
930bff88 | 138 | R10KCBARRIER(0(ra)) |
1da177e4 | 139 | PTR_LA t1, 2f /* where to start */ |
26c5e07d SH |
140 | #ifdef CONFIG_CPU_MICROMIPS |
141 | LONG_SRL t7, t0, 1 | |
142 | #endif | |
a583158c | 143 | #if LONGSIZE == 4 |
26c5e07d | 144 | PTR_SUBU t1, FILLPTRG |
a583158c AN |
145 | #else |
146 | .set noat | |
26c5e07d | 147 | LONG_SRL AT, FILLPTRG, 1 |
a583158c | 148 | PTR_SUBU t1, AT |
619b6e18 | 149 | .set at |
a583158c | 150 | #endif |
1da177e4 | 151 | jr t1 |
8483b14a | 152 | PTR_ADDU a0, t0 /* dest ptr */ |
1da177e4 LT |
153 | |
154 | .set push | |
155 | .set noreorder | |
156 | .set nomacro | |
6d5155c2 | 157 | /* ... but first do longs ... */ |
fd9720e9 | 158 | f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode |
1da177e4 | 159 | 2: .set pop |
26c5e07d | 160 | andi a2, STORMASK /* At most one long to go */ |
1da177e4 LT |
161 | |
162 | beqz a2, 1f | |
8483b14a | 163 | PTR_ADDU a0, a2 /* What's left */ |
930bff88 | 164 | R10KCBARRIER(0(ra)) |
1da177e4 | 165 | #ifdef __MIPSEB__ |
6d5155c2 | 166 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) |
1da177e4 LT |
167 | #endif |
168 | #ifdef __MIPSEL__ | |
6d5155c2 | 169 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) |
1da177e4 LT |
170 | #endif |
171 | 1: jr ra | |
8483b14a | 172 | move a2, zero |
1da177e4 | 173 | |
6d5155c2 | 174 | .Lsmall_memset\@: |
1da177e4 | 175 | beqz a2, 2f |
8483b14a | 176 | PTR_ADDU t1, a0, a2 |
1da177e4 LT |
177 | |
178 | 1: PTR_ADDIU a0, 1 /* fill bytewise */ | |
930bff88 | 179 | R10KCBARRIER(0(ra)) |
1da177e4 | 180 | bne t1, a0, 1b |
8483b14a | 181 | sb a1, -1(a0) |
1da177e4 LT |
182 | |
183 | 2: jr ra /* done */ | |
8483b14a | 184 | move a2, zero |
6d5155c2 | 185 | .if __memset == 1 |
1da177e4 | 186 | END(memset) |
6d5155c2 MC |
187 | .set __memset, 0 |
188 | .hidden __memset | |
189 | .endif | |
1da177e4 | 190 | |
6d5155c2 | 191 | .Lfirst_fixup\@: |
1da177e4 | 192 | jr ra |
8483b14a | 193 | nop |
1da177e4 | 194 | |
6d5155c2 | 195 | .Lfwd_fixup\@: |
1da177e4 | 196 | PTR_L t0, TI_TASK($28) |
1da177e4 | 197 | andi a2, 0x3f |
e5674ad6 | 198 | LONG_L t0, THREAD_BUADDR(t0) |
1da177e4 LT |
199 | LONG_ADDU a2, t1 |
200 | jr ra | |
8483b14a | 201 | LONG_SUBU a2, t0 |
1da177e4 | 202 | |
6d5155c2 | 203 | .Lpartial_fixup\@: |
1da177e4 | 204 | PTR_L t0, TI_TASK($28) |
26c5e07d | 205 | andi a2, STORMASK |
e5674ad6 | 206 | LONG_L t0, THREAD_BUADDR(t0) |
1da177e4 LT |
207 | LONG_ADDU a2, t1 |
208 | jr ra | |
8483b14a | 209 | LONG_SUBU a2, t0 |
1da177e4 | 210 | |
6d5155c2 | 211 | .Llast_fixup\@: |
1da177e4 | 212 | jr ra |
8483b14a | 213 | andi v1, a2, STORMASK |
6d5155c2 MC |
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 | ||
225 | LEAF(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 | |
238 | 1: | |
fd9720e9 | 239 | #ifndef CONFIG_EVA |
6d5155c2 | 240 | FEXPORT(__bzero) |
fd9720e9 | 241 | #endif |
6d5155c2 | 242 | __BUILD_BZERO LEGACY_MODE |
fd9720e9 MC |
243 | |
244 | #ifdef CONFIG_EVA | |
245 | LEAF(__bzero) | |
246 | __BUILD_BZERO EVA_MODE | |
247 | END(__bzero) | |
248 | #endif |