1 /* 1 /* 2 * This file is subject to the terms and condi 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the mai 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 4 * for more details. 5 * 5 * 6 * Copyright (C) 1998, 1999, 2000 by Ralf Baec 6 * Copyright (C) 1998, 1999, 2000 by Ralf Baechle 7 * Copyright (C) 1999, 2000 Silicon Graphics, 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 2007 by Maciej W. Rozycki 8 * Copyright (C) 2007 by Maciej W. Rozycki 9 * Copyright (C) 2011, 2012 MIPS Technologies, 9 * Copyright (C) 2011, 2012 MIPS Technologies, Inc. 10 */ 10 */ 11 #include <linux/export.h> << 12 #include <asm/asm.h> 11 #include <asm/asm.h> 13 #include <asm/asm-offsets.h> 12 #include <asm/asm-offsets.h> 14 #include <asm/regdef.h> 13 #include <asm/regdef.h> 15 14 16 #if LONGSIZE == 4 15 #if LONGSIZE == 4 17 #define LONG_S_L swl 16 #define LONG_S_L swl 18 #define LONG_S_R swr 17 #define LONG_S_R swr 19 #else 18 #else 20 #define LONG_S_L sdl 19 #define LONG_S_L sdl 21 #define LONG_S_R sdr 20 #define LONG_S_R sdr 22 #endif 21 #endif 23 22 24 #ifdef CONFIG_CPU_MICROMIPS 23 #ifdef CONFIG_CPU_MICROMIPS 25 #define STORSIZE (LONGSIZE * 2) 24 #define STORSIZE (LONGSIZE * 2) 26 #define STORMASK (STORSIZE - 1) 25 #define STORMASK (STORSIZE - 1) 27 #define FILL64RG t8 26 #define FILL64RG t8 28 #define FILLPTRG t7 27 #define FILLPTRG t7 29 #undef LONG_S 28 #undef LONG_S 30 #define LONG_S LONG_SP 29 #define LONG_S LONG_SP 31 #else 30 #else 32 #define STORSIZE LONGSIZE 31 #define STORSIZE LONGSIZE 33 #define STORMASK LONGMASK 32 #define STORMASK LONGMASK 34 #define FILL64RG a1 33 #define FILL64RG a1 35 #define FILLPTRG t0 34 #define FILLPTRG t0 36 #endif 35 #endif 37 36 38 #define LEGACY_MODE 1 37 #define LEGACY_MODE 1 39 #define EVA_MODE 2 38 #define EVA_MODE 2 40 39 41 /* 40 /* 42 * No need to protect it with EVA #ifdefery. T 41 * No need to protect it with EVA #ifdefery. The generated block of code 43 * will never be assembled if EVA is not enabl 42 * will never be assembled if EVA is not enabled. 44 */ 43 */ 45 #define __EVAFY(insn, reg, addr) __BUILD_EVA_I 44 #define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr) 46 #define ___BUILD_EVA_INSN(insn, reg, addr) __E 45 #define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr) 47 46 48 #define EX(insn,reg,addr,handler) 47 #define EX(insn,reg,addr,handler) \ 49 .if \mode == LEGACY_MODE; 48 .if \mode == LEGACY_MODE; \ 50 9: insn reg, addr; 49 9: insn reg, addr; \ 51 .else; 50 .else; \ 52 9: ___BUILD_EVA_INSN(insn, reg, a 51 9: ___BUILD_EVA_INSN(insn, reg, addr); \ 53 .endif; 52 .endif; \ 54 .section __ex_table,"a"; 53 .section __ex_table,"a"; \ 55 PTR_WD 9b, handler; !! 54 PTR 9b, handler; \ 56 .previous 55 .previous 57 56 58 .macro f_fill64 dst, offset, val, fix 57 .macro f_fill64 dst, offset, val, fixup, mode 59 EX(LONG_S, \val, (\offset + 0 * STORS 58 EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) 60 EX(LONG_S, \val, (\offset + 1 * STORS 59 EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) 61 EX(LONG_S, \val, (\offset + 2 * STORS 60 EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) 62 EX(LONG_S, \val, (\offset + 3 * STORS 61 EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup) 63 #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSI 62 #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS)) 64 EX(LONG_S, \val, (\offset + 4 * STORS 63 EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup) 65 EX(LONG_S, \val, (\offset + 5 * STORS 64 EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup) 66 EX(LONG_S, \val, (\offset + 6 * STORS 65 EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup) 67 EX(LONG_S, \val, (\offset + 7 * STORS 66 EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup) 68 #endif 67 #endif 69 #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSI 68 #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) 70 EX(LONG_S, \val, (\offset + 8 * STORS 69 EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup) 71 EX(LONG_S, \val, (\offset + 9 * STORS 70 EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup) 72 EX(LONG_S, \val, (\offset + 10 * STORS 71 EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup) 73 EX(LONG_S, \val, (\offset + 11 * STORS 72 EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup) 74 EX(LONG_S, \val, (\offset + 12 * STORS 73 EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup) 75 EX(LONG_S, \val, (\offset + 13 * STORS 74 EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup) 76 EX(LONG_S, \val, (\offset + 14 * STORS 75 EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup) 77 EX(LONG_S, \val, (\offset + 15 * STORS 76 EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup) 78 #endif 77 #endif 79 .endm 78 .endm 80 79 >> 80 .set noreorder 81 .align 5 81 .align 5 82 82 83 /* 83 /* 84 * Macro to generate the __bzero{,_use 84 * Macro to generate the __bzero{,_user} symbol 85 * Arguments: 85 * Arguments: 86 * mode: LEGACY_MODE or EVA_MODE 86 * mode: LEGACY_MODE or EVA_MODE 87 */ 87 */ 88 .macro __BUILD_BZERO mode 88 .macro __BUILD_BZERO mode 89 /* Initialize __memset if this is the 89 /* Initialize __memset if this is the first time we call this macro */ 90 .ifnotdef __memset 90 .ifnotdef __memset 91 .set __memset, 1 91 .set __memset, 1 92 .hidden __memset /* Make sure it does 92 .hidden __memset /* Make sure it does not leak */ 93 .endif 93 .endif 94 94 95 sltiu t0, a2, STORSIZE 95 sltiu t0, a2, STORSIZE /* very small region? */ 96 .set noreorder << 97 bnez t0, .Lsmall_memset\@ 96 bnez t0, .Lsmall_memset\@ 98 andi t0, a0, STORMASK !! 97 andi t0, a0, STORMASK /* aligned? */ 99 .set reorder << 100 98 101 #ifdef CONFIG_CPU_MICROMIPS 99 #ifdef CONFIG_CPU_MICROMIPS 102 move t8, a1 100 move t8, a1 /* used by 'swp' instruction */ 103 move t9, a1 101 move t9, a1 104 #endif 102 #endif 105 .set noreorder << 106 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS 103 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS 107 beqz t0, 1f 104 beqz t0, 1f 108 PTR_SUBU t0, STORSIZE !! 105 PTR_SUBU t0, STORSIZE /* alignment in bytes */ 109 #else 106 #else 110 .set noat 107 .set noat 111 li AT, STORSIZE 108 li AT, STORSIZE 112 beqz t0, 1f 109 beqz t0, 1f 113 PTR_SUBU t0, AT !! 110 PTR_SUBU t0, AT /* alignment in bytes */ 114 .set at 111 .set at 115 #endif 112 #endif 116 .set reorder << 117 113 118 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR !! 114 #ifndef CONFIG_CPU_MIPSR6 119 R10KCBARRIER(0(ra)) 115 R10KCBARRIER(0(ra)) 120 #ifdef __MIPSEB__ 116 #ifdef __MIPSEB__ 121 EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@ 117 EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ 122 #else 118 #else 123 EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@ 119 EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ 124 #endif 120 #endif 125 PTR_SUBU a0, t0 121 PTR_SUBU a0, t0 /* long align ptr */ 126 PTR_ADDU a2, t0 122 PTR_ADDU a2, t0 /* correct size */ 127 123 128 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ !! 124 #else /* CONFIG_CPU_MIPSR6 */ 129 #define STORE_BYTE(N) 125 #define STORE_BYTE(N) \ 130 EX(sb, a1, N(a0), .Lbyte_fixup\@); 126 EX(sb, a1, N(a0), .Lbyte_fixup\@); \ 131 .set noreorder; << 132 beqz t0, 0f; 127 beqz t0, 0f; \ 133 PTR_ADDU t0, 1; !! 128 PTR_ADDU t0, 1; 134 .set reorder; << 135 129 136 PTR_ADDU a2, t0 130 PTR_ADDU a2, t0 /* correct size */ 137 PTR_ADDU t0, 1 131 PTR_ADDU t0, 1 138 STORE_BYTE(0) 132 STORE_BYTE(0) 139 STORE_BYTE(1) 133 STORE_BYTE(1) 140 #if LONGSIZE == 4 134 #if LONGSIZE == 4 141 EX(sb, a1, 2(a0), .Lbyte_fixup\@) 135 EX(sb, a1, 2(a0), .Lbyte_fixup\@) 142 #else 136 #else 143 STORE_BYTE(2) 137 STORE_BYTE(2) 144 STORE_BYTE(3) 138 STORE_BYTE(3) 145 STORE_BYTE(4) 139 STORE_BYTE(4) 146 STORE_BYTE(5) 140 STORE_BYTE(5) 147 EX(sb, a1, 6(a0), .Lbyte_fixup\@) 141 EX(sb, a1, 6(a0), .Lbyte_fixup\@) 148 #endif 142 #endif 149 0: 143 0: 150 ori a0, STORMASK 144 ori a0, STORMASK 151 xori a0, STORMASK 145 xori a0, STORMASK 152 PTR_ADDIU a0, STORSIZE 146 PTR_ADDIU a0, STORSIZE 153 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ !! 147 #endif /* CONFIG_CPU_MIPSR6 */ 154 1: ori t1, a2, 0x3f 148 1: ori t1, a2, 0x3f /* # of full blocks */ 155 xori t1, 0x3f 149 xori t1, 0x3f 156 andi t0, a2, 0x40-STORSIZE << 157 beqz t1, .Lmemset_partial\@ 150 beqz t1, .Lmemset_partial\@ /* no block to fill */ >> 151 andi t0, a2, 0x40-STORSIZE 158 152 159 PTR_ADDU t1, a0 153 PTR_ADDU t1, a0 /* end address */ >> 154 .set reorder 160 1: PTR_ADDIU a0, 64 155 1: PTR_ADDIU a0, 64 161 R10KCBARRIER(0(ra)) 156 R10KCBARRIER(0(ra)) 162 f_fill64 a0, -64, FILL64RG, .Lfwd_fixu 157 f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode 163 bne t1, a0, 1b 158 bne t1, a0, 1b >> 159 .set noreorder 164 160 165 .Lmemset_partial\@: 161 .Lmemset_partial\@: 166 R10KCBARRIER(0(ra)) 162 R10KCBARRIER(0(ra)) 167 PTR_LA t1, 2f 163 PTR_LA t1, 2f /* where to start */ 168 #ifdef CONFIG_CPU_MICROMIPS 164 #ifdef CONFIG_CPU_MICROMIPS 169 LONG_SRL t7, t0, 1 165 LONG_SRL t7, t0, 1 170 #endif 166 #endif 171 #if LONGSIZE == 4 167 #if LONGSIZE == 4 172 PTR_SUBU t1, FILLPTRG 168 PTR_SUBU t1, FILLPTRG 173 #else 169 #else 174 .set noat 170 .set noat 175 LONG_SRL AT, FILLPTRG, 1 171 LONG_SRL AT, FILLPTRG, 1 176 PTR_SUBU t1, AT 172 PTR_SUBU t1, AT 177 .set at 173 .set at 178 #endif 174 #endif 179 PTR_ADDU a0, t0 << 180 jr t1 175 jr t1 >> 176 PTR_ADDU a0, t0 /* dest ptr */ 181 177 >> 178 .set push >> 179 .set noreorder >> 180 .set nomacro 182 /* ... but first do longs ... */ 181 /* ... but first do longs ... */ 183 f_fill64 a0, -64, FILL64RG, .Lpartial_ 182 f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode 184 2: andi a2, STORMASK !! 183 2: .set pop >> 184 andi a2, STORMASK /* At most one long to go */ 185 185 186 .set noreorder << 187 beqz a2, 1f 186 beqz a2, 1f 188 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR !! 187 #ifndef CONFIG_CPU_MIPSR6 189 PTR_ADDU a0, a2 !! 188 PTR_ADDU a0, a2 /* What's left */ 190 .set reorder << 191 R10KCBARRIER(0(ra)) 189 R10KCBARRIER(0(ra)) 192 #ifdef __MIPSEB__ 190 #ifdef __MIPSEB__ 193 EX(LONG_S_R, a1, -1(a0), .Llast_fixup\ 191 EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) 194 #else 192 #else 195 EX(LONG_S_L, a1, -1(a0), .Llast_fixup\ 193 EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) 196 #endif 194 #endif 197 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ !! 195 #else 198 PTR_SUBU t0, $0, a2 !! 196 PTR_SUBU t0, $0, a2 199 .set reorder << 200 move a2, zero << 201 PTR_ADDIU t0, 1 197 PTR_ADDIU t0, 1 202 STORE_BYTE(0) 198 STORE_BYTE(0) 203 STORE_BYTE(1) 199 STORE_BYTE(1) 204 #if LONGSIZE == 4 200 #if LONGSIZE == 4 205 EX(sb, a1, 2(a0), .Lbyte_fixup\@) 201 EX(sb, a1, 2(a0), .Lbyte_fixup\@) 206 #else 202 #else 207 STORE_BYTE(2) 203 STORE_BYTE(2) 208 STORE_BYTE(3) 204 STORE_BYTE(3) 209 STORE_BYTE(4) 205 STORE_BYTE(4) 210 STORE_BYTE(5) 206 STORE_BYTE(5) 211 EX(sb, a1, 6(a0), .Lbyte_fixup\@) 207 EX(sb, a1, 6(a0), .Lbyte_fixup\@) 212 #endif 208 #endif 213 0: 209 0: 214 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ !! 210 #endif 215 1: move a2, zero !! 211 1: jr ra 216 jr ra !! 212 move a2, zero 217 213 218 .Lsmall_memset\@: 214 .Lsmall_memset\@: 219 PTR_ADDU t1, a0, a2 << 220 beqz a2, 2f 215 beqz a2, 2f >> 216 PTR_ADDU t1, a0, a2 221 217 222 1: PTR_ADDIU a0, 1 218 1: PTR_ADDIU a0, 1 /* fill bytewise */ 223 R10KCBARRIER(0(ra)) 219 R10KCBARRIER(0(ra)) 224 .set noreorder << 225 bne t1, a0, 1b 220 bne t1, a0, 1b 226 EX(sb, a1, -1(a0), .Lsmall_fixup\@) 221 EX(sb, a1, -1(a0), .Lsmall_fixup\@) 227 .set reorder << 228 222 229 2: move a2, zero !! 223 2: jr ra /* done */ 230 jr ra !! 224 move a2, zero 231 .if __memset == 1 225 .if __memset == 1 232 END(memset) 226 END(memset) 233 .set __memset, 0 227 .set __memset, 0 234 .hidden __memset 228 .hidden __memset 235 .endif 229 .endif 236 230 237 #ifdef CONFIG_CPU_NO_LOAD_STORE_LR !! 231 #ifdef CONFIG_CPU_MIPSR6 238 .Lbyte_fixup\@: 232 .Lbyte_fixup\@: 239 /* !! 233 PTR_SUBU a2, $0, t0 240 * unset_bytes = (#bytes - (#unaligned << 241 * a2 = a2 << 242 */ << 243 PTR_SUBU a2, t0 << 244 PTR_ADDIU a2, 1 << 245 jr ra 234 jr ra 246 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ !! 235 PTR_ADDIU a2, 1 >> 236 #endif /* CONFIG_CPU_MIPSR6 */ 247 237 248 .Lfirst_fixup\@: 238 .Lfirst_fixup\@: 249 /* unset_bytes already in a2 */ << 250 jr ra 239 jr ra >> 240 nop 251 241 252 .Lfwd_fixup\@: 242 .Lfwd_fixup\@: 253 /* << 254 * unset_bytes = partial_start_addr + << 255 * a2 = t1 + << 256 */ << 257 PTR_L t0, TI_TASK($28) 243 PTR_L t0, TI_TASK($28) 258 andi a2, 0x3f 244 andi a2, 0x3f 259 LONG_L t0, THREAD_BUADDR(t0) 245 LONG_L t0, THREAD_BUADDR(t0) 260 LONG_ADDU a2, t1 246 LONG_ADDU a2, t1 261 LONG_SUBU a2, t0 << 262 jr ra 247 jr ra >> 248 LONG_SUBU a2, t0 263 249 264 .Lpartial_fixup\@: 250 .Lpartial_fixup\@: 265 /* << 266 * unset_bytes = partial_end_addr + << 267 * a2 = a0 + (a << 268 */ << 269 PTR_L t0, TI_TASK($28) 251 PTR_L t0, TI_TASK($28) 270 andi a2, STORMASK 252 andi a2, STORMASK 271 LONG_L t0, THREAD_BUADDR(t0) 253 LONG_L t0, THREAD_BUADDR(t0) 272 LONG_ADDU a2, a0 254 LONG_ADDU a2, a0 273 LONG_SUBU a2, t0 << 274 jr ra 255 jr ra >> 256 LONG_SUBU a2, t0 275 257 276 .Llast_fixup\@: 258 .Llast_fixup\@: 277 /* unset_bytes already in a2 */ << 278 jr ra 259 jr ra >> 260 nop 279 261 280 .Lsmall_fixup\@: 262 .Lsmall_fixup\@: 281 /* << 282 * unset_bytes = end_addr - current_ad << 283 * a2 = t1 - a0 << 284 */ << 285 PTR_SUBU a2, t1, a0 263 PTR_SUBU a2, t1, a0 286 PTR_ADDIU a2, 1 << 287 jr ra 264 jr ra >> 265 PTR_ADDIU a2, 1 288 266 289 .endm 267 .endm 290 268 291 /* 269 /* 292 * memset(void *s, int c, size_t n) 270 * memset(void *s, int c, size_t n) 293 * 271 * 294 * a0: start of area to clear 272 * a0: start of area to clear 295 * a1: char to fill with 273 * a1: char to fill with 296 * a2: size of area to clear 274 * a2: size of area to clear 297 */ 275 */ 298 276 299 LEAF(memset) 277 LEAF(memset) 300 EXPORT_SYMBOL(memset) << 301 move v0, a0 << 302 beqz a1, 1f 278 beqz a1, 1f >> 279 move v0, a0 /* result */ 303 280 304 andi a1, 0xff 281 andi a1, 0xff /* spread fillword */ 305 LONG_SLL t1, a1, 8 282 LONG_SLL t1, a1, 8 306 or a1, t1 283 or a1, t1 307 LONG_SLL t1, a1, 16 284 LONG_SLL t1, a1, 16 308 #if LONGSIZE == 8 285 #if LONGSIZE == 8 309 or a1, t1 286 or a1, t1 310 LONG_SLL t1, a1, 32 287 LONG_SLL t1, a1, 32 311 #endif 288 #endif 312 or a1, t1 289 or a1, t1 313 1: 290 1: 314 #ifndef CONFIG_EVA 291 #ifndef CONFIG_EVA 315 FEXPORT(__bzero) 292 FEXPORT(__bzero) 316 EXPORT_SYMBOL(__bzero) !! 293 #else >> 294 FEXPORT(__bzero_kernel) 317 #endif 295 #endif 318 __BUILD_BZERO LEGACY_MODE 296 __BUILD_BZERO LEGACY_MODE 319 297 320 #ifdef CONFIG_EVA 298 #ifdef CONFIG_EVA 321 LEAF(__bzero) 299 LEAF(__bzero) 322 EXPORT_SYMBOL(__bzero) << 323 __BUILD_BZERO EVA_MODE 300 __BUILD_BZERO EVA_MODE 324 END(__bzero) 301 END(__bzero) 325 #endif 302 #endif
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.