xref: /netbsd/sys/arch/mips/mips/copy.S (revision 6550d01e)
1/*	$NetBSD: copy.S,v 1.10 2010/07/07 01:21:47 chs Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Digital Equipment Corporation and Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * Copyright (C) 1989 Digital Equipment Corporation.
35 * Permission to use, copy, modify, and distribute this software and
36 * its documentation for any purpose and without fee is hereby granted,
37 * provided that the above copyright notice appears in all copies.
38 * Digital Equipment Corporation makes no representations about the
39 * suitability of this software for any purpose.  It is provided "as is"
40 * without express or implied warranty.
41 *
42 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
43 *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
44 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
45 *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
46 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
47 *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
48 *
49 *	@(#)locore.s	8.5 (Berkeley) 1/4/94
50 */
51
52/*
53 * copy(9) - kernel space to/from user space copy functions.
54 * fetch(9) - fetch data from user-space.
55 * store(9) - store data to user-space.
56 */
57
58#include <sys/errno.h>
59#include <mips/asm.h>
60#include <mips/cpu.h>
61#include "assym.h"
62
63	.set	noreorder
64/*
65 * int copystr(void *kfaddr, void *kdaddr, size_t maxlen, size_t *lencopied)
66 * Copy a NIL-terminated string, at most maxlen characters long.  Return the
67 * number of characters copied (including the NIL) in *lencopied.  If the
68 * string is too long, return ENAMETOOLONG; else return 0.
69 */
70LEAF(copystr)
71	move	t0, a2
72	beq	a2, zero, 4f
73	 nop
741:
75	lbu	v0, 0(a0)
76	PTR_SUBU a2, a2, 1
77	beq	v0, zero, 2f
78	 sb	v0, 0(a1)			# each byte until NIL
79	PTR_ADDU a0, a0, 1
80	bne	a2, zero, 1b			# less than maxlen
81	 PTR_ADDU a1, a1, 1
824:
83	li	v0, ENAMETOOLONG		# run out of space
842:
85	beq	a3, zero, 3f			# return num. of copied bytes
86	 PTR_SUBU a2, t0, a2			# if the 4th arg was non-NULL
87	PTR_S	a2, 0(a3)
883:
89	j	ra				# v0 is 0 or ENAMETOOLONG
90	 nop
91END(copystr)
92
93/*
94 * int copyinstr(void *uaddr, void *kaddr, size_t maxlen, size_t *lencopied)
95 * Copy a NUL-terminated string, at most maxlen characters long, from the
96 * user's address space.  Return the number of characters copied (including
97 * the NUL) in *lencopied.  If the string is too long, return ENAMETOOLONG;
98 * else return 0 or EFAULT.
99 */
100LEAF(copyinstr)
101	PTR_L	v1, L_PCB(MIPS_CURLWP)
102	PTR_LA	v0, _C_LABEL(copystrerr)
103	blt	a0, zero, _C_LABEL(copystrefault)
104	 PTR_S	v0, PCB_ONFAULT(v1)
105	move	t0, a2
106	beq	a2, zero, 4f
107	 nop
1081:
109	lbu	v0, 0(a0)
110	PTR_SUBU a2, a2, 1
111	beq	v0, zero, 2f
112	 sb	v0, 0(a1)			# write trailing NUL
113	PTR_ADDU a0, a0, 1
114	bne	a2, zero, 1b
115	 PTR_ADDU a1, a1, 1
1164:
117	li	v0, ENAMETOOLONG
1182:
119	beq	a3, zero, 3f
120	 PTR_SUBU a2, t0, a2
121	PTR_S	a2, 0(a3)
1223:
123	j	ra				# v0 is 0 or ENAMETOOLONG
124	 PTR_S	zero, PCB_ONFAULT(v1)
125END(copyinstr)
126
127/*
128 * int copyoutstr(void *uaddr, void *kaddr, size_t maxlen, size_t *lencopied);
129 * Copy a NIL-terminated string, at most maxlen characters long, into the
130 * user's address space.  Return the number of characters copied (including
131 * the NIL) in *lencopied.  If the string is too long, return ENAMETOOLONG;
132 * else return 0 or EFAULT.
133 */
134LEAF(copyoutstr)
135	PTR_L	v1, L_PCB(MIPS_CURLWP)
136	PTR_LA	v0, _C_LABEL(copystrerr)
137	blt	a1, zero, _C_LABEL(copystrefault)
138	 PTR_S	v0, PCB_ONFAULT(v1)
139	move	t0, a2
140	beq	a2, zero, 4f
141	 nop
1421:
143	lbu	v0, 0(a0)
144	PTR_SUBU a2, a2, 1
145	beq	v0, zero, 2f
146	 sb	v0, 0(a1)
147	PTR_ADDU a0, a0, 1
148	 bne	a2, zero, 1b
149	PTR_ADDU a1, a1, 1
1504:
151	li	v0, ENAMETOOLONG
1522:
153	beq	a3, zero, 3f
154	PTR_SUBU a2, t0, a2
155	PTR_S	a2, 0(a3)
1563:
157	j	ra				# v0 is 0 or ENAMETOOLONG
158	 PTR_S	zero, PCB_ONFAULT(v1)
159END(copyoutstr)
160
161LEAF(copystrerr)
162	j	ra
163	 PTR_S	zero, PCB_ONFAULT(v1)
164END(copystrerr)
165
166LEAF(copystrefault)
167	b	copystrerr
168	 li	v0, EFAULT
169END(copystrefault)
170
171/*
172 * kcopy(const void *src, void *dst, size_t len);
173 *
174 * Copy len bytes from src to dst, aborting if we encounter a fatal
175 * page fault.
176 *
177 * kcopy() _must_ save and restore the old fault handler since it is
178 * called by uiomove(), which may be in the path of servicing a non-fatal
179 * page fault.
180 */
181NESTED(kcopy, 2*CALLFRAME_SIZ, ra)
182	PTR_SUBU sp, sp, 2*CALLFRAME_SIZ	# set up stack frame
183	/* Frame contains RA (31) and S0 (16). */
184	.mask	0x80010000, -SZREG
185	REG_S	ra, CALLFRAME_SIZ+CALLFRAME_RA(sp)	# save ra
186	REG_S	s0, CALLFRAME_SIZ+CALLFRAME_S0(sp)	# save s0
187	move	v0, a0				# swap a0, a1 for call to memcpy
188	move	a0, a1
189	move	a1, v0
190	PTR_L	v1, L_PCB(MIPS_CURLWP)		# set up fault handler
191	PTR_LA	v0, _C_LABEL(kcopyerr)
192	PTR_L	s0, PCB_ONFAULT(v1)		# save old handler
193	jal	memcpy
194	 PTR_S	v0, PCB_ONFAULT(v1)
195
196	PTR_L	v1, L_PCB(MIPS_CURLWP)		# restore the old handler
197	REG_L	ra, CALLFRAME_SIZ+CALLFRAME_RA(sp)	# restore ra
198	PTR_S	s0, PCB_ONFAULT(v1)
199	REG_L	s0, CALLFRAME_SIZ+CALLFRAME_S0(sp)	# restore s0
200	PTR_ADDU sp, sp, 2*CALLFRAME_SIZ	# kill stack frame
201	j	ra
202	 move	v0, zero			# success!
203END(kcopy)
204
205LEAF(kcopyerr)
206	PTR_L	v1, L_PCB(MIPS_CURLWP)		# restore the old handler
207	REG_L	ra, CALLFRAME_SIZ+CALLFRAME_RA(sp) 	# restore ra
208	PTR_S	s0, PCB_ONFAULT(v1)
209	REG_L	s0, CALLFRAME_SIZ+CALLFRAME_S0(sp) 	# restore s0
210	j	ra
211	 PTR_ADDU sp, sp, 2*CALLFRAME_SIZ	# kill stack frame
212END(kcopyerr)
213
214/*
215 * int copyin(void *uaddr, void *kaddr, size_t len)
216 * Copies len bytes of data from the user-space address uaddr to the
217 * kernel-space address kaddr.  copyin returns 0 on success or EFAULT
218 * if a bad address is encountered.
219 */
220NESTED(copyin, CALLFRAME_SIZ, ra)
221	PTR_SUBU sp, sp, CALLFRAME_SIZ
222	.mask	0x80000000, -4
223	REG_S	ra, CALLFRAME_RA(sp)
224	 blt	a0, zero, _C_LABEL(copyefault)
225	move	v0, a0				# swap a0, a1 for call to memcpy
226	move	a0, a1
227	move	a1, v0
228	PTR_L	v1, L_PCB(MIPS_CURLWP)
229	PTR_LA	v0, _C_LABEL(copyerr)
230	jal	memcpy
231	 PTR_S	v0, PCB_ONFAULT(v1)
232
233	PTR_L	v1, L_PCB(MIPS_CURLWP)
234	REG_L	ra, CALLFRAME_RA(sp)
235	PTR_ADDU sp, sp, CALLFRAME_SIZ
236	PTR_S	zero, PCB_ONFAULT(v1)
237	j	ra
238	 move	v0, zero
239END(copyin)
240
241/*
242 * int copyout(void *kaddr, void *uaddr, size_t len)
243 * Copies len bytes of data from the kernel-space address kaddr to the
244 * user-space address uaddr.  copyout returns 0 on success or EFAULT
245 * if a bad address is encountered.
246 */
247NESTED(copyout, CALLFRAME_SIZ, ra)
248	PTR_SUBU sp, sp, CALLFRAME_SIZ
249	.mask	0x80000000, -4
250	REG_S	ra, CALLFRAME_RA(sp)
251	blt	a1, zero, _C_LABEL(copyefault)
252	move	v0, a0				# swap a0, a1 for call to memcpy
253	move	a0, a1
254	move	a1, v0
255	PTR_L	v1, L_PCB(MIPS_CURLWP)
256	PTR_LA	v0, _C_LABEL(copyerr)
257	jal	memcpy
258	 PTR_S	v0, PCB_ONFAULT(v1)
259
260	PTR_L	v1, L_PCB(MIPS_CURLWP)
261	REG_L	ra, CALLFRAME_RA(sp)
262	PTR_ADDU sp, sp, CALLFRAME_SIZ
263	PTR_S	zero, PCB_ONFAULT(v1)
264	j	ra
265	 move	v0, zero
266END(copyout)
267
268LEAF(copyerr)
269	PTR_L	v1, L_PCB(MIPS_CURLWP)
270	REG_L	ra, CALLFRAME_RA(sp)
271	PTR_ADDU sp, sp, CALLFRAME_SIZ
272	j	ra
273	 PTR_S	zero, PCB_ONFAULT(v1)
274END(copyerr)
275
276LEAF(copyefault)
277	b	copyerr
278	 li	v0, EFAULT
279END(copyefault)
280
281/*
282 * int fuswintr(void *)
283 * Fetches a short word of data from the user-space address.
284 * This function is safe to call during an interrupt context.
285 */
286LEAF(fuswintr)
287	PTR_L	v1, L_PCB(MIPS_CURLWP)
288	PTR_LA	v0, _C_LABEL(fswintrberr)
289	PTR_L	a2, PCB_ONFAULT(v1)
290	blt	a0, zero, _C_LABEL(fswintrberr)
291	 PTR_S	v0, PCB_ONFAULT(v1)
292	lhu	v0, 0(a0)			# fetch short
293	j	ra
294	 PTR_S	a2, PCB_ONFAULT(v1)
295END(fuswintr)
296
297/*
298 * int suswintr(void *, short);
299 * Stores a short word of data to the user-space address.
300 * This function is safe to call during an interrupt context.
301 */
302LEAF(suswintr)
303	PTR_L	v1, L_PCB(MIPS_CURLWP)
304	PTR_LA	v0, _C_LABEL(fswintrberr)
305	PTR_L	a2, PCB_ONFAULT(v1)
306	blt	a0, zero, _C_LABEL(fswintrberr)
307	 PTR_S	v0, PCB_ONFAULT(v1)
308	sh	a1, 0(a0)			# store short
309	PTR_S	a2, PCB_ONFAULT(v1)
310	j	ra
311	 move	v0, zero
312END(suswintr)
313
314/*
315 * uint32_t ufetch_uint32(void *)
316 * Fetches a 32-bit datum from the user-space address.
317 */
318LEAF(ufetch_uint32)
319	PTR_L	v1, L_PCB(MIPS_CURLWP)
320	PTR_LA	v0, _C_LABEL(fswberr)
321	blt	a0, zero, _C_LABEL(fswberr)
322	 PTR_S	v0, PCB_ONFAULT(v1)
323	INT_L	v0, 0(a0)			# fetch int
324	j	ra
325	 PTR_S	zero, PCB_ONFAULT(v1)
326END(ufetch_uint32)
327STRONG_ALIAS(ufetch_int32, ufetch_uint32)
328STRONG_ALIAS(ufetch_int, ufetch_uint32)
329STRONG_ALIAS(ufetch_uint, ufetch_uint32)
330STRONG_ALIAS(ufetch_uint32_intrsafe, ufetch_uint32)
331STRONG_ALIAS(ufetch_int32_intrsafe, ufetch_uint32)
332STRONG_ALIAS(ufetch_int_intrsafe, ufetch_uint32)
333STRONG_ALIAS(ufetch_uint_intrsafe, ufetch_uint32)
334#ifndef _LP64
335STRONG_ALIAS(ufetch_ptr, ufetch_uint32)
336STRONG_ALIAS(ufetch_long, ufetch_uint32)
337STRONG_ALIAS(ufetch_ulong, ufetch_uint32)
338STRONG_ALIAS(ufetch_ptr_intrsafe, ufetch_uint32)
339STRONG_ALIAS(ufetch_long_intrsafe, ufetch_uint32)
340STRONG_ALIAS(ufetch_ulong_intrsafe, ufetch_uint32)
341STRONG_ALIAS(fuword, ufetch_uint32)
342STRONG_ALIAS(fuiword, ufetch_uint32)
343#endif
344
345#ifdef _LP64
346/*
347 * uint64_t ufetch_uint64(void *)
348 * Fetches a 64-bit datum from the user-space address.
349 */
350LEAF(ufetch_uint64)
351	PTR_L	v1, L_PCB(MIPS_CURLWP)
352	PTR_LA	v0, _C_LABEL(fswberr)
353	blt	a0, zero, _C_LABEL(fswberr)
354	 PTR_S	v0, PCB_ONFAULT(v1)
355	LONG_L	v0, 0(a0)			# fetch 64-bit datum
356	j	ra
357	 PTR_S	zero, PCB_ONFAULT(v1)
358END(ufetch_uint64)
359STRONG_ALIAS(ufetch_int64, ufetch_uint64)
360STRONG_ALIAS(ufetch_ptr, ufetch_uint64)
361STRONG_ALIAS(ufetch_long, ufetch_uint64)
362STRONG_ALIAS(ufetch_ulong, ufetch_uint64)
363STRONG_ALIAS(ufetch_int64_intrsafe, ufetch_uint64)
364STRONG_ALIAS(ufetch_ptr_intrsafe, ufetch_uint64)
365STRONG_ALIAS(ufetch_long_intrsafe, ufetch_uint64)
366STRONG_ALIAS(ufetch_ulong_intrsafe, ufetch_uint64)
367STRONG_ALIAS(fuword, ufetch_uint64)
368STRONG_ALIAS(fuiword, ufetch_uint64)
369#endif
370
371/*
372 * uint16_t ufetch_uint16(void *)
373 * Fetches an unsigned 16-bit datum from the user-space address.
374 */
375LEAF(ufetch_uint16)
376	PTR_L	v1, L_PCB(MIPS_CURLWP)
377	PTR_LA	v0, _C_LABEL(fswberr)
378	blt	a0, zero, _C_LABEL(fswberr)
379	 PTR_S	v0, PCB_ONFAULT(v1)
380	lhu	v0, 0(a0)			# fetch short
381	j	ra
382	 PTR_S	zero, PCB_ONFAULT(v1)
383END(ufetch_uint16)
384STRONG_ALIAS(ufetch_ushort, ufetch_uint16)
385STRONG_ALIAS(ufetch_uint16_intrsafe, ufetch_uint16)
386STRONG_ALIAS(ufetch_ushort_intrsafe, ufetch_uint16)
387STRONG_ALIAS(fusword, ufetch_uint16)
388STRONG_ALIAS(fuisword, ufetch_uint16)
389
390/*
391 * uint16_t ufetch_int16(void *)
392 * Fetches a signed 16-bit datum from the user-space address.
393 */
394LEAF(ufetch_int16)
395	PTR_L	v1, L_PCB(MIPS_CURLWP)
396	PTR_LA	v0, _C_LABEL(fswberr)
397	blt	a0, zero, _C_LABEL(fswberr)
398	 PTR_S	v0, PCB_ONFAULT(v1)
399	lh	v0, 0(a0)			# fetch short
400	j	ra
401	 PTR_S	zero, PCB_ONFAULT(v1)
402END(ufetch_int16)
403STRONG_ALIAS(ufetch_short, ufetch_int16)
404STRONG_ALIAS(ufetch_int16_intrsafe, ufetch_int16)
405STRONG_ALIAS(ufetch_short_intrsafe, ufetch_int16)
406
407/*
408 * uint8_t uftech_uint8(void *)
409 * Fetch a byte from the user's address space.
410 */
411LEAF(ufetch_uint8)
412	PTR_L	v1, L_PCB(MIPS_CURLWP)
413	PTR_LA	v0, _C_LABEL(fswberr)
414	blt	a0, zero, _C_LABEL(fswberr)
415	 PTR_S	v0, PCB_ONFAULT(v1)
416	lbu	v0, 0(a0)			# fetch byte
417	j	ra
418	 PTR_S	zero, PCB_ONFAULT(v1)
419END(ufetch_uint8)
420STRONG_ALIAS(ufetch_uchar, ufetch_uint8)
421STRONG_ALIAS(ufetch_uint8_intrsafe, ufetch_uint8)
422STRONG_ALIAS(ufetch_uchar_intrsafe, ufetch_uint8)
423STRONG_ALIAS(fubyte, ufetch_uint8)
424STRONG_ALIAS(fuibyte, ufetch_uint8)
425
426/*
427 * int8_t uftech_int8(void *)
428 * Fetch a byte from the user's address space.
429 */
430LEAF(ufetch_int8)
431	PTR_L	v1, L_PCB(MIPS_CURLWP)
432	PTR_LA	v0, _C_LABEL(fswberr)
433	blt	a0, zero, _C_LABEL(fswberr)
434	 PTR_S	v0, PCB_ONFAULT(v1)
435	lb	v0, 0(a0)			# fetch byte
436	j	ra
437	 PTR_S	zero, PCB_ONFAULT(v1)
438END(ufetch_int8)
439STRONG_ALIAS(ufetch_char, ufetch_int8)
440STRONG_ALIAS(ufetch_int8_intrsafe, ufetch_int8)
441STRONG_ALIAS(ufetch_char_intrsafe, ufetch_int8)
442
443/*
444 * int ustore_uint32(void *, uint32_t)
445 * Stores a 32-bit datum to the user-space address.
446 */
447LEAF(ustore_uint32)
448	PTR_L	v1, L_PCB(MIPS_CURLWP)
449	PTR_LA	v0, _C_LABEL(fswberr)
450	blt	a0, zero, _C_LABEL(fswberr)
451	 PTR_S	v0, PCB_ONFAULT(v1)
452	INT_S	a1, 0(a0)			# store word
453	PTR_S	zero, PCB_ONFAULT(v1)
454	j	ra
455	 move	v0, zero
456END(ustore_uint32)
457STRONG_ALIAS(ustore_int32, ustore_uint32)
458STRONG_ALIAS(ustore_int, ustore_uint32)
459STRONG_ALIAS(ustore_uint, ustore_uint32)
460STRONG_ALIAS(ustore_uint32_intrsafe, ustore_uint32)
461STRONG_ALIAS(ustore_int32_intrsafe, ustore_uint32)
462STRONG_ALIAS(ustore_int_intrsafe, ustore_uint32)
463STRONG_ALIAS(ustore_uint_intrsafe, ustore_uint32)
464#ifndef _LP64
465STRONG_ALIAS(ustore_ptr, ustore_uint32)
466STRONG_ALIAS(ustore_long, ustore_uint32)
467STRONG_ALIAS(ustore_ulong, ustore_uint32)
468STRONG_ALIAS(ustore_ptr_intrsafe, ustore_uint32)
469STRONG_ALIAS(ustore_long_intrsafe, ustore_uint32)
470STRONG_ALIAS(ustore_ulong_intrsafe, ustore_uint32)
471STRONG_ALIAS(suword, ustore_uint32)
472#endif
473
474/*
475 * int ustore_uint32_isync(void *, uint32_t)
476 * Have to flush instruction cache afterwards.
477 */
478LEAF(ustore_uint32_isync)
479	PTR_L	v1, L_PCB(MIPS_CURLWP)
480	PTR_LA	v0, _C_LABEL(fswberr)
481	blt	a0, zero, _C_LABEL(fswberr)
482	 PTR_S	v0, PCB_ONFAULT(v1)
483	INT_S	a1, 0(a0)			# store word
484	PTR_S	zero, PCB_ONFAULT(v1)
485	move	v0, zero
486	PTR_L	v1, _C_LABEL(mips_cache_ops) + MIPSX_FLUSHICACHE
487	j	v1				# NOTE: must not clobber v0!
488	 li	a1, 4				# size of word
489END(ustore_uint32_isync)
490
491#ifdef _LP64
492/*
493 * int ustore_uint64(void *, uint64_t)
494 * Stores a 64-bit datum to the user-space address.
495 */
496LEAF(ustore_uint64)
497	PTR_L	v1, L_PCB(MIPS_CURLWP)
498	PTR_LA	v0, _C_LABEL(fswberr)
499	blt	a0, zero, _C_LABEL(fswberr)
500	 PTR_S	v0, PCB_ONFAULT(v1)
501	LONG_S	a1, 0(a0)			# store word
502	PTR_S	zero, PCB_ONFAULT(v1)
503	j	ra
504	 move	v0, zero
505END(ustore_uint64)
506STRONG_ALIAS(ustore_int64, ustore_uint64)
507STRONG_ALIAS(ustore_int, ustore_uint64)
508STRONG_ALIAS(ustore_uint, ustore_uint64)
509STRONG_ALIAS(ustore_uint64_intrsafe, ustore_uint64)
510STRONG_ALIAS(ustore_int64_intrsafe, ustore_uint64)
511STRONG_ALIAS(ustore_int_intrsafe, ustore_uint64)
512STRONG_ALIAS(ustore_uint_intrsafe, ustore_uint64)
513STRONG_ALIAS(ustore_ptr, ustore_uint64)
514STRONG_ALIAS(ustore_long, ustore_uint64)
515STRONG_ALIAS(ustore_ulong, ustore_uint64)
516STRONG_ALIAS(ustore_long_intrsafe, ustore_uint64)
517STRONG_ALIAS(ustore_ulong_intrsafe, ustore_uint64)
518STRONG_ALIAS(suword, ustore_uint64)
519#endif
520
521/*
522 * int ustore_uint16(void *, uint16_t)
523 * Stores a short word of data to the user-space address.
524 */
525LEAF(ustore_uint16)
526	PTR_L	v1, L_PCB(MIPS_CURLWP)
527	PTR_LA	v0, _C_LABEL(fswberr)
528	blt	a0, zero, _C_LABEL(fswberr)
529	 PTR_S	v0, PCB_ONFAULT(v1)
530	sh	a1, 0(a0)			# store short
531	PTR_S	zero, PCB_ONFAULT(v1)
532	j	ra
533	 move	v0, zero
534END(ustore_uint16)
535STRONG_ALIAS(ustore_int16, ustore_uint16)
536STRONG_ALIAS(ustore_uint16_intrsafe, ustore_uint16)
537STRONG_ALIAS(ustore_int16_intrsafe, ustore_uint16)
538STRONG_ALIAS(susword, ustore_uint16)
539STRONG_ALIAS(suisword, ustore_uint16)
540
541/*
542 * int ustore_uint8(void *, uint8_t)
543 * Stores a byte of data to the user-space address.
544 */
545LEAF(ustore_uint8)
546	PTR_L	v1, L_PCB(MIPS_CURLWP)
547	PTR_LA	v0, _C_LABEL(fswberr)
548	blt	a0, zero, _C_LABEL(fswberr)
549	 PTR_S	v0, PCB_ONFAULT(v1)
550	sb	a1, 0(a0)			# store byte
551	PTR_S	zero, PCB_ONFAULT(v1)
552	j	ra
553	 move	v0, zero
554END(ustore_uint8)
555STRONG_ALIAS(ustore_int8, ustore_uint8)
556STRONG_ALIAS(ustore_uint8_intrsafe, ustore_uint8)
557STRONG_ALIAS(ustore_int8_intrsafe, ustore_uint8)
558STRONG_ALIAS(subyte, ustore_uint8)
559STRONG_ALIAS(suibyte, ustore_uint8)
560
561/*
562 * int badaddr(void addr, int len)
563 * See if access to addr with a len type instruction causes a machine check.
564 * len is length of access (1=byte, 2=short, 4=long)
565 */
566LEAF(badaddr)
567	PTR_L	v1, L_PCB(MIPS_CURLWP)
568	PTR_LA	v0, _C_LABEL(baderr)
569	bne	a1, 1, 2f
570	PTR_S	v0, PCB_ONFAULT(v1)
571	b	5f
572	 lbu	v0, (a0)
5732:
574	bne	a1, 2, 4f
575	nop
576	b	5f
577	 lhu	v0, (a0)
5784:
579	INT_L	v0, (a0)
5805:
581	PTR_S	zero, PCB_ONFAULT(v1)
582	j	ra
583	 move	v0, zero		# made it w/o errors
584END(badaddr)
585
586/*
587 * Error routine for {f,s}uswintr.  The fault handler in trap.c
588 * checks for pcb_onfault set to this fault handler and
589 * "bails out" before calling the VM fault handler.
590 * (We can not call VM code from interrupt level.)
591 */
592LEAF(fswintrberr)
593	nop
594	PTR_S	a2, PCB_ONFAULT(v1)
595	j	ra
596	 li	v0, -1
597END(fswintrberr)
598
599LEAF(fswberr)
600XLEAF(baderr)
601	PTR_S	zero, PCB_ONFAULT(v1)
602	j	ra
603	 li	v0, -1
604END(fswberr)
605