memset.S 5.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 9
 * Copyright (C) 2007 by Maciej W. Rozycki
 * Copyright (C) 2011, 2012 MIPS Technologies, Inc.
L
Linus Torvalds 已提交
10 11
 */
#include <asm/asm.h>
12
#include <asm/asm-offsets.h>
L
Linus Torvalds 已提交
13 14
#include <asm/regdef.h>

A
Atsushi Nemoto 已提交
15 16 17 18 19 20 21 22
#if LONGSIZE == 4
#define LONG_S_L swl
#define LONG_S_R swr
#else
#define LONG_S_L sdl
#define LONG_S_R sdr
#endif

23 24 25 26 27 28 29 30 31 32 33 34 35 36
#ifdef CONFIG_CPU_MICROMIPS
#define STORSIZE (LONGSIZE * 2)
#define STORMASK (STORSIZE - 1)
#define FILL64RG t8
#define FILLPTRG t7
#undef  LONG_S
#define LONG_S LONG_SP
#else
#define STORSIZE LONGSIZE
#define STORMASK LONGMASK
#define FILL64RG a1
#define FILLPTRG t0
#endif

37 38 39
#define LEGACY_MODE 1
#define EVA_MODE    2

40 41 42 43 44 45 46
/*
 * No need to protect it with EVA #ifdefery. The generated block of code
 * will never be assembled if EVA is not enabled.
 */
#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)

L
Linus Torvalds 已提交
47
#define EX(insn,reg,addr,handler)			\
48 49 50 51 52
	.if \mode == LEGACY_MODE;			\
9:		insn	reg, addr;			\
	.else;						\
9:		___BUILD_EVA_INSN(insn, reg, addr);	\
	.endif;						\
R
Ralf Baechle 已提交
53 54
	.section __ex_table,"a";			\
	PTR	9b, handler;				\
L
Linus Torvalds 已提交
55 56
	.previous

57
	.macro	f_fill64 dst, offset, val, fixup, mode
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	EX(LONG_S, \val, (\offset +  0 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  1 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  2 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  3 * STORSIZE)(\dst), \fixup)
#if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS))
	EX(LONG_S, \val, (\offset +  4 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  5 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  6 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  7 * STORSIZE)(\dst), \fixup)
#endif
#if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4))
	EX(LONG_S, \val, (\offset +  8 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset +  9 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup)
	EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup)
A
Atsushi Nemoto 已提交
77
#endif
L
Linus Torvalds 已提交
78 79 80 81 82
	.endm

	.set	noreorder
	.align	5

83 84 85 86 87 88 89 90 91 92 93
	/*
	 * Macro to generate the __bzero{,_user} symbol
	 * Arguments:
	 * mode: LEGACY_MODE or EVA_MODE
	 */
	.macro __BUILD_BZERO mode
	/* Initialize __memset if this is the first time we call this macro */
	.ifnotdef __memset
	.set __memset, 1
	.hidden __memset /* Make sure it does not leak */
	.endif
L
Linus Torvalds 已提交
94

95
	sltiu		t0, a2, STORSIZE	/* very small region? */
96
	bnez		t0, .Lsmall_memset\@
97
	andi		t0, a0, STORMASK	/* aligned? */
L
Linus Torvalds 已提交
98

99 100 101 102
#ifdef CONFIG_CPU_MICROMIPS
	move		t8, a1			/* used by 'swp' instruction */
	move		t9, a1
#endif
103
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
L
Linus Torvalds 已提交
104
	beqz		t0, 1f
105
	PTR_SUBU	t0, STORSIZE		/* alignment in bytes */
106 107
#else
	.set		noat
108
	li		AT, STORSIZE
109
	beqz		t0, 1f
110
	PTR_SUBU	t0, AT			/* alignment in bytes */
111 112
	.set		at
#endif
L
Linus Torvalds 已提交
113

114
	R10KCBARRIER(0(ra))
L
Linus Torvalds 已提交
115
#ifdef __MIPSEB__
116
	EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
L
Linus Torvalds 已提交
117 118
#endif
#ifdef __MIPSEL__
119
	EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@)	/* make word/dword aligned */
L
Linus Torvalds 已提交
120 121 122 123 124 125
#endif
	PTR_SUBU	a0, t0			/* long align ptr */
	PTR_ADDU	a2, t0			/* correct size */

1:	ori		t1, a2, 0x3f		/* # of full blocks */
	xori		t1, 0x3f
126
	beqz		t1, .Lmemset_partial\@	/* no block to fill */
127
	andi		t0, a2, 0x40-STORSIZE
L
Linus Torvalds 已提交
128 129 130 131

	PTR_ADDU	t1, a0			/* end address */
	.set		reorder
