xref: /linux/arch/mips/lib/memset.S (revision 6312455a0437a64059bdeee5696b375593a09947)
1a583158cSAtsushi Nemoto/*
2a583158cSAtsushi Nemoto * This file is subject to the terms and conditions of the GNU General Public
3a583158cSAtsushi Nemoto * License.  See the file "COPYING" in the main directory of this archive
4a583158cSAtsushi Nemoto * for more details.
5a583158cSAtsushi Nemoto *
6a583158cSAtsushi Nemoto * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
7a583158cSAtsushi Nemoto * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
826c5e07dSSteven J. Hill * Copyright (C) 2007 by Maciej W. Rozycki
926c5e07dSSteven J. Hill * Copyright (C) 2011, 2012 MIPS Technologies, Inc.
10a583158cSAtsushi Nemoto */
11a583158cSAtsushi Nemoto#include <asm/asm.h>
12a583158cSAtsushi Nemoto#include <asm/asm-offsets.h>
13576a2f0cSPaul Burton#include <asm/export.h>
14a583158cSAtsushi Nemoto#include <asm/regdef.h>
15a583158cSAtsushi Nemoto
16a583158cSAtsushi Nemoto#if LONGSIZE == 4
17a583158cSAtsushi Nemoto#define LONG_S_L swl
18a583158cSAtsushi Nemoto#define LONG_S_R swr
19a583158cSAtsushi Nemoto#else
20a583158cSAtsushi Nemoto#define LONG_S_L sdl
21a583158cSAtsushi Nemoto#define LONG_S_R sdr
22a583158cSAtsushi Nemoto#endif
23a583158cSAtsushi Nemoto
2426c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
2526c5e07dSSteven J. Hill#define STORSIZE (LONGSIZE * 2)
2626c5e07dSSteven J. Hill#define STORMASK (STORSIZE - 1)
2726c5e07dSSteven J. Hill#define FILL64RG t8
2826c5e07dSSteven J. Hill#define FILLPTRG t7
2926c5e07dSSteven J. Hill#undef  LONG_S
3026c5e07dSSteven J. Hill#define LONG_S LONG_SP
3126c5e07dSSteven J. Hill#else
3226c5e07dSSteven J. Hill#define STORSIZE LONGSIZE
3326c5e07dSSteven J. Hill#define STORMASK LONGMASK
3426c5e07dSSteven J. Hill#define FILL64RG a1
3526c5e07dSSteven J. Hill#define FILLPTRG t0
3626c5e07dSSteven J. Hill#endif
3726c5e07dSSteven J. Hill
386d5155c2SMarkos Chandras#define LEGACY_MODE 1
396d5155c2SMarkos Chandras#define EVA_MODE    2
406d5155c2SMarkos Chandras
41fd9720e9SMarkos Chandras/*
42fd9720e9SMarkos Chandras * No need to protect it with EVA #ifdefery. The generated block of code
43fd9720e9SMarkos Chandras * will never be assembled if EVA is not enabled.
44fd9720e9SMarkos Chandras */
45fd9720e9SMarkos Chandras#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
46fd9720e9SMarkos Chandras#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
47fd9720e9SMarkos Chandras
48a583158cSAtsushi Nemoto#define EX(insn,reg,addr,handler)			\
49fd9720e9SMarkos Chandras	.if \mode == LEGACY_MODE;			\
50a583158cSAtsushi Nemoto9:		insn	reg, addr;			\
51fd9720e9SMarkos Chandras	.else;						\
52fd9720e9SMarkos Chandras9:		___BUILD_EVA_INSN(insn, reg, addr);	\
53fd9720e9SMarkos Chandras	.endif;						\
54a583158cSAtsushi Nemoto	.section __ex_table,"a";			\
55a583158cSAtsushi Nemoto	PTR	9b, handler;				\
56a583158cSAtsushi Nemoto	.previous
57a583158cSAtsushi Nemoto
58fd9720e9SMarkos Chandras	.macro	f_fill64 dst, offset, val, fixup, mode
5926c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  0 * STORSIZE)(\dst), \fixup)
6026c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  1 * STORSIZE)(\dst), \fixup)
6126c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  2 * STORSIZE)(\dst), \fixup)
6226c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  3 * STORSIZE)(\dst), \fixup)
6326c5e07dSSteven J. Hill#if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS))
6426c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  4 * STORSIZE)(\dst), \fixup)
6526c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  5 * STORSIZE)(\dst), \fixup)
6626c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  6 * STORSIZE)(\dst), \fixup)
6726c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  7 * STORSIZE)(\dst), \fixup)
6826c5e07dSSteven J. Hill#endif
6926c5e07dSSteven J. Hill#if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4))
7026c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  8 * STORSIZE)(\dst), \fixup)
7126c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset +  9 * STORSIZE)(\dst), \fixup)
7226c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup)
7326c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup)
7426c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup)
7526c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup)
7626c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup)
7726c5e07dSSteven J. Hill	EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup)
78a583158cSAtsushi Nemoto#endif
79a583158cSAtsushi Nemoto	.endm
80a583158cSAtsushi Nemoto
81a583158cSAtsushi Nemoto	.set	noreorder
82a583158cSAtsushi Nemoto	.align	5
83a583158cSAtsushi Nemoto
846d5155c2SMarkos Chandras	/*
856d5155c2SMarkos Chandras	 * Macro to generate the __bzero{,_user} symbol
866d5155c2SMarkos Chandras	 * Arguments:
876d5155c2SMarkos Chandras	 * mode: LEGACY_MODE or EVA_MODE
886d5155c2SMarkos Chandras	 */
896d5155c2SMarkos Chandras	.macro __BUILD_BZERO mode
906d5155c2SMarkos Chandras	/* Initialize __memset if this is the first time we call this macro */
916d5155c2SMarkos Chandras	.ifnotdef __memset
926d5155c2SMarkos Chandras	.set __memset, 1
936d5155c2SMarkos Chandras	.hidden __memset /* Make sure it does not leak */
946d5155c2SMarkos Chandras	.endif
95a583158cSAtsushi Nemoto
9626c5e07dSSteven J. Hill	sltiu		t0, a2, STORSIZE	/* very small region? */
976d5155c2SMarkos Chandras	bnez		t0, .Lsmall_memset\@
9826c5e07dSSteven J. Hill	 andi		t0, a0, STORMASK	/* aligned? */
99a583158cSAtsushi Nemoto
10026c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
10126c5e07dSSteven J. Hill	move		t8, a1			/* used by 'swp' instruction */
10226c5e07dSSteven J. Hill	move		t9, a1
10326c5e07dSSteven J. Hill#endif
104619b6e18SMaciej W. Rozycki#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
105a583158cSAtsushi Nemoto	beqz		t0, 1f
10626c5e07dSSteven J. Hill	 PTR_SUBU	t0, STORSIZE		/* alignment in bytes */
107619b6e18SMaciej W. Rozycki#else
108619b6e18SMaciej W. Rozycki	.set		noat
10926c5e07dSSteven J. Hill	li		AT, STORSIZE
110619b6e18SMaciej W. Rozycki	beqz		t0, 1f
111619b6e18SMaciej W. Rozycki	 PTR_SUBU	t0, AT			/* alignment in bytes */
112619b6e18SMaciej W. Rozycki	.set		at
113619b6e18SMaciej W. Rozycki#endif
114a583158cSAtsushi Nemoto
1158c56208aSLeonid Yegoshin#ifndef CONFIG_CPU_MIPSR6
116930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
117a583158cSAtsushi Nemoto#ifdef __MIPSEB__
1186d5155c2SMarkos Chandras	EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
119dd2adea4SMarkos Chandras#else
1206d5155c2SMarkos Chandras	EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
121a583158cSAtsushi Nemoto#endif
122a583158cSAtsushi Nemoto	PTR_SUBU	a0, t0			/* long align ptr */
123a583158cSAtsushi Nemoto	PTR_ADDU	a2, t0			/* correct size */
124a583158cSAtsushi Nemoto
1258c56208aSLeonid Yegoshin#else /* CONFIG_CPU_MIPSR6 */
1268c56208aSLeonid Yegoshin#define STORE_BYTE(N)				\
1278c56208aSLeonid Yegoshin	EX(sb, a1, N(a0), .Lbyte_fixup\@);	\
1288c56208aSLeonid Yegoshin	beqz		t0, 0f;			\
1298c56208aSLeonid Yegoshin	PTR_ADDU	t0, 1;
1308c56208aSLeonid Yegoshin
1318c56208aSLeonid Yegoshin	PTR_ADDU	a2, t0			/* correct size */
1328c56208aSLeonid Yegoshin	PTR_ADDU	t0, 1
1338c56208aSLeonid Yegoshin	STORE_BYTE(0)
1348c56208aSLeonid Yegoshin	STORE_BYTE(1)
1358c56208aSLeonid Yegoshin#if LONGSIZE == 4
1368c56208aSLeonid Yegoshin	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
1378c56208aSLeonid Yegoshin#else
1388c56208aSLeonid Yegoshin	STORE_BYTE(2)
1398c56208aSLeonid Yegoshin	STORE_BYTE(3)
1408c56208aSLeonid Yegoshin	STORE_BYTE(4)
1418c56208aSLeonid Yegoshin	STORE_BYTE(5)
1428c56208aSLeonid Yegoshin	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
1438c56208aSLeonid Yegoshin#endif
1448c56208aSLeonid Yegoshin0:
1458c56208aSLeonid Yegoshin	ori		a0, STORMASK
1468c56208aSLeonid Yegoshin	xori		a0, STORMASK
1478c56208aSLeonid Yegoshin	PTR_ADDIU	a0, STORSIZE
1488c56208aSLeonid Yegoshin#endif /* CONFIG_CPU_MIPSR6 */
149a583158cSAtsushi Nemoto1:	ori		t1, a2, 0x3f		/* # of full blocks */
150a583158cSAtsushi Nemoto	xori		t1, 0x3f
1516d5155c2SMarkos Chandras	beqz		t1, .Lmemset_partial\@	/* no block to fill */
15226c5e07dSSteven J. Hill	 andi		t0, a2, 0x40-STORSIZE
153a583158cSAtsushi Nemoto
154a583158cSAtsushi Nemoto	PTR_ADDU	t1, a0			/* end address */
155a583158cSAtsushi Nemoto	.set		reorder
156a583158cSAtsushi Nemoto1:	PTR_ADDIU	a0, 64
157930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
158fd9720e9SMarkos Chandras	f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
159a583158cSAtsushi Nemoto	bne		t1, a0, 1b
160a583158cSAtsushi Nemoto	.set		noreorder
161a583158cSAtsushi Nemoto
1626d5155c2SMarkos Chandras.Lmemset_partial\@:
163930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
164a583158cSAtsushi Nemoto	PTR_LA		t1, 2f			/* where to start */
16526c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
16626c5e07dSSteven J. Hill	LONG_SRL	t7, t0, 1
16726c5e07dSSteven J. Hill#endif
168a583158cSAtsushi Nemoto#if LONGSIZE == 4
16926c5e07dSSteven J. Hill	PTR_SUBU	t1, FILLPTRG
170a583158cSAtsushi Nemoto#else
171a583158cSAtsushi Nemoto	.set		noat
17226c5e07dSSteven J. Hill	LONG_SRL	AT, FILLPTRG, 1
173a583158cSAtsushi Nemoto	PTR_SUBU	t1, AT
174619b6e18SMaciej W. Rozycki	.set		at
175a583158cSAtsushi Nemoto#endif
176a583158cSAtsushi Nemoto	jr		t1
177a583158cSAtsushi Nemoto	 PTR_ADDU	a0, t0			/* dest ptr */
178a583158cSAtsushi Nemoto
179a583158cSAtsushi Nemoto	.set		push
180a583158cSAtsushi Nemoto	.set		noreorder
181a583158cSAtsushi Nemoto	.set		nomacro
1826d5155c2SMarkos Chandras	/* ... but first do longs ... */
183fd9720e9SMarkos Chandras	f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
184a583158cSAtsushi Nemoto2:	.set		pop
18526c5e07dSSteven J. Hill	andi		a2, STORMASK		/* At most one long to go */
186a583158cSAtsushi Nemoto
187a583158cSAtsushi Nemoto	beqz		a2, 1f
1888c56208aSLeonid Yegoshin#ifndef CONFIG_CPU_MIPSR6
189a583158cSAtsushi Nemoto	 PTR_ADDU	a0, a2			/* What's left */
190930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
191a583158cSAtsushi Nemoto#ifdef __MIPSEB__
1926d5155c2SMarkos Chandras	EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
193dd2adea4SMarkos Chandras#else
1946d5155c2SMarkos Chandras	EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
195a583158cSAtsushi Nemoto#endif
1968c56208aSLeonid Yegoshin#else
1978c56208aSLeonid Yegoshin	 PTR_SUBU	t0, $0, a2
198b1c03f1eSMatt Redfearn	move		a2, zero		/* No remaining longs */
1998c56208aSLeonid Yegoshin	PTR_ADDIU	t0, 1
2008c56208aSLeonid Yegoshin	STORE_BYTE(0)
2018c56208aSLeonid Yegoshin	STORE_BYTE(1)
2028c56208aSLeonid Yegoshin#if LONGSIZE == 4
2038c56208aSLeonid Yegoshin	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
2048c56208aSLeonid Yegoshin#else
2058c56208aSLeonid Yegoshin	STORE_BYTE(2)
2068c56208aSLeonid Yegoshin	STORE_BYTE(3)
2078c56208aSLeonid Yegoshin	STORE_BYTE(4)
2088c56208aSLeonid Yegoshin	STORE_BYTE(5)
2098c56208aSLeonid Yegoshin	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
2108c56208aSLeonid Yegoshin#endif
2118c56208aSLeonid Yegoshin0:
2128c56208aSLeonid Yegoshin#endif
213a583158cSAtsushi Nemoto1:	jr		ra
214a583158cSAtsushi Nemoto	 move		a2, zero
215a583158cSAtsushi Nemoto
2166d5155c2SMarkos Chandras.Lsmall_memset\@:
217a583158cSAtsushi Nemoto	beqz		a2, 2f
218a583158cSAtsushi Nemoto	 PTR_ADDU	t1, a0, a2
219a583158cSAtsushi Nemoto
220a583158cSAtsushi Nemoto1:	PTR_ADDIU	a0, 1			/* fill bytewise */
221930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
222a583158cSAtsushi Nemoto	bne		t1, a0, 1b
2238a8158c8SMatt Redfearn	 EX(sb, a1, -1(a0), .Lsmall_fixup\@)
224a583158cSAtsushi Nemoto
225a583158cSAtsushi Nemoto2:	jr		ra			/* done */
226a583158cSAtsushi Nemoto	 move		a2, zero
2276d5155c2SMarkos Chandras	.if __memset == 1
228a583158cSAtsushi Nemoto	END(memset)
2296d5155c2SMarkos Chandras	.set __memset, 0
2306d5155c2SMarkos Chandras	.hidden __memset
2316d5155c2SMarkos Chandras	.endif
232a583158cSAtsushi Nemoto
2338e85f275SMaciej W. Rozycki#ifdef CONFIG_CPU_MIPSR6
2348c56208aSLeonid Yegoshin.Lbyte_fixup\@:
235*6312455aSMatt Redfearn	/*
236*6312455aSMatt Redfearn	 * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1
237*6312455aSMatt Redfearn	 *      a2     =             a2                -              t0                   + 1
238*6312455aSMatt Redfearn	 */
239b1c03f1eSMatt Redfearn	PTR_SUBU	a2, t0
2408c56208aSLeonid Yegoshin	jr		ra
2418c56208aSLeonid Yegoshin	 PTR_ADDIU	a2, 1
2428e85f275SMaciej W. Rozycki#endif /* CONFIG_CPU_MIPSR6 */
2438c56208aSLeonid Yegoshin
2446d5155c2SMarkos Chandras.Lfirst_fixup\@:
245*6312455aSMatt Redfearn	/* unset_bytes already in a2 */
246a583158cSAtsushi Nemoto	jr	ra
247a583158cSAtsushi Nemoto	 nop
248a583158cSAtsushi Nemoto
2496d5155c2SMarkos Chandras.Lfwd_fixup\@:
250*6312455aSMatt Redfearn	/*
251*6312455aSMatt Redfearn	 * unset_bytes = partial_start_addr +  #bytes   -     fault_addr
252*6312455aSMatt Redfearn	 *      a2     =         t1         + (a2 & 3f) - $28->task->BUADDR
253*6312455aSMatt Redfearn	 */
254a583158cSAtsushi Nemoto	PTR_L		t0, TI_TASK($28)
255a583158cSAtsushi Nemoto	andi		a2, 0x3f
256e5674ad6STony Wu	LONG_L		t0, THREAD_BUADDR(t0)
257a583158cSAtsushi Nemoto	LONG_ADDU	a2, t1
258a583158cSAtsushi Nemoto	jr		ra
259a583158cSAtsushi Nemoto	 LONG_SUBU	a2, t0
260a583158cSAtsushi Nemoto
2616d5155c2SMarkos Chandras.Lpartial_fixup\@:
262*6312455aSMatt Redfearn	/*
263*6312455aSMatt Redfearn	 * unset_bytes = partial_end_addr +      #bytes     -     fault_addr
264*6312455aSMatt Redfearn	 *      a2     =       a0         + (a2 & STORMASK) - $28->task->BUADDR
265*6312455aSMatt Redfearn	 */
266a583158cSAtsushi Nemoto	PTR_L		t0, TI_TASK($28)
26726c5e07dSSteven J. Hill	andi		a2, STORMASK
268e5674ad6STony Wu	LONG_L		t0, THREAD_BUADDR(t0)
269daf70d89SMatt Redfearn	LONG_ADDU	a2, a0
270a583158cSAtsushi Nemoto	jr		ra
271a583158cSAtsushi Nemoto	 LONG_SUBU	a2, t0
272a583158cSAtsushi Nemoto
2736d5155c2SMarkos Chandras.Llast_fixup\@:
274*6312455aSMatt Redfearn	/* unset_bytes already in a2 */
275a583158cSAtsushi Nemoto	jr		ra
276c96eebf0SMatt Redfearn	 nop
2776d5155c2SMarkos Chandras
2788a8158c8SMatt Redfearn.Lsmall_fixup\@:
279*6312455aSMatt Redfearn	/*
280*6312455aSMatt Redfearn	 * unset_bytes = end_addr - current_addr + 1
281*6312455aSMatt Redfearn	 *      a2     =    t1    -      a0      + 1
282*6312455aSMatt Redfearn	 */
2838a8158c8SMatt Redfearn	PTR_SUBU	a2, t1, a0
2848a8158c8SMatt Redfearn	jr		ra
2858a8158c8SMatt Redfearn	 PTR_ADDIU	a2, 1
2868a8158c8SMatt Redfearn
2876d5155c2SMarkos Chandras	.endm
2886d5155c2SMarkos Chandras
2896d5155c2SMarkos Chandras/*
2906d5155c2SMarkos Chandras * memset(void *s, int c, size_t n)
2916d5155c2SMarkos Chandras *
2926d5155c2SMarkos Chandras * a0: start of area to clear
2936d5155c2SMarkos Chandras * a1: char to fill with
2946d5155c2SMarkos Chandras * a2: size of area to clear
2956d5155c2SMarkos Chandras */
2966d5155c2SMarkos Chandras
2976d5155c2SMarkos ChandrasLEAF(memset)
298576a2f0cSPaul BurtonEXPORT_SYMBOL(memset)
2996d5155c2SMarkos Chandras	beqz		a1, 1f
3006d5155c2SMarkos Chandras	 move		v0, a0			/* result */
3016d5155c2SMarkos Chandras
3026d5155c2SMarkos Chandras	andi		a1, 0xff		/* spread fillword */
3036d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 8
3046d5155c2SMarkos Chandras	or		a1, t1
3056d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 16
3066d5155c2SMarkos Chandras#if LONGSIZE == 8
3076d5155c2SMarkos Chandras	or		a1, t1
3086d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 32
3096d5155c2SMarkos Chandras#endif
3106d5155c2SMarkos Chandras	or		a1, t1
3116d5155c2SMarkos Chandras1:
312fd9720e9SMarkos Chandras#ifndef CONFIG_EVA
3136d5155c2SMarkos ChandrasFEXPORT(__bzero)
314576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero)
315d6a428fbSJames Hogan#else
316d6a428fbSJames HoganFEXPORT(__bzero_kernel)
317576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero_kernel)
318fd9720e9SMarkos Chandras#endif
3196d5155c2SMarkos Chandras	__BUILD_BZERO LEGACY_MODE
320fd9720e9SMarkos Chandras
321fd9720e9SMarkos Chandras#ifdef CONFIG_EVA
322fd9720e9SMarkos ChandrasLEAF(__bzero)
323576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero)
324fd9720e9SMarkos Chandras	__BUILD_BZERO EVA_MODE
325fd9720e9SMarkos ChandrasEND(__bzero)
326fd9720e9SMarkos Chandras#endif
327