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.
8 */
9#include <asm/asm.h>
10#include <asm/asm-offsets.h>
11#include <asm/regdef.h>
12
13#if LONGSIZE == 4
14#define LONG_S_L swl
15#define LONG_S_R swr
16#else
17#define LONG_S_L sdl
18#define LONG_S_R sdr
19#endif
20
21#define EX(insn,reg,addr,handler)			\
229:	insn	reg, addr;				\
23	.section __ex_table,"a"; 			\
24	PTR	9b, handler; 				\
25	.previous
26
27	.macro	f_fill64 dst, offset, val, fixup
28	EX(LONG_S, \val, (\offset +  0 * LONGSIZE)(\dst), \fixup)
29	EX(LONG_S, \val, (\offset +  1 * LONGSIZE)(\dst), \fixup)
30	EX(LONG_S, \val, (\offset +  2 * LONGSIZE)(\dst), \fixup)
31	EX(LONG_S, \val, (\offset +  3 * LONGSIZE)(\dst), \fixup)
32	EX(LONG_S, \val, (\offset +  4 * LONGSIZE)(\dst), \fixup)
33	EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
34	EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
35	EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
36#if LONGSIZE == 4
37	EX(LONG_S, \val, (\offset +  8 * LONGSIZE)(\dst), \fixup)
38	EX(LONG_S, \val, (\offset +  9 * LONGSIZE)(\dst), \fixup)
39	EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
40	EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
41	EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
42	EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
43	EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
44	EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
45#endif
46	.endm
47
48/*
49 * memset(void *s, int c, size_t n)
50 *
51 * a0: start of area to clear
52 * a1: char to fill with
53 * a2: size of area to clear
54 */
55	.section .text.fastpath, "a"
56	.set	noreorder
57	.align	5
58LEAF(memset)
59	beqz		a1, 1f
60	 move		v0, a0			/* result */
61
62	andi		a1, 0xff		/* spread fillword */
63	LONG_SLL		t1, a1, 8
64	or		a1, t1
65	LONG_SLL		t1, a1, 16
66#if LONGSIZE == 8
67	or		a1, t1
68	LONG_SLL		t1, a1, 32
69#endif
70	or		a1, t1
711:
72
73FEXPORT(__bzero)
74	sltiu		t0, a2, LONGSIZE	/* very small region? */
75	bnez		t0, small_memset
76	 andi		t0, a0, LONGMASK	/* aligned? */
77
78	beqz		t0, 1f
79	 PTR_SUBU	t0, LONGSIZE		/* alignment in bytes */
80
81#ifdef __MIPSEB__
82	EX(LONG_S_L, a1, (a0), first_fixup)	/* make word/dword aligned */
83#endif
84#ifdef __MIPSEL__
85	EX(LONG_S_R, a1, (a0), first_fixup)	/* make word/dword aligned */
86#endif
87	PTR_SUBU	a0, t0			/* long align ptr */
88	PTR_ADDU	a2, t0			/* correct size */
89
901:	ori		t1, a2, 0x3f		/* # of full blocks */
91	xori		t1, 0x3f
92	beqz		t1, memset_partial	/* no block to fill */
93	 andi		t0, a2, 0x40-LONGSIZE
94
95	PTR_ADDU	t1, a0			/* end address */
96	.set		reorder
971:	PTR_ADDIU	a0, 64
98	f_fill64 a0, -64, a1, fwd_fixup
99	bne		t1, a0, 1b
100	.set		noreorder
101
102memset_partial:
103	PTR_LA		t1, 2f			/* where to start */
104#if LONGSIZE == 4
105	PTR_SUBU	t1, t0
106#else
107	.set		noat
108	LONG_SRL		AT, t0, 1
109	PTR_SUBU	t1, AT
110	.set		noat
111#endif
112	jr		t1
113	 PTR_ADDU	a0, t0			/* dest ptr */
114
115	.set		push
116	.set		noreorder
117	.set		nomacro
118	f_fill64 a0, -64, a1, partial_fixup	/* ... but first do longs ... */
1192:	.set		pop
120	andi		a2, LONGMASK		/* At most one long to go */
121
122	beqz		a2, 1f
123	 PTR_ADDU	a0, a2			/* What's left */
124#ifdef __MIPSEB__
125	EX(LONG_S_R, a1, -1(a0), last_fixup)
126#endif
127#ifdef __MIPSEL__
128	EX(LONG_S_L, a1, -1(a0), last_fixup)
129#endif
1301:	jr		ra
131	 move		a2, zero
132
133small_memset:
134	beqz		a2, 2f
135	 PTR_ADDU	t1, a0, a2
136
1371:	PTR_ADDIU	a0, 1			/* fill bytewise */
138	bne		t1, a0, 1b
139	 sb		a1, -1(a0)
140
1412:	jr		ra			/* done */
142	 move		a2, zero
143	END(memset)
144
145first_fixup:
146	jr	ra
147	 nop
148
149fwd_fixup:
150	PTR_L		t0, TI_TASK($28)
151	LONG_L		t0, THREAD_BUADDR(t0)
152	andi		a2, 0x3f
153	LONG_ADDU	a2, t1
154	jr		ra
155	 LONG_SUBU	a2, t0
156
157partial_fixup:
158	PTR_L		t0, TI_TASK($28)
159	LONG_L		t0, THREAD_BUADDR(t0)
160	andi		a2, LONGMASK
161	LONG_ADDU	a2, t1
162	jr		ra
163	 LONG_SUBU	a2, t0
164
165last_fixup:
166	jr		ra
167	 andi		v1, a2, LONGMASK
168