1:	PTR_ADDIU	a0, 64
132
	R10KCBARRIER(0(ra))
133
	f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
L
Linus Torvalds 已提交
134 135 136
	bne		t1, a0, 1b
	.set		noreorder

137
.Lmemset_partial\@:
138
	R10KCBARRIER(0(ra))
L
Linus Torvalds 已提交
139
	PTR_LA		t1, 2f			/* where to start */
140 141 142
#ifdef CONFIG_CPU_MICROMIPS
	LONG_SRL	t7, t0, 1
#endif
A
Atsushi Nemoto 已提交
143
#if LONGSIZE == 4
144
	PTR_SUBU	t1, FILLPTRG
A
Atsushi Nemoto 已提交
145 146
#else
	.set		noat
147
	LONG_SRL	AT, FILLPTRG, 1
A
Atsushi Nemoto 已提交
148
	PTR_SUBU	t1, AT
149
	.set		at
A
Atsushi Nemoto 已提交
150
#endif
L
Linus Torvalds 已提交
151
	jr		t1
152
	PTR_ADDU	a0, t0			/* dest ptr */
L
Linus Torvalds 已提交
153 154 155 156

	.set		push
	.set		noreorder
	.set		nomacro
157
	/* ... but first do longs ... */
158
	f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
L
Linus Torvalds 已提交
159
2:	.set		pop
160
	andi		a2, STORMASK		/* At most one long to go */
L
Linus Torvalds 已提交
161 162

	beqz		a2, 1f
163
	PTR_ADDU	a0, a2			/* What's left */
164
	R10KCBARRIER(0(ra))
L
Linus Torvalds 已提交
165
#ifdef __MIPSEB__
166
	EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
L
Linus Torvalds 已提交
167 168
#endif
#ifdef __MIPSEL__
169
	EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
L
Linus Torvalds 已提交
170 171
#endif
1:	jr		ra
172
	move		a2, zero
L
Linus Torvalds 已提交
173

174
.Lsmall_memset\@:
L
Linus Torvalds 已提交
175
	beqz		a2, 2f
176
	PTR_ADDU	t1, a0, a2
L
Linus Torvalds 已提交
177 178

1:	PTR_ADDIU	a0, 1			/* fill bytewise */
179
	R10KCBARRIER(0(ra))
L
Linus Torvalds 已提交
180
	bne		t1, a0, 1b
181
	sb		a1, -1(a0)
L
Linus Torvalds 已提交
182 183

2:	jr		ra			/* done */
184
	move		a2, zero
185
	.if __memset == 1
L
Linus Torvalds 已提交
186
	END(memset)
187 188 189
	.set __memset, 0
	.hidden __memset
	.endif
L
Linus Torvalds 已提交
190

191
.Lfirst_fixup\@:
L
Linus Torvalds 已提交
192
	jr	ra
193
	nop
L
Linus Torvalds 已提交
194

195
.Lfwd_fixup\@:
L
Linus Torvalds 已提交
196 197
	PTR_L		t0, TI_TASK($28)
	andi		a2, 0x3f
198
	LONG_L		t0, THREAD_BUADDR(t0)
L
Linus Torvalds 已提交
199 200
	LONG_ADDU	a2, t1
	jr		ra
201
	LONG_SUBU	a2, t0
L
Linus Torvalds 已提交
202

203
.Lpartial_fixup\@:
L
Linus Torvalds 已提交
204
	PTR_L		t0, TI_TASK($28)
205
	andi		a2, STORMASK
206
	LONG_L		t0, THREAD_BUADDR(t0)
L
Linus Torvalds 已提交
207 208
	LONG_ADDU	a2, t1
	jr		ra
209
	LONG_SUBU	a2, t0
L
Linus Torvalds 已提交
210

211
.Llast_fixup\@:
L
Linus Torvalds 已提交
212
	jr		ra
213
	andi		v1, a2, STORMASK
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

	.endm

/*
 * memset(void *s, int c, size_t n)
 *
 * a0: start of area to clear
 * a1: char to fill with
 * a2: size of area to clear
 */

LEAF(memset)
	beqz		a1, 1f
	move		v0, a0			/* result */

	andi		a1, 0xff		/* spread fillword */
	LONG_SLL		t1, a1, 8
	or		a1, t1
	LONG_SLL		t1, a1, 16
#if LONGSIZE == 8
	or		a1, t1
	LONG_SLL		t1, a1, 32
#endif
	or		a1, t1
1:
239
#ifndef CONFIG_EVA
240
FEXPORT(__bzero)
241
#endif
242
	__BUILD_BZERO LEGACY_MODE
243 244 245 246 247 248

#ifdef CONFIG_EVA
LEAF(__bzero)
	__BUILD_BZERO EVA_MODE
END(__bzero)
#endif