xref: /openbmc/linux/arch/mips/lib/memset.S (revision 64c70b1c)
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	.set	noreorder
56	.align	5
57LEAF(memset)
58	beqz		a1, 1f
59	 move		v0, a0			/* result */
60
61	andi		a1, 0xff		/* spread fillword */
62	LONG_SLL		t1, a1, 8
63	or		a1, t1
64	LONG_SLL		t1, a1, 16
65#if LONGSIZE == 8
66	or		a1, t1
67	LONG_SLL		t1, a1, 32
68#endif
69	or		a1, t1
701:
71
72FEXPORT(__bzero)
73	sltiu		t0, a2, LONGSIZE	/* very small region? */
74	bnez		t0, small_memset
75	 andi		t0, a0, LONGMASK	/* aligned? */
76
77	beqz		t0, 1f
78	 PTR_SUBU	t0, LONGSIZE		/* alignment in bytes */
79
80#ifdef __MIPSEB__
81	EX(LONG_S_L, a1, (a0), first_fixup)	/* make word/dword aligned */
82#endif
83#ifdef __MIPSEL__
84	EX(LONG_S_R, a1, (a0), first_fixup)	/* make word/dword aligned */
85#endif
86	PTR_SUBU	a0, t0			/* long align ptr */
87	PTR_ADDU	a2, t0			/* correct size */
88
891:	ori		t1, a2, 0x3f		/* # of full blocks */
90	xori		t1, 0x3f
91	beqz		t1, memset_partial	/* no block to fill */
92	 andi		t0, a2, 0x40-LONGSIZE
93
94	PTR_ADDU	t1, a0			/* end address */
95	.set		reorder
961:	PTR_ADDIU	a0, 64
97	f_fill64 a0, -64, a1, fwd_fixup
98	bne		t1, a0, 1b
99	.set		noreorder
100
101memset_partial:
102	PTR_LA		t1, 2f			/* where to start */
103#if LONGSIZE == 4
104	PTR_SUBU	t1, t0
105#else
106	.set		noat
107	LONG_SRL		AT, t0, 1
108	PTR_SUBU	t1, AT
109	.set		noat
110#endif
111	jr		t1
112	 PTR_ADDU	a0, t0			/* dest ptr */
113
114	.set		push
115	.set		noreorder
116	.set		nomacro
117	f_fill64 a0, -64, a1, partial_fixup	/* ... but first do longs ... */
1182:	.set		pop
119	andi		a2, LONGMASK		/* At most one long to go */
120
121	beqz		a2, 1f
122	 PTR_ADDU	a0, a2			/* What's left */
123#ifdef __MIPSEB__
124	EX(LONG_S_R, a1, -1(a0), last_fixup)
125#endif
126#ifdef __MIPSEL__
127	EX(LONG_S_L, a1, -1(a0), last_fixup)
128#endif
1291:	jr		ra
130	 move		a2, zero
131
132small_memset:
133	beqz		a2, 2f
134	 PTR_ADDU	t1, a0, a2
135
1361:	PTR_ADDIU	a0, 1			/* fill bytewise */
137	bne		t1, a0, 1b
138	 sb		a1, -1(a0)
139
1402:	jr		ra			/* done */
141	 move		a2, zero
142	END(memset)
143
144first_fixup:
145	jr	ra
146	 nop
147
148fwd_fixup:
149	PTR_L		t0, TI_TASK($28)
150	LONG_L		t0, THREAD_BUADDR(t0)
151	andi		a2, 0x3f
152	LONG_ADDU	a2, t1
153	jr		ra
154	 LONG_SUBU	a2, t0
155
156partial_fixup:
157	PTR_L		t0, TI_TASK($28)
158	LONG_L		t0, THREAD_BUADDR(t0)
159	andi		a2, LONGMASK
160	LONG_ADDU	a2, t1
161	jr		ra
162	 LONG_SUBU	a2, t0
163
164last_fixup:
165	jr		ra
166	 andi		v1, a2, LONGMASK
167