1 /* SPDX-License-Identifier: GPL-2.0-only */ << 2 /* 1 /* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy !! 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. >> 8 * Copyright (C) 2007 Maciej W. Rozycki 4 */ 9 */ >> 10 #include <asm/asm.h> >> 11 #include <asm/asm-offsets.h> >> 12 #include <asm/regdef.h> >> 13 >> 14 #if LONGSIZE == 4 >> 15 #define LONG_S_L swl >> 16 #define LONG_S_R swr >> 17 #else >> 18 #define LONG_S_L sdl >> 19 #define LONG_S_R sdr >> 20 #endif >> 21 >> 22 #define EX(insn,reg,addr,handler) \ >> 23 9: insn reg, addr; \ >> 24 .section __ex_table,"a"; \ >> 25 PTR 9b, handler; \ >> 26 .previous >> 27 >> 28 .macro f_fill64 dst, offset, val, fixup >> 29 EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup) >> 30 EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup) >> 31 EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup) >> 32 EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup) >> 33 EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup) >> 34 EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup) >> 35 EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup) >> 36 EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup) >> 37 #if LONGSIZE == 4 >> 38 EX(LONG_S, \val, (\offset + 8 * LONGSIZE)(\dst), \fixup) >> 39 EX(LONG_S, \val, (\offset + 9 * LONGSIZE)(\dst), \fixup) >> 40 EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup) >> 41 EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup) >> 42 EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup) >> 43 EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup) >> 44 EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup) >> 45 EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup) >> 46 #endif >> 47 .endm 5 48 6 #include <linux/linkage.h> !! 49 /* 7 !! 50 * memset(void *s, int c, size_t n) 8 #define SMALL 7 /* Must be at least 6 to dea !! 51 * 9 !! 52 * a0: start of area to clear 10 ENTRY_CFI(memset) !! 53 * a1: char to fill with 11 mov_s r4,r0 !! 54 * a2: size of area to clear 12 or r12,r0,r2 !! 55 */ 13 bmsk.f r12,r12,1 !! 56 .set noreorder 14 extb_s r1,r1 !! 57 .align 5 15 asl r3,r1,8 !! 58 LEAF(memset) 16 beq.d .Laligned !! 59 beqz a1, 1f 17 or_s r1,r1,r3 !! 60 move v0, a0 /* result */ 18 brls r2,SMALL,.Ltiny !! 61 19 add r3,r2,r0 !! 62 andi a1, 0xff /* spread fillword */ 20 stb r1,[r3,-1] !! 63 LONG_SLL t1, a1, 8 21 bclr_s r3,r3,0 !! 64 or a1, t1 22 stw r1,[r3,-2] !! 65 LONG_SLL t1, a1, 16 23 bmsk.f r12,r0,1 !! 66 #if LONGSIZE == 8 24 add_s r2,r2,r12 !! 67 or a1, t1 25 sub.ne r2,r2,4 !! 68 LONG_SLL t1, a1, 32 26 stb.ab r1,[r4,1] !! 69 #endif 27 and r4,r4,-2 !! 70 or a1, t1 28 stw.ab r1,[r4,2] !! 71 1: 29 and r4,r4,-4 !! 72 30 .Laligned: ; This code address should be !! 73 FEXPORT(__bzero) 31 asl r3,r1,16 !! 74 sltiu t0, a2, LONGSIZE /* very small region? */ 32 lsr.f lp_count,r2,2 !! 75 bnez t0, .Lsmall_memset 33 or_s r1,r1,r3 !! 76 andi t0, a0, LONGMASK /* aligned? */ 34 lpne .Loop_end !! 77 35 st.ab r1,[r4,4] !! 78 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS 36 .Loop_end: !! 79 beqz t0, 1f 37 j_s [blink] !! 80 PTR_SUBU t0, LONGSIZE /* alignment in bytes */ 38 !! 81 #else 39 .balign 4 !! 82 .set noat 40 .Ltiny: !! 83 li AT, LONGSIZE 41 mov.f lp_count,r2 !! 84 beqz t0, 1f 42 lpne .Ltiny_end !! 85 PTR_SUBU t0, AT /* alignment in bytes */ 43 stb.ab r1,[r4,1] !! 86 .set at 44 .Ltiny_end: !! 87 #endif 45 j_s [blink] !! 88 46 END_CFI(memset) !! 89 R10KCBARRIER(0(ra)) 47 !! 90 #ifdef __MIPSEB__ 48 ; memzero: @r0 = mem, @r1 = size_t !! 91 EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ 49 ; memset: @r0 = mem, @r1 = char, @r2 = size_t !! 92 #endif 50 !! 93 #ifdef __MIPSEL__ 51 ENTRY_CFI(memzero) !! 94 EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ 52 ; adjust bzero args to memset args !! 95 #endif 53 mov r2, r1 !! 96 PTR_SUBU a0, t0 /* long align ptr */ 54 mov r1, 0 !! 97 PTR_ADDU a2, t0 /* correct size */ 55 b memset ;tail call so need to tinker !! 98 56 END_CFI(memzero) !! 99 1: ori t1, a2, 0x3f /* # of full blocks */ >> 100 xori t1, 0x3f >> 101 beqz t1, .Lmemset_partial /* no block to fill */ >> 102 andi t0, a2, 0x40-LONGSIZE >> 103 >> 104 PTR_ADDU t1, a0 /* end address */ >> 105 .set reorder >> 106 1: PTR_ADDIU a0, 64 >> 107 R10KCBARRIER(0(ra)) >> 108 f_fill64 a0, -64, a1, .Lfwd_fixup >> 109 bne t1, a0, 1b >> 110 .set noreorder >> 111 >> 112 .Lmemset_partial: >> 113 R10KCBARRIER(0(ra)) >> 114 PTR_LA t1, 2f /* where to start */ >> 115 #if LONGSIZE == 4 >> 116 PTR_SUBU t1, t0 >> 117 #else >> 118 .set noat >> 119 LONG_SRL AT, t0, 1 >> 120 PTR_SUBU t1, AT >> 121 .set at >> 122 #endif >> 123 jr t1 >> 124 PTR_ADDU a0, t0 /* dest ptr */ >> 125 >> 126 .set push >> 127 .set noreorder >> 128 .set nomacro >> 129 f_fill64 a0, -64, a1, .Lpartial_fixup /* ... but first do longs ... */ >> 130 2: .set pop >> 131 andi a2, LONGMASK /* At most one long to go */ >> 132 >> 133 beqz a2, 1f >> 134 PTR_ADDU a0, a2 /* What's left */ >> 135 R10KCBARRIER(0(ra)) >> 136 #ifdef __MIPSEB__ >> 137 EX(LONG_S_R, a1, -1(a0), .Llast_fixup) >> 138 #endif >> 139 #ifdef __MIPSEL__ >> 140 EX(LONG_S_L, a1, -1(a0), .Llast_fixup) >> 141 #endif >> 142 1: jr ra >> 143 move a2, zero >> 144 >> 145 .Lsmall_memset: >> 146 beqz a2, 2f >> 147 PTR_ADDU t1, a0, a2 >> 148 >> 149 1: PTR_ADDIU a0, 1 /* fill bytewise */ >> 150 R10KCBARRIER(0(ra)) >> 151 bne t1, a0, 1b >> 152 sb a1, -1(a0) >> 153 >> 154 2: jr ra /* done */ >> 155 move a2, zero >> 156 END(memset) >> 157 >> 158 .Lfirst_fixup: >> 159 jr ra >> 160 nop >> 161 >> 162 .Lfwd_fixup: >> 163 PTR_L t0, TI_TASK($28) >> 164 LONG_L t0, THREAD_BUADDR(t0) >> 165 andi a2, 0x3f >> 166 LONG_ADDU a2, t1 >> 167 jr ra >> 168 LONG_SUBU a2, t0 >> 169 >> 170 .Lpartial_fixup: >> 171 PTR_L t0, TI_TASK($28) >> 172 LONG_L t0, THREAD_BUADDR(t0) >> 173 andi a2, LONGMASK >> 174 LONG_ADDU a2, t1 >> 175 jr ra >> 176 LONG_SUBU a2, t0 >> 177 >> 178 .Llast_fixup: >> 179 jr ra >> 180 andi v1, a2, LONGMASK
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.