xref: /linux/arch/mips/lib/memset.S (revision daf70d89f80c6e1772233da9e020114b1254e7e0)
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
1988c56208aSLeonid Yegoshin	PTR_ADDIU	t0, 1
1998c56208aSLeonid Yegoshin	STORE_BYTE(0)
2008c56208aSLeonid Yegoshin	STORE_BYTE(1)
2018c56208aSLeonid Yegoshin#if LONGSIZE == 4
2028c56208aSLeonid Yegoshin	EX(sb, a1, 2(a0), .Lbyte_fixup\@)
2038c56208aSLeonid Yegoshin#else
2048c56208aSLeonid Yegoshin	STORE_BYTE(2)
2058c56208aSLeonid Yegoshin	STORE_BYTE(3)
2068c56208aSLeonid Yegoshin	STORE_BYTE(4)
2078c56208aSLeonid Yegoshin	STORE_BYTE(5)
2088c56208aSLeonid Yegoshin	EX(sb, a1, 6(a0), .Lbyte_fixup\@)
2098c56208aSLeonid Yegoshin#endif
2108c56208aSLeonid Yegoshin0:
2118c56208aSLeonid Yegoshin#endif
212a583158cSAtsushi Nemoto1:	jr		ra
213a583158cSAtsushi Nemoto	move		a2, zero
214a583158cSAtsushi Nemoto
2156d5155c2SMarkos Chandras.Lsmall_memset\@:
216a583158cSAtsushi Nemoto	beqz		a2, 2f
217a583158cSAtsushi Nemoto	PTR_ADDU	t1, a0, a2
218a583158cSAtsushi Nemoto
219a583158cSAtsushi Nemoto1:	PTR_ADDIU	a0, 1			/* fill bytewise */
220930bff88SThomas Bogendoerfer	R10KCBARRIER(0(ra))
221a583158cSAtsushi Nemoto	bne		t1, a0, 1b
2228a8158c8SMatt Redfearn	 EX(sb, a1, -1(a0), .Lsmall_fixup\@)
223a583158cSAtsushi Nemoto
224a583158cSAtsushi Nemoto2:	jr		ra			/* done */
225a583158cSAtsushi Nemoto	move		a2, zero
2266d5155c2SMarkos Chandras	.if __memset == 1
227a583158cSAtsushi Nemoto	END(memset)
2286d5155c2SMarkos Chandras	.set __memset, 0
2296d5155c2SMarkos Chandras	.hidden __memset
2306d5155c2SMarkos Chandras	.endif
231a583158cSAtsushi Nemoto
2328e85f275SMaciej W. Rozycki#ifdef CONFIG_CPU_MIPSR6
2338c56208aSLeonid Yegoshin.Lbyte_fixup\@:
2348c56208aSLeonid Yegoshin	PTR_SUBU	a2, $0, t0
2358c56208aSLeonid Yegoshin	jr		ra
2368c56208aSLeonid Yegoshin	 PTR_ADDIU	a2, 1
2378e85f275SMaciej W. Rozycki#endif /* CONFIG_CPU_MIPSR6 */
2388c56208aSLeonid Yegoshin
2396d5155c2SMarkos Chandras.Lfirst_fixup\@:
240a583158cSAtsushi Nemoto	jr	ra
241a583158cSAtsushi Nemoto	nop
242a583158cSAtsushi Nemoto
2436d5155c2SMarkos Chandras.Lfwd_fixup\@:
244a583158cSAtsushi Nemoto	PTR_L		t0, TI_TASK($28)
245a583158cSAtsushi Nemoto	andi		a2, 0x3f
246e5674ad6STony Wu	LONG_L		t0, THREAD_BUADDR(t0)
247a583158cSAtsushi Nemoto	LONG_ADDU	a2, t1
248a583158cSAtsushi Nemoto	jr		ra
249a583158cSAtsushi Nemoto	LONG_SUBU	a2, t0
250a583158cSAtsushi Nemoto
2516d5155c2SMarkos Chandras.Lpartial_fixup\@:
252a583158cSAtsushi Nemoto	PTR_L		t0, TI_TASK($28)
25326c5e07dSSteven J. Hill	andi		a2, STORMASK
254e5674ad6STony Wu	LONG_L		t0, THREAD_BUADDR(t0)
255*daf70d89SMatt Redfearn	LONG_ADDU	a2, a0
256a583158cSAtsushi Nemoto	jr		ra
257a583158cSAtsushi Nemoto	LONG_SUBU	a2, t0
258a583158cSAtsushi Nemoto
2596d5155c2SMarkos Chandras.Llast_fixup\@:
260a583158cSAtsushi Nemoto	jr		ra
26126c5e07dSSteven J. Hill	andi		v1, a2, STORMASK
2626d5155c2SMarkos Chandras
2638a8158c8SMatt Redfearn.Lsmall_fixup\@:
2648a8158c8SMatt Redfearn	PTR_SUBU	a2, t1, a0
2658a8158c8SMatt Redfearn	jr		ra
2668a8158c8SMatt Redfearn	 PTR_ADDIU	a2, 1
2678a8158c8SMatt Redfearn
2686d5155c2SMarkos Chandras	.endm
2696d5155c2SMarkos Chandras
2706d5155c2SMarkos Chandras/*
2716d5155c2SMarkos Chandras * memset(void *s, int c, size_t n)
2726d5155c2SMarkos Chandras *
2736d5155c2SMarkos Chandras * a0: start of area to clear
2746d5155c2SMarkos Chandras * a1: char to fill with
2756d5155c2SMarkos Chandras * a2: size of area to clear
2766d5155c2SMarkos Chandras */
2776d5155c2SMarkos Chandras
2786d5155c2SMarkos ChandrasLEAF(memset)
279576a2f0cSPaul BurtonEXPORT_SYMBOL(memset)
2806d5155c2SMarkos Chandras	beqz		a1, 1f
2816d5155c2SMarkos Chandras	move		v0, a0			/* result */
2826d5155c2SMarkos Chandras
2836d5155c2SMarkos Chandras	andi		a1, 0xff		/* spread fillword */
2846d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 8
2856d5155c2SMarkos Chandras	or		a1, t1
2866d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 16
2876d5155c2SMarkos Chandras#if LONGSIZE == 8
2886d5155c2SMarkos Chandras	or		a1, t1
2896d5155c2SMarkos Chandras	LONG_SLL		t1, a1, 32
2906d5155c2SMarkos Chandras#endif
2916d5155c2SMarkos Chandras	or		a1, t1
2926d5155c2SMarkos Chandras1:
293fd9720e9SMarkos Chandras#ifndef CONFIG_EVA
2946d5155c2SMarkos ChandrasFEXPORT(__bzero)
295576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero)
296d6a428fbSJames Hogan#else
297d6a428fbSJames HoganFEXPORT(__bzero_kernel)
298576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero_kernel)
299fd9720e9SMarkos Chandras#endif
3006d5155c2SMarkos Chandras	__BUILD_BZERO LEGACY_MODE
301fd9720e9SMarkos Chandras
302fd9720e9SMarkos Chandras#ifdef CONFIG_EVA
303fd9720e9SMarkos ChandrasLEAF(__bzero)
304576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero)
305fd9720e9SMarkos Chandras	__BUILD_BZERO EVA_MODE
306fd9720e9SMarkos ChandrasEND(__bzero)
307fd9720e9SMarkos Chandras#endif
308