support.S revision 327195
1286441Srpaulo/*	$OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $	*/
2286441Srpaulo/*-
3286441Srpaulo * Copyright (c) 1992, 1993
4286441Srpaulo *	The Regents of the University of California.  All rights reserved.
5286441Srpaulo *
6286441Srpaulo * This code is derived from software contributed to Berkeley by
7286441Srpaulo * Digital Equipment Corporation and Ralph Campbell.
8286441Srpaulo *
9286441Srpaulo * Redistribution and use in source and binary forms, with or without
10286441Srpaulo * modification, are permitted provided that the following conditions
11286441Srpaulo * are met:
12286441Srpaulo * 1. Redistributions of source code must retain the above copyright
13286441Srpaulo *    notice, this list of conditions and the following disclaimer.
14286441Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
15286441Srpaulo *    notice, this list of conditions and the following disclaimer in the
16286441Srpaulo *    documentation and/or other materials provided with the distribution.
17286441Srpaulo * 4. Neither the name of the University nor the names of its contributors
18286441Srpaulo *    may be used to endorse or promote products derived from this software
19286441Srpaulo *    without specific prior written permission.
20286441Srpaulo *
21286441Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22286441Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23286441Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24286441Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25286441Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26286441Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27286441Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28286441Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29286441Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30286441Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31286441Srpaulo * SUCH DAMAGE.
32286441Srpaulo *
33286441Srpaulo * Copyright (C) 1989 Digital Equipment Corporation.
34286441Srpaulo * Permission to use, copy, modify, and distribute this software and
35286441Srpaulo * its documentation for any purpose and without fee is hereby granted,
36286441Srpaulo * provided that the above copyright notice appears in all copies.
37286441Srpaulo * Digital Equipment Corporation makes no representations about the
38286441Srpaulo * suitability of this software for any purpose.  It is provided "as is"
39286441Srpaulo * without express or implied warranty.
40286441Srpaulo *
41286441Srpaulo * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
42286441Srpaulo *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
43286441Srpaulo * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
44286441Srpaulo *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
45286441Srpaulo * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
46286441Srpaulo *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
47286441Srpaulo *
48286441Srpaulo *	from: @(#)locore.s	8.5 (Berkeley) 1/4/94
49286441Srpaulo *	JNPR: support.S,v 1.5.2.2 2007/08/29 10:03:49 girish
50286441Srpaulo * $FreeBSD: stable/11/sys/mips/mips/support.S 327195 2017-12-26 10:07:17Z kib $
51286441Srpaulo */
52286441Srpaulo
53286441Srpaulo/*
54286441Srpaulo * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
55286441Srpaulo * All rights reserved.
56286441Srpaulo *
57286441Srpaulo * Redistribution and use in source and binary forms, with or without
58286441Srpaulo * modification, are permitted provided that the following conditions
59286441Srpaulo * are met:
60286441Srpaulo * 1. Redistributions of source code must retain the above copyright
61286441Srpaulo *    notice, this list of conditions and the following disclaimer.
62286441Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
63286441Srpaulo *    notice, this list of conditions and the following disclaimer in the
64286441Srpaulo *    documentation and/or other materials provided with the distribution.
65286441Srpaulo * 3. All advertising materials mentioning features or use of this software
66286441Srpaulo *    must display the following acknowledgement:
67286441Srpaulo *      This product includes software developed by Jonathan R. Stone for
68286441Srpaulo *      the NetBSD Project.
69286441Srpaulo * 4. The name of the author may not be used to endorse or promote products
70286441Srpaulo *    derived from this software without specific prior written permission.
71286441Srpaulo *
72286441Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
73286441Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74286441Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75286441Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
76286441Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77286441Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78286441Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79286441Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80286441Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81286441Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82286441Srpaulo * SUCH DAMAGE.
83286441Srpaulo */
84286441Srpaulo
85286441Srpaulo/*
86286441Srpaulo *	Contains assembly language support routines.
87286441Srpaulo */
88286441Srpaulo
89286441Srpaulo#include "opt_ddb.h"
90286441Srpaulo#include <sys/errno.h>
91286441Srpaulo#include <machine/asm.h>
92286441Srpaulo#include <machine/cpu.h>
93286441Srpaulo#include <machine/regnum.h>
94286441Srpaulo#include <machine/cpuregs.h>
95286441Srpaulo#include <machine/pcb.h>
96286441Srpaulo
97286441Srpaulo#include "assym.s"
98286441Srpaulo
99286441Srpaulo	.set	noreorder		# Noreorder is default style!
100286441Srpaulo
101286441Srpaulo/*
102286441Srpaulo * Primitives
103286441Srpaulo */
104286441Srpaulo
105286441Srpaulo	.text
106286441Srpaulo
107286441Srpaulo/*
108286441Srpaulo * See if access to addr with a len type instruction causes a machine check.
109286441Srpaulo * len is length of access (1=byte, 2=short, 4=int)
110286441Srpaulo *
111286441Srpaulo * badaddr(addr, len)
112286441Srpaulo *	char *addr;
113286441Srpaulo *	int len;
114286441Srpaulo */
115286441SrpauloLEAF(badaddr)
116286441Srpaulo	PTR_LA	v0, baderr
117286441Srpaulo	GET_CPU_PCPU(v1)
118286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
119286441Srpaulo	bne	a1, 1, 2f
120286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
121286441Srpaulo	b	5f
122286441Srpaulo	lbu	v0, (a0)
123286441Srpaulo2:
124286441Srpaulo	bne	a1, 2, 4f
125286441Srpaulo	nop
126286441Srpaulo	b	5f
127286441Srpaulo	lhu	v0, (a0)
128286441Srpaulo4:
129286441Srpaulo	lw	v0, (a0)
130286441Srpaulo5:
131286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
132286441Srpaulo	j	ra
133286441Srpaulo	move	v0, zero		# made it w/o errors
134286441Srpaulobaderr:
135286441Srpaulo	j	ra
136286441Srpaulo	li	v0, 1			# trap sends us here
137286441SrpauloEND(badaddr)
138286441Srpaulo
139286441Srpaulo/*
140286441Srpaulo * int copystr(void *kfaddr, void *kdaddr, size_t maxlen, size_t *lencopied)
141286441Srpaulo * Copy a NIL-terminated string, at most maxlen characters long.  Return the
142286441Srpaulo * number of characters copied (including the NIL) in *lencopied.  If the
143286441Srpaulo * string is too long, return ENAMETOOLONG; else return 0.
144286441Srpaulo */
145286441SrpauloLEAF(copystr)
146286441Srpaulo	move		t0, a2
147286441Srpaulo	beq		a2, zero, 4f
148286441Srpaulo1:
149286441Srpaulo	lbu		v0, 0(a0)
150286441Srpaulo	PTR_SUBU	a2, a2, 1
151286475Srpaulo	beq		v0, zero, 2f
152286475Srpaulo	sb		v0, 0(a1)		# each byte until NIL
153286475Srpaulo	PTR_ADDU	a0, a0, 1
154286475Srpaulo	bne		a2, zero, 1b		# less than maxlen
155286475Srpaulo	PTR_ADDU	a1, a1, 1
156286475Srpaulo4:
157286475Srpaulo	li		v0, ENAMETOOLONG	# run out of space
158286475Srpaulo2:
159286475Srpaulo	beq		a3, zero, 3f		# return num. of copied bytes
160286475Srpaulo	PTR_SUBU	a2, t0, a2		# if the 4th arg was non-NULL
161286475Srpaulo	PTR_S		a2, 0(a3)
162286441Srpaulo3:
163286475Srpaulo	j		ra			# v0 is 0 or ENAMETOOLONG
164286441Srpaulo	nop
165286441SrpauloEND(copystr)
166286441Srpaulo
167286441Srpaulo
168286441Srpaulo/*
169298877Savos * Copy a null terminated string from the user address space into
170286441Srpaulo * the kernel address space.
171286441Srpaulo *
172286441Srpaulo *	copyinstr(fromaddr, toaddr, maxlength, &lencopied)
173286441Srpaulo *		caddr_t fromaddr;
174286441Srpaulo *		caddr_t toaddr;
175298877Savos *		u_int maxlength;
176298877Savos *		u_int *lencopied;
177298877Savos */
178286441SrpauloNESTED(copyinstr, CALLFRAME_SIZ, ra)
179286441Srpaulo	PTR_SUBU	sp, sp, CALLFRAME_SIZ
180286441Srpaulo	.mask	0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
181286441Srpaulo	PTR_LA	v0, copyerr
182286441Srpaulo	blt	a0, zero, _C_LABEL(copyerr)  # make sure address is in user space
183286441Srpaulo	REG_S	ra, CALLFRAME_RA(sp)
184286441Srpaulo	GET_CPU_PCPU(v1)
185286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
186286441Srpaulo	jal	_C_LABEL(copystr)
187286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
188286441Srpaulo	REG_L	ra, CALLFRAME_RA(sp)
189286441Srpaulo	GET_CPU_PCPU(v1)
190286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
191286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
192286441Srpaulo	j	ra
193286441Srpaulo	PTR_ADDU	sp, sp, CALLFRAME_SIZ
194286441SrpauloEND(copyinstr)
195286441Srpaulo
196286441Srpaulo/*
197286441Srpaulo * Copy a null terminated string from the kernel address space into
198286441Srpaulo * the user address space.
199286441Srpaulo *
200286441Srpaulo *	copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
201286441Srpaulo *		caddr_t fromaddr;
202286441Srpaulo *		caddr_t toaddr;
203286441Srpaulo *		u_int maxlength;
204286441Srpaulo *		u_int *lencopied;
205286441Srpaulo */
206286441SrpauloNESTED(copyoutstr, CALLFRAME_SIZ, ra)
207286441Srpaulo	PTR_SUBU	sp, sp, CALLFRAME_SIZ
208286441Srpaulo	.mask	0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
209286441Srpaulo	PTR_LA	v0, copyerr
210286441Srpaulo	blt	a1, zero, _C_LABEL(copyerr)  # make sure address is in user space
211286441Srpaulo	REG_S	ra, CALLFRAME_RA(sp)
212286441Srpaulo	GET_CPU_PCPU(v1)
213286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
214286441Srpaulo	jal	_C_LABEL(copystr)
215286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
216286441Srpaulo	REG_L	ra, CALLFRAME_RA(sp)
217286441Srpaulo	GET_CPU_PCPU(v1)
218286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
219286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
220286441Srpaulo	j	ra
221286441Srpaulo	PTR_ADDU	sp, sp, CALLFRAME_SIZ
222286441SrpauloEND(copyoutstr)
223286441Srpaulo
224286441Srpaulo/*
225286441Srpaulo * Copy specified amount of data from user space into the kernel
226286441Srpaulo *	copyin(from, to, len)
227286441Srpaulo *		caddr_t *from;	(user source address)
228286441Srpaulo *		caddr_t *to;	(kernel destination address)
229286441Srpaulo *		unsigned len;
230286441Srpaulo */
231286441SrpauloNESTED(copyin, CALLFRAME_SIZ, ra)
232286441Srpaulo	PTR_SUBU	sp, sp, CALLFRAME_SIZ
233286441Srpaulo	.mask	0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
234286441Srpaulo	PTR_LA	v0, copyerr
235286441Srpaulo	blt	a0, zero, _C_LABEL(copyerr)  # make sure address is in user space
236286441Srpaulo	REG_S	ra, CALLFRAME_RA(sp)
237286441Srpaulo	GET_CPU_PCPU(v1)
238286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
239286441Srpaulo	jal	_C_LABEL(bcopy)
240286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
241286441Srpaulo	REG_L	ra, CALLFRAME_RA(sp)
242286441Srpaulo	GET_CPU_PCPU(v1)
243286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)	 	# bcopy modified v1, so reload
244286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
245286441Srpaulo	PTR_ADDU	sp, sp, CALLFRAME_SIZ
246286441Srpaulo	j	ra
247298877Savos	move	v0, zero
248298877SavosEND(copyin)
249298877Savos
250298877Savos/*
251298877Savos * Copy specified amount of data from kernel to the user space
252298877Savos *	copyout(from, to, len)
253286441Srpaulo *		caddr_t *from;	(kernel source address)
254286441Srpaulo *		caddr_t *to;	(user destination address)
255286441Srpaulo *		unsigned len;
256286441Srpaulo */
257286441SrpauloNESTED(copyout, CALLFRAME_SIZ, ra)
258286441Srpaulo	PTR_SUBU	sp, sp, CALLFRAME_SIZ
259286441Srpaulo	.mask	0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
260286441Srpaulo	PTR_LA	v0, copyerr
261286441Srpaulo	blt	a1, zero, _C_LABEL(copyerr) # make sure address is in user space
262286441Srpaulo	REG_S	ra, CALLFRAME_RA(sp)
263286441Srpaulo	GET_CPU_PCPU(v1)
264286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
265286441Srpaulo	jal	_C_LABEL(bcopy)
266286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
267286441Srpaulo	REG_L	ra, CALLFRAME_RA(sp)
268286441Srpaulo	GET_CPU_PCPU(v1)
269286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)	 	# bcopy modified v1, so reload
270286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
271286441Srpaulo	PTR_ADDU	sp, sp, CALLFRAME_SIZ
272286441Srpaulo	j	ra
273286441Srpaulo	move	v0, zero
274286441SrpauloEND(copyout)
275286441Srpaulo
276286441SrpauloLEAF(copyerr)
277286441Srpaulo	REG_L	ra, CALLFRAME_RA(sp)
278286441Srpaulo	PTR_ADDU	sp, sp, CALLFRAME_SIZ
279286441Srpaulo	j	ra
280293100Savos	li	v0, EFAULT			# return error
281286441SrpauloEND(copyerr)
282286441Srpaulo
283286441Srpaulo/*
284286441Srpaulo * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to
285286441Srpaulo * user text space.
286286441Srpaulo * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to
287286441Srpaulo * user data space.
288286441Srpaulo */
289286441Srpaulo#ifdef __mips_n64
290286441SrpauloLEAF(fuword64)
291286441SrpauloXLEAF(fuword)
292286441Srpaulo	PTR_LA	v0, fswberr
293286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
294286441Srpaulo	nop
295286441Srpaulo	GET_CPU_PCPU(v1)
296286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
297286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
298286441Srpaulo	ld	v0, 0(a0)		# fetch word
299286441Srpaulo	j	ra
300286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
301286441SrpauloEND(fuword64)
302286441Srpaulo#endif
303286441Srpaulo
304286441SrpauloLEAF(fuword32)
305286441Srpaulo#ifndef __mips_n64
306286441SrpauloXLEAF(fuword)
307286441Srpaulo#endif
308286441Srpaulo	PTR_LA	v0, fswberr
309286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
310286441Srpaulo	nop
311286441Srpaulo	GET_CPU_PCPU(v1)
312286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
313286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
314286441Srpaulo	lw	v0, 0(a0)		# fetch word
315286441Srpaulo	j	ra
316286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
317286441SrpauloEND(fuword32)
318286441Srpaulo
319286441SrpauloLEAF(fusword)
320286441Srpaulo	PTR_LA	v0, fswberr
321286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
322287197Sglebius	nop
323287197Sglebius	GET_CPU_PCPU(v1)
324287197Sglebius	PTR_L	v1, PC_CURPCB(v1)
325286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
326287197Sglebius	lhu	v0, 0(a0)		# fetch short
327286441Srpaulo	j	ra
328286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
329286441SrpauloEND(fusword)
330286441Srpaulo
331286441SrpauloLEAF(fubyte)
332286441Srpaulo	PTR_LA	v0, fswberr
333286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
334286441Srpaulo	nop
335286441Srpaulo	GET_CPU_PCPU(v1)
336286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
337286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
338286441Srpaulo	lbu	v0, 0(a0)		# fetch byte
339286441Srpaulo	j	ra
340286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
341286441SrpauloEND(fubyte)
342286441Srpaulo
343286441SrpauloLEAF(suword32)
344286441Srpaulo#ifndef __mips_n64
345286441SrpauloXLEAF(suword)
346286441Srpaulo#endif
347286441Srpaulo	PTR_LA	v0, fswberr
348286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
349286441Srpaulo	nop
350286441Srpaulo	GET_CPU_PCPU(v1)
351286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
352286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
353286441Srpaulo	sw	a1, 0(a0)		# store word
354286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
355286441Srpaulo	j	ra
356286441Srpaulo	move	v0, zero
357286441SrpauloEND(suword32)
358286441Srpaulo
359286441Srpaulo#ifdef __mips_n64
360286441SrpauloLEAF(suword64)
361286441SrpauloXLEAF(suword)
362286441Srpaulo	PTR_LA	v0, fswberr
363286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
364286441Srpaulo	nop
365286441Srpaulo	GET_CPU_PCPU(v1)
366286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
367286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
368286441Srpaulo	sd	a1, 0(a0)		# store word
369286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
370286441Srpaulo	j	ra
371286441Srpaulo	move	v0, zero
372286441SrpauloEND(suword64)
373286441Srpaulo#endif
374286441Srpaulo
375286441Srpaulo/*
376286441Srpaulo * casuword(9)
377286441Srpaulo * <v0>u_long casuword(<a0>u_long *p, <a1>u_long oldval, <a2>u_long newval)
378286441Srpaulo */
379286441Srpaulo/*
380286441Srpaulo * casuword32(9)
381286441Srpaulo * <v0>uint32_t casuword(<a0>uint32_t *p, <a1>uint32_t oldval,
382286441Srpaulo *							<a2>uint32_t newval)
383286441Srpaulo */
384286441SrpauloLEAF(casuword32)
385286441Srpaulo#ifndef __mips_n64
386286441SrpauloXLEAF(casuword)
387286441Srpaulo#endif
388286441Srpaulo	PTR_LA	v0, fswberr
389286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
390286441Srpaulo	nop
391286441Srpaulo	GET_CPU_PCPU(v1)
392286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
393286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
394286441Srpaulo1:
395286441Srpaulo	move	t0, a2
396286441Srpaulo	ll	v0, 0(a0)
397286441Srpaulo	bne	a1, v0, 2f
398286441Srpaulo	nop
399286441Srpaulo	sc	t0, 0(a0)		# store word
400286441Srpaulo	beqz	t0, 1b
401286441Srpaulo	nop
402286441Srpaulo	j	3f
403286441Srpaulo	nop
404286441Srpaulo2:
405286441Srpaulo	li	v0, -1
406286441Srpaulo3:
407286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
408286441Srpaulo	jr	ra
409286441Srpaulo	nop
410286441SrpauloEND(casuword32)
411286441Srpaulo
412286441Srpaulo#ifdef __mips_n64
413286441SrpauloLEAF(casuword64)
414286441SrpauloXLEAF(casuword)
415286441Srpaulo	PTR_LA	v0, fswberr
416286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
417286441Srpaulo	nop
418286441Srpaulo	GET_CPU_PCPU(v1)
419286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
420286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
421286441Srpaulo1:
422286441Srpaulo	move	t0, a2
423286441Srpaulo	lld	v0, 0(a0)
424286441Srpaulo	bne	a1, v0, 2f
425286441Srpaulo	nop
426286441Srpaulo	scd	t0, 0(a0)		# store double word
427286441Srpaulo	beqz	t0, 1b
428286441Srpaulo	nop
429286441Srpaulo	j	3f
430286441Srpaulo	nop
431286441Srpaulo2:
432286441Srpaulo	li	v0, -1
433293177Savos3:
434293177Savos	PTR_S	zero, U_PCB_ONFAULT(v1)
435286441Srpaulo	jr	ra
436286441Srpaulo	nop
437286441SrpauloEND(casuword64)
438286441Srpaulo#endif
439286441Srpaulo
440286441Srpaulo/*
441286441Srpaulo * Will have to flush the instruction cache if byte merging is done in hardware.
442286441Srpaulo */
443286441SrpauloLEAF(susword)
444286441Srpaulo	PTR_LA	v0, fswberr
445286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
446286441Srpaulo	nop
447286441Srpaulo	GET_CPU_PCPU(v1)
448286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
449286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
450286441Srpaulo	sh	a1, 0(a0)		# store short
451286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
452286441Srpaulo	j	ra
453286441Srpaulo	move	v0, zero
454286441SrpauloEND(susword)
455286441Srpaulo
456286441SrpauloLEAF(subyte)
457286441Srpaulo	PTR_LA	v0, fswberr
458286441Srpaulo	blt	a0, zero, fswberr	# make sure address is in user space
459293177Savos	nop
460286441Srpaulo	GET_CPU_PCPU(v1)
461286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
462286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
463286441Srpaulo	sb	a1, 0(a0)		# store byte
464293177Savos	PTR_S	zero, U_PCB_ONFAULT(v1)
465286441Srpaulo	j	ra
466286441Srpaulo	move	v0, zero
467286441SrpauloEND(subyte)
468293177Savos
469286441SrpauloLEAF(fswberr)
470286441Srpaulo	j	ra
471286441Srpaulo	li	v0, -1
472286441SrpauloEND(fswberr)
473286441Srpaulo
474286441Srpaulo/*
475293177Savos * fuswintr and suswintr are just like fusword and susword except that if
476286441Srpaulo * the page is not in memory or would cause a trap, then we return an error.
477286441Srpaulo * The important thing is to prevent sleep() and switch().
478286441Srpaulo */
479286441SrpauloLEAF(fuswintr)
480286441Srpaulo	PTR_LA	v0, fswintrberr
481293177Savos	blt	a0, zero, fswintrberr	# make sure address is in user space
482293177Savos	nop
483286441Srpaulo	GET_CPU_PCPU(v1)
484286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
485286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
486286441Srpaulo	lhu	v0, 0(a0)		# fetch short
487286441Srpaulo	j	ra
488286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
489286441SrpauloEND(fuswintr)
490286441Srpaulo
491286441SrpauloLEAF(suswintr)
492293177Savos	PTR_LA	v0, fswintrberr
493286441Srpaulo	blt	a0, zero, fswintrberr	# make sure address is in user space
494286441Srpaulo	nop
495286441Srpaulo	GET_CPU_PCPU(v1)
496286441Srpaulo	PTR_L	v1, PC_CURPCB(v1)
497286441Srpaulo	PTR_S	v0, U_PCB_ONFAULT(v1)
498286441Srpaulo	sh	a1, 0(a0)		# store short
499286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(v1)
500286441Srpaulo	j	ra
501286441Srpaulo	move	v0, zero
502286441SrpauloEND(suswintr)
503286441Srpaulo
504286441SrpauloLEAF(fswintrberr)
505286441Srpaulo	j	ra
506286441Srpaulo	li	v0, -1
507286441SrpauloEND(fswintrberr)
508286441Srpaulo
509286441Srpaulo/*
510286441Srpaulo * memset(void *s1, int c, int len)
511286441Srpaulo * NetBSD: memset.S,v 1.3 2001/10/16 15:40:53 uch Exp
512286441Srpaulo */
513286441SrpauloLEAF(memset)
514286441Srpaulo	.set noreorder
515286441Srpaulo	blt	a2, 12, memsetsmallclr	# small amount to clear?
516286441Srpaulo	move	v0, a0			# save s1 for result
517286441Srpaulo
518286441Srpaulo	sll	t1, a1, 8		# compute  c << 8 in t1
519286441Srpaulo	or	t1, t1, a1		# compute c << 8 | c in 11
520286441Srpaulo	sll	t2, t1, 16		# shift that left 16
521286441Srpaulo	or	t1, t2, t1		# or together
522286441Srpaulo
523286441Srpaulo	PTR_SUBU	t0, zero, a0		# compute # bytes to word align address
524286441Srpaulo	and	t0, t0, 3
525286441Srpaulo	beq	t0, zero, 1f		# skip if word aligned
526286441Srpaulo	PTR_SUBU	a2, a2, t0		# subtract from remaining count
527286441Srpaulo	SWHI	t1, 0(a0)		# store 1, 2, or 3 bytes to align
528286441Srpaulo	PTR_ADDU	a0, a0, t0
529286441Srpaulo1:
530286441Srpaulo	and	v1, a2, 3		# compute number of whole words left
531286441Srpaulo	PTR_SUBU	t0, a2, v1
532286441Srpaulo	PTR_SUBU	a2, a2, t0
533286441Srpaulo	PTR_ADDU	t0, t0, a0		# compute ending address
534286441Srpaulo2:
535286441Srpaulo	PTR_ADDU	a0, a0, 4		# clear words
536286441Srpaulo	bne	a0, t0, 2b		#  unrolling loop does not help
537286441Srpaulo	sw	t1, -4(a0)		#  since we are limited by memory speed
538286441Srpaulo
539286441Srpaulomemsetsmallclr:
540286441Srpaulo	ble	a2, zero, 2f
541286441Srpaulo	PTR_ADDU	t0, a2, a0		# compute ending address
542286441Srpaulo1:
543286441Srpaulo	PTR_ADDU	a0, a0, 1		# clear bytes
544286441Srpaulo	bne	a0, t0, 1b
545286441Srpaulo	sb	a1, -1(a0)
546286441Srpaulo2:
547286441Srpaulo	j	ra
548286441Srpaulo	nop
549286441Srpaulo	.set reorder
550286441SrpauloEND(memset)
551286441Srpaulo
552286441Srpaulo/*
553286441Srpaulo * bzero(s1, n)
554286441Srpaulo */
555286441SrpauloLEAF(bzero)
556286441SrpauloXLEAF(blkclr)
557286441Srpaulo	.set	noreorder
558286441Srpaulo	blt	a1, 12, smallclr	# small amount to clear?
559286441Srpaulo	PTR_SUBU	a3, zero, a0		# compute # bytes to word align address
560286441Srpaulo	and	a3, a3, 3
561286441Srpaulo	beq	a3, zero, 1f		# skip if word aligned
562286441Srpaulo	PTR_SUBU	a1, a1, a3		# subtract from remaining count
563286441Srpaulo	SWHI	zero, 0(a0)		# clear 1, 2, or 3 bytes to align
564286441Srpaulo	PTR_ADDU	a0, a0, a3
565286441Srpaulo1:
566286441Srpaulo	and	v0, a1, 3		# compute number of words left
567286441Srpaulo	PTR_SUBU	a3, a1, v0
568286441Srpaulo	move	a1, v0
569286441Srpaulo	PTR_ADDU	a3, a3, a0		# compute ending address
570286441Srpaulo2:
571286441Srpaulo	PTR_ADDU	a0, a0, 4		# clear words
572286441Srpaulo	bne	a0, a3, 2b		#  unrolling loop does not help
573286441Srpaulo	sw	zero, -4(a0)		#  since we are limited by memory speed
574286441Srpaulosmallclr:
575286441Srpaulo	ble	a1, zero, 2f
576286441Srpaulo	PTR_ADDU	a3, a1, a0		# compute ending address
577286441Srpaulo1:
578286441Srpaulo	PTR_ADDU	a0, a0, 1		# clear bytes
579286441Srpaulo	bne	a0, a3, 1b
580286441Srpaulo	sb	zero, -1(a0)
581286441Srpaulo2:
582286441Srpaulo	j	ra
583286441Srpaulo	nop
584286441SrpauloEND(bzero)
585286441Srpaulo
586286441Srpaulo
587286441Srpaulo/*
588286441Srpaulo * bcmp(s1, s2, n)
589286441Srpaulo */
590286441SrpauloLEAF(bcmp)
591286441Srpaulo	.set	noreorder
592286441Srpaulo	blt	a2, 16, smallcmp	# is it worth any trouble?
593286441Srpaulo	xor	v0, a0, a1		# compare low two bits of addresses
594286441Srpaulo	and	v0, v0, 3
595286441Srpaulo	PTR_SUBU	a3, zero, a1		# compute # bytes to word align address
596286441Srpaulo	bne	v0, zero, unalignedcmp	# not possible to align addresses
597286441Srpaulo	and	a3, a3, 3
598286441Srpaulo
599286441Srpaulo	beq	a3, zero, 1f
600286441Srpaulo	PTR_SUBU	a2, a2, a3		# subtract from remaining count
601286441Srpaulo	move	v0, v1			# init v0,v1 so unmodified bytes match
602286441Srpaulo	LWHI	v0, 0(a0)		# read 1, 2, or 3 bytes
603286441Srpaulo	LWHI	v1, 0(a1)
604286441Srpaulo	PTR_ADDU	a1, a1, a3
605286441Srpaulo	bne	v0, v1, nomatch
606286441Srpaulo	PTR_ADDU	a0, a0, a3
607286441Srpaulo1:
608286441Srpaulo	and	a3, a2, ~3		# compute number of whole words left
609286441Srpaulo	PTR_SUBU	a2, a2, a3		#   which has to be >= (16-3) & ~3
610286441Srpaulo	PTR_ADDU	a3, a3, a0		# compute ending address
611286441Srpaulo2:
612286441Srpaulo	lw	v0, 0(a0)		# compare words
613286441Srpaulo	lw	v1, 0(a1)
614286441Srpaulo	PTR_ADDU	a0, a0, 4
615286441Srpaulo	bne	v0, v1, nomatch
616286441Srpaulo	PTR_ADDU	a1, a1, 4
617286441Srpaulo	bne	a0, a3, 2b
618286441Srpaulo	nop
619286441Srpaulo	b	smallcmp		# finish remainder
620286441Srpaulo	nop
621286441Srpaulounalignedcmp:
622286441Srpaulo	beq	a3, zero, 2f
623286441Srpaulo	PTR_SUBU	a2, a2, a3		# subtract from remaining count
624286441Srpaulo	PTR_ADDU	a3, a3, a0		# compute ending address
625286441Srpaulo1:
626286441Srpaulo	lbu	v0, 0(a0)		# compare bytes until a1 word aligned
627286441Srpaulo	lbu	v1, 0(a1)
628286441Srpaulo	PTR_ADDU	a0, a0, 1
629286441Srpaulo	bne	v0, v1, nomatch
630286441Srpaulo	PTR_ADDU	a1, a1, 1
631286441Srpaulo	bne	a0, a3, 1b
632286441Srpaulo	nop
633286441Srpaulo2:
634286441Srpaulo	and	a3, a2, ~3		# compute number of whole words left
635286441Srpaulo	PTR_SUBU	a2, a2, a3		#   which has to be >= (16-3) & ~3
636286441Srpaulo	PTR_ADDU	a3, a3, a0		# compute ending address
637286441Srpaulo3:
638286441Srpaulo	LWHI	v0, 0(a0)		# compare words a0 unaligned, a1 aligned
639286441Srpaulo	LWLO	v0, 3(a0)
640286441Srpaulo	lw	v1, 0(a1)
641286441Srpaulo	PTR_ADDU	a0, a0, 4
642286441Srpaulo	bne	v0, v1, nomatch
643286441Srpaulo	PTR_ADDU	a1, a1, 4
644286441Srpaulo	bne	a0, a3, 3b
645286441Srpaulo	nop
646286441Srpaulosmallcmp:
647286441Srpaulo	ble	a2, zero, match
648286441Srpaulo	PTR_ADDU	a3, a2, a0		# compute ending address
649286441Srpaulo1:
650286441Srpaulo	lbu	v0, 0(a0)
651286441Srpaulo	lbu	v1, 0(a1)
652286441Srpaulo	PTR_ADDU	a0, a0, 1
653286441Srpaulo	bne	v0, v1, nomatch
654286441Srpaulo	PTR_ADDU	a1, a1, 1
655286441Srpaulo	bne	a0, a3, 1b
656286441Srpaulo	nop
657286441Srpaulomatch:
658286441Srpaulo	j	ra
659286441Srpaulo	 move	v0, zero
660286441Srpaulonomatch:
661286441Srpaulo	j	ra
662286441Srpaulo	li	v0, 1
663286441SrpauloEND(bcmp)
664286441Srpaulo
665286441Srpaulo
666286441Srpaulo/*
667286441Srpaulo * bit = ffs(value)
668286441Srpaulo */
669286441SrpauloLEAF(ffs)
670286441Srpaulo	.set	noreorder
671286441Srpaulo	beq	a0, zero, 2f
672286441Srpaulo	move	v0, zero
673286441Srpaulo1:
674286441Srpaulo	and	v1, a0, 1		# bit set?
675286441Srpaulo	addu	v0, v0, 1
676286441Srpaulo	beq	v1, zero, 1b		# no, continue
677286441Srpaulo	srl	a0, a0, 1
678286441Srpaulo2:
679286441Srpaulo	j	ra
680286441Srpaulo	nop
681286441SrpauloEND(ffs)
682286441Srpaulo
683286441Srpaulo/**
684286441Srpaulo * void
685286441Srpaulo * atomic_set_16(u_int16_t *a, u_int16_t b)
686286441Srpaulo * {
687286441Srpaulo *	*a |= b;
688286441Srpaulo * }
689286441Srpaulo */
690286441SrpauloLEAF(atomic_set_16)
691293177Savos	.set	noreorder
692286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
693286441Srpaulo	sll	a0, a0, 2
694286441Srpaulo	andi	a1, a1, 0xffff
695286441Srpaulo1:
696286441Srpaulo	ll	t0, 0(a0)
697286441Srpaulo	or	t0, t0, a1
698286441Srpaulo	sc	t0, 0(a0)
699286441Srpaulo	beq	t0, zero, 1b
700286441Srpaulo	nop
701286441Srpaulo	j	ra
702286441Srpaulo	nop
703286441SrpauloEND(atomic_set_16)
704286441Srpaulo
705286441Srpaulo/**
706286441Srpaulo * void
707286441Srpaulo * atomic_clear_16(u_int16_t *a, u_int16_t b)
708286441Srpaulo * {
709286441Srpaulo *	*a &= ~b;
710286441Srpaulo * }
711286441Srpaulo */
712286441SrpauloLEAF(atomic_clear_16)
713286441Srpaulo	.set	noreorder
714286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
715286441Srpaulo	sll	a0, a0, 2
716286441Srpaulo	nor	a1, zero, a1
717286441Srpaulo1:
718286441Srpaulo	ll	t0, 0(a0)
719286441Srpaulo	move	t1, t0
720286441Srpaulo	andi	t1, t1, 0xffff	# t1 has the original lower 16 bits
721286441Srpaulo	and	t1, t1, a1	# t1 has the new lower 16 bits
722286441Srpaulo	srl	t0, t0, 16	# preserve original top 16 bits
723286441Srpaulo	sll	t0, t0, 16
724289679Skevlo	or	t0, t0, t1
725286441Srpaulo	sc	t0, 0(a0)
726286441Srpaulo	beq	t0, zero, 1b
727286441Srpaulo	nop
728286441Srpaulo	j	ra
729286441Srpaulo	nop
730286441SrpauloEND(atomic_clear_16)
731286441Srpaulo
732286441Srpaulo
733286441Srpaulo/**
734286441Srpaulo * void
735286441Srpaulo * atomic_subtract_16(uint16_t *a, uint16_t b)
736286441Srpaulo * {
737286441Srpaulo *	*a -= b;
738286441Srpaulo * }
739286441Srpaulo */
740286441SrpauloLEAF(atomic_subtract_16)
741286441Srpaulo	.set	noreorder
742286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
743286441Srpaulo	sll	a0, a0, 2
744286441Srpaulo1:
745286441Srpaulo	ll	t0, 0(a0)
746286441Srpaulo	move	t1, t0
747286441Srpaulo	andi	t1, t1, 0xffff	# t1 has the original lower 16 bits
748286441Srpaulo	subu	t1, t1, a1
749286441Srpaulo	andi	t1, t1, 0xffff	# t1 has the new lower 16 bits
750286441Srpaulo	srl	t0, t0, 16	# preserve original top 16 bits
751286441Srpaulo	sll	t0, t0, 16
752286441Srpaulo	or	t0, t0, t1
753286441Srpaulo	sc	t0, 0(a0)
754286441Srpaulo	beq	t0, zero, 1b
755286441Srpaulo	nop
756286441Srpaulo	j	ra
757286441Srpaulo	nop
758286441SrpauloEND(atomic_subtract_16)
759286441Srpaulo
760286441Srpaulo/**
761286441Srpaulo * void
762286441Srpaulo * atomic_add_16(uint16_t *a, uint16_t b)
763286441Srpaulo * {
764286441Srpaulo *	*a += b;
765286441Srpaulo * }
766286441Srpaulo */
767286441SrpauloLEAF(atomic_add_16)
768286441Srpaulo	.set	noreorder
769286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
770286441Srpaulo	sll	a0, a0, 2
771286441Srpaulo1:
772286441Srpaulo	ll	t0, 0(a0)
773286441Srpaulo	move	t1, t0
774286441Srpaulo	andi	t1, t1, 0xffff	# t1 has the original lower 16 bits
775286441Srpaulo	addu	t1, t1, a1
776286441Srpaulo	andi	t1, t1, 0xffff	# t1 has the new lower 16 bits
777286441Srpaulo	srl	t0, t0, 16	# preserve original top 16 bits
778286441Srpaulo	sll	t0, t0, 16
779286441Srpaulo	or	t0, t0, t1
780286441Srpaulo	sc	t0, 0(a0)
781286441Srpaulo	beq	t0, zero, 1b
782286441Srpaulo	nop
783286441Srpaulo	j	ra
784286441Srpaulo	nop
785286441SrpauloEND(atomic_add_16)
786286441Srpaulo
787286441Srpaulo/**
788286441Srpaulo * void
789286441Srpaulo * atomic_add_8(uint8_t *a, uint8_t b)
790286441Srpaulo * {
791286441Srpaulo *	*a += b;
792286441Srpaulo * }
793286441Srpaulo */
794286441SrpauloLEAF(atomic_add_8)
795286441Srpaulo	.set	noreorder
796286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
797286441Srpaulo	sll	a0, a0, 2
798286441Srpaulo1:
799286441Srpaulo	ll	t0, 0(a0)
800286441Srpaulo	move	t1, t0
801286441Srpaulo	andi	t1, t1, 0xff	# t1 has the original lower 8 bits
802286441Srpaulo	addu	t1, t1, a1
803286441Srpaulo	andi	t1, t1, 0xff	# t1 has the new lower 8 bits
804286441Srpaulo	srl	t0, t0, 8	# preserve original top 24 bits
805286441Srpaulo	sll	t0, t0, 8
806286441Srpaulo	or	t0, t0, t1
807286441Srpaulo	sc	t0, 0(a0)
808286441Srpaulo	beq	t0, zero, 1b
809286441Srpaulo	nop
810286441Srpaulo	j	ra
811286441Srpaulo	nop
812286441SrpauloEND(atomic_add_8)
813286441Srpaulo
814286441Srpaulo
815286441Srpaulo/**
816286441Srpaulo * void
817286441Srpaulo * atomic_subtract_8(uint8_t *a, uint8_t b)
818286441Srpaulo * {
819286441Srpaulo *	*a += b;
820286441Srpaulo * }
821286441Srpaulo */
822286441SrpauloLEAF(atomic_subtract_8)
823286441Srpaulo	.set	noreorder
824286441Srpaulo	srl	a0, a0, 2	# round down address to be 32-bit aligned
825286441Srpaulo	sll	a0, a0, 2
826286441Srpaulo1:
827286441Srpaulo	ll	t0, 0(a0)
828286441Srpaulo	move	t1, t0
829286441Srpaulo	andi	t1, t1, 0xff	# t1 has the original lower 8 bits
830286441Srpaulo	subu	t1, t1, a1
831286441Srpaulo	andi	t1, t1, 0xff	# t1 has the new lower 8 bits
832286441Srpaulo	srl	t0, t0, 8	# preserve original top 24 bits
833286441Srpaulo	sll	t0, t0, 8
834286441Srpaulo	or	t0, t0, t1
835286441Srpaulo	sc	t0, 0(a0)
836286441Srpaulo	beq	t0, zero, 1b
837286441Srpaulo	nop
838286441Srpaulo	j	ra
839286441Srpaulo	nop
840286441SrpauloEND(atomic_subtract_8)
841286441Srpaulo
842286441Srpaulo	.set	noreorder		# Noreorder is default style!
843286441Srpaulo
844286441Srpaulo#if defined(DDB) || defined(DEBUG)
845286441Srpaulo
846286441SrpauloLEAF(kdbpeek)
847286441Srpaulo	PTR_LA	v1, ddberr
848286441Srpaulo	and	v0, a0, 3			# unaligned ?
849286441Srpaulo	GET_CPU_PCPU(t1)
850286441Srpaulo	PTR_L	t1, PC_CURPCB(t1)
851286441Srpaulo	bne	v0, zero, 1f
852286441Srpaulo	PTR_S	v1, U_PCB_ONFAULT(t1)
853286441Srpaulo
854286441Srpaulo	lw	v0, (a0)
855286441Srpaulo	jr	ra
856286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
857286441Srpaulo
858289679Skevlo1:
859286441Srpaulo	LWHI	v0, 0(a0)
860286441Srpaulo	LWLO	v0, 3(a0)
861286441Srpaulo	jr	ra
862286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
863286441SrpauloEND(kdbpeek)
864286441Srpaulo
865286441SrpauloLEAF(kdbpeekd)
866286441Srpaulo	PTR_LA	v1, ddberr
867286441Srpaulo	and	v0, a0, 3			# unaligned ?
868286441Srpaulo	GET_CPU_PCPU(t1)
869286441Srpaulo	PTR_L	t1, PC_CURPCB(t1)
870286441Srpaulo	bne	v0, zero, 1f
871286441Srpaulo	PTR_S	v1, U_PCB_ONFAULT(t1)
872286441Srpaulo
873286441Srpaulo	ld	v0, (a0)
874286441Srpaulo	jr	ra
875286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
876286441Srpaulo
877286441Srpaulo1:
878286441Srpaulo	REG_LHI	v0, 0(a0)
879286441Srpaulo	REG_LLO	v0, 7(a0)
880286441Srpaulo	jr	ra
881286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
882286441SrpauloEND(kdbpeekd)
883286441Srpaulo
884286441Srpauloddberr:
885286441Srpaulo	jr	ra
886286441Srpaulo	nop
887286441Srpaulo
888286441Srpaulo#if defined(DDB)
889286441SrpauloLEAF(kdbpoke)
890287965Sadrian	PTR_LA	v1, ddberr
891286441Srpaulo	and	v0, a0, 3			# unaligned ?
892287965Sadrian	GET_CPU_PCPU(t1)
893286441Srpaulo	PTR_L	t1, PC_CURPCB(t1)
894286441Srpaulo	bne	v0, zero, 1f
895286441Srpaulo	PTR_S	v1, U_PCB_ONFAULT(t1)
896286441Srpaulo
897286441Srpaulo	sw	a1, (a0)
898286441Srpaulo	jr	ra
899286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
900286441Srpaulo
901286441Srpaulo1:
902286441Srpaulo	SWHI	a1, 0(a0)
903286441Srpaulo	SWLO	a1, 3(a0)
904286441Srpaulo	jr	ra
905286441Srpaulo	PTR_S	zero, U_PCB_ONFAULT(t1)
906286441SrpauloEND(kdbpoke)
907286441Srpaulo
908286441Srpaulo	.data
909286441Srpaulo	.globl	esym
910286441Srpauloesym:	.word	0
911286441Srpaulo
912286441Srpaulo#endif /* DDB */
913286441Srpaulo#endif /* DDB || DEBUG */
914286441Srpaulo
915286441Srpaulo	.text
916286441SrpauloLEAF(breakpoint)
917286441Srpaulo	break	MIPS_BREAK_SOVER_VAL
918286441Srpaulo	jr	ra
919286441Srpaulo	nop
920286441SrpauloEND(breakpoint)
921286441Srpaulo
922286441SrpauloLEAF(setjmp)
923286441Srpaulo	mfc0	v0, MIPS_COP_0_STATUS	# Later the "real" spl value!
924286441Srpaulo	REG_S	s0, (SZREG * PCB_REG_S0)(a0)
925286441Srpaulo	REG_S	s1, (SZREG * PCB_REG_S1)(a0)
926286441Srpaulo	REG_S	s2, (SZREG * PCB_REG_S2)(a0)
927286441Srpaulo	REG_S	s3, (SZREG * PCB_REG_S3)(a0)
928286441Srpaulo	REG_S	s4, (SZREG * PCB_REG_S4)(a0)
929286441Srpaulo	REG_S	s5, (SZREG * PCB_REG_S5)(a0)
930286441Srpaulo	REG_S	s6, (SZREG * PCB_REG_S6)(a0)
931286441Srpaulo	REG_S	s7, (SZREG * PCB_REG_S7)(a0)
932286441Srpaulo	REG_S	s8, (SZREG * PCB_REG_S8)(a0)
933286441Srpaulo	REG_S	sp, (SZREG * PCB_REG_SP)(a0)
934286441Srpaulo	REG_S	ra, (SZREG * PCB_REG_RA)(a0)
935286441Srpaulo	REG_S	v0, (SZREG * PCB_REG_SR)(a0)
936286441Srpaulo	jr	ra
937286441Srpaulo	li	v0, 0			# setjmp return
938286441SrpauloEND(setjmp)
939286441Srpaulo
940286441SrpauloLEAF(longjmp)
941286441Srpaulo	REG_L	v0, (SZREG * PCB_REG_SR)(a0)
942286441Srpaulo	REG_L	ra, (SZREG * PCB_REG_RA)(a0)
943286441Srpaulo	REG_L	s0, (SZREG * PCB_REG_S0)(a0)
944286441Srpaulo	REG_L	s1, (SZREG * PCB_REG_S1)(a0)
945286441Srpaulo	REG_L	s2, (SZREG * PCB_REG_S2)(a0)
946286441Srpaulo	REG_L	s3, (SZREG * PCB_REG_S3)(a0)
947286441Srpaulo	REG_L	s4, (SZREG * PCB_REG_S4)(a0)
948286441Srpaulo	REG_L	s5, (SZREG * PCB_REG_S5)(a0)
949286441Srpaulo	REG_L	s6, (SZREG * PCB_REG_S6)(a0)
950286441Srpaulo	REG_L	s7, (SZREG * PCB_REG_S7)(a0)
951286441Srpaulo	REG_L	s8, (SZREG * PCB_REG_S8)(a0)
952286441Srpaulo	REG_L	sp, (SZREG * PCB_REG_SP)(a0)
953286441Srpaulo	mtc0	v0, MIPS_COP_0_STATUS	# Later the "real" spl value!
954286441Srpaulo	ITLBNOPFIX
955286441Srpaulo	jr	ra
956286441Srpaulo	li	v0, 1			# longjmp return
957286441SrpauloEND(longjmp)
958286441Srpaulo
959286441SrpauloLEAF(mips3_ld)
960286441Srpaulo	.set push
961286441Srpaulo	.set noreorder
962286441Srpaulo	.set mips64
963293119Savos#if defined(__mips_o32)
964286441Srpaulo	mfc0	t0, MIPS_COP_0_STATUS		# turn off interrupts
965286441Srpaulo	and	t1, t0, ~(MIPS_SR_INT_IE)
966286441Srpaulo	mtc0	t1, MIPS_COP_0_STATUS
967286441Srpaulo	COP0_SYNC
968286441Srpaulo	nop
969286441Srpaulo	nop
970286441Srpaulo	nop
971286441Srpaulo
972286441Srpaulo	ld	v0, 0(a0)
973286441Srpaulo#if _BYTE_ORDER == _BIG_ENDIAN
974286441Srpaulo	dsll	v1, v0, 32
975286441Srpaulo	dsra	v1, v1, 32			# low word in v1
976286441Srpaulo	dsra	v0, v0, 32			# high word in v0
977286441Srpaulo#else
978286441Srpaulo	dsra	v1, v0, 32			# high word in v1
979286441Srpaulo	dsll	v0, v0, 32
980286441Srpaulo	dsra	v0, v0, 32			# low word in v0
981286441Srpaulo#endif
982286441Srpaulo
983286441Srpaulo	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
984286441Srpaulo	COP0_SYNC
985286441Srpaulo	nop
986286441Srpaulo#else /* !__mips_o32 */
987286441Srpaulo	ld	v0, 0(a0)
988286441Srpaulo#endif /* !__mips_o32 */
989286441Srpaulo
990286441Srpaulo	jr	ra
991286441Srpaulo	nop
992286441Srpaulo	.set pop
993286441SrpauloEND(mips3_ld)
994286441Srpaulo
995286441SrpauloLEAF(mips3_sd)
996286441Srpaulo	.set push
997286441Srpaulo	.set mips64
998286441Srpaulo	.set noreorder
999286441Srpaulo#if defined(__mips_o32)
1000286441Srpaulo	mfc0	t0, MIPS_COP_0_STATUS		# turn off interrupts
1001286441Srpaulo	and	t1, t0, ~(MIPS_SR_INT_IE)
1002286441Srpaulo	mtc0	t1, MIPS_COP_0_STATUS
1003286441Srpaulo	COP0_SYNC
1004286441Srpaulo	nop
1005286441Srpaulo	nop
1006286441Srpaulo	nop
1007286441Srpaulo
1008286441Srpaulo	# NOTE: a1 is padding!
1009286441Srpaulo
1010286441Srpaulo#if _BYTE_ORDER == _BIG_ENDIAN
1011286441Srpaulo	dsll	a2, a2, 32			# high word in a2
1012286441Srpaulo	dsll	a3, a3, 32			# low word in a3
1013286441Srpaulo	dsrl	a3, a3, 32
1014286441Srpaulo#else
1015286441Srpaulo	dsll	a2, a2, 32			# low word in a2
1016286441Srpaulo	dsrl	a2, a2, 32
1017286441Srpaulo	dsll	a3, a3, 32			# high word in a3
1018286441Srpaulo#endif
1019286441Srpaulo	or	a1, a2, a3
1020286441Srpaulo	sd	a1, 0(a0)
1021286441Srpaulo
1022286441Srpaulo	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
1023286441Srpaulo	COP0_SYNC
1024286441Srpaulo	nop
1025286441Srpaulo#else /* !__mips_o32 */
1026286441Srpaulo	sd	a1, 0(a0)
1027286441Srpaulo#endif /* !__mips_o32 */
1028286441Srpaulo
1029286441Srpaulo	jr	ra
1030286441Srpaulo	nop
1031286441Srpaulo	.set pop
1032286441SrpauloEND(mips3_sd)
1033286441Srpaulo