fusu.S revision 266311
1231990Smp/*	$NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $	*/
259243Sobrien
359243Sobrien/*-
459243Sobrien * Copyright (c) 1996-1998 Mark Brinicombe.
559243Sobrien * All rights reserved.
659243Sobrien *
759243Sobrien * Redistribution and use in source and binary forms, with or without
859243Sobrien * modification, are permitted provided that the following conditions
959243Sobrien * are met:
1059243Sobrien * 1. Redistributions of source code must retain the above copyright
1159243Sobrien *    notice, this list of conditions and the following disclaimer.
1259243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer in the
1459243Sobrien *    documentation and/or other materials provided with the distribution.
1559243Sobrien * 3. All advertising materials mentioning features or use of this software
1659243Sobrien *    must display the following acknowledgement:
17100616Smp *	This product includes software developed by Mark Brinicombe
1859243Sobrien * 4. The name of the company nor the name of the author may be used to
1959243Sobrien *    endorse or promote products derived from this software without specific
2059243Sobrien *    prior written permission.
2159243Sobrien *
2259243Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
2359243Sobrien * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2459243Sobrien * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2559243Sobrien * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2659243Sobrien * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2759243Sobrien * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2859243Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2959243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3059243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3159243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3259243Sobrien * SUCH DAMAGE.
3359243Sobrien *
3459243Sobrien */
3559243Sobrien
3659243Sobrien#include <machine/asm.h>
3759243Sobrien#include <machine/armreg.h>
3859243Sobrien#include "assym.s"
3959243Sobrien__FBSDID("$FreeBSD: stable/10/sys/arm/arm/fusu.S 266311 2014-05-17 13:53:38Z ian $");
4059243Sobrien
4159243Sobrien#ifdef _ARM_ARCH_6
42231990Smp#define GET_PCB(tmp) \
4359243Sobrien	mrc p15, 0, tmp, c13, c0, 4; \
4459243Sobrien	add	tmp, tmp, #(TD_PCB)
4559243Sobrien#else
4659243Sobrien.Lcurpcb:
4759243Sobrien	.word	_C_LABEL(__pcpu) + PC_CURPCB
48145479Smp#define GET_PCB(tmp) \
49145479Smp	ldr	tmp, .Lcurpcb
5059243Sobrien#endif
5159243Sobrien
5259243Sobrien/*
5359243Sobrien * fuword(caddr_t uaddr);
5459243Sobrien * Fetch an int from the user's address space.
5559243Sobrien */
5659243Sobrien
5759243SobrienENTRY_NP(casuword32)
5859243SobrienENTRY(casuword)
5959243Sobrien	GET_PCB(r3)
6059243Sobrien	ldr	r3, [r3]
6159243Sobrien
6259243Sobrien#ifdef DIAGNOSTIC
6359243Sobrien	teq	r3, #0x00000000
6459243Sobrien	beq	.Lfusupcbfault
6559243Sobrien#endif
6659243Sobrien	stmfd	sp!, {r4, r5}
6759243Sobrien	adr	r4, .Lcasuwordfault
6859243Sobrien	str	r4, [r3, #PCB_ONFAULT]
6959243Sobrien	ldrt	r5, [r0]
7059243Sobrien	cmp	r5, r1
7159243Sobrien	movne	r0, r5
7259243Sobrien	streqt	r2, [r0]
7359243Sobrien	moveq	r0, r1
7459243Sobrien	ldmfd	sp!, {r4, r5}
7559243Sobrien	mov	r1, #0x00000000
7659243Sobrien	str	r1, [r3, #PCB_ONFAULT]
7759243Sobrien	RET
7859243SobrienEND(casuword32)
7959243SobrienEND(casuword)
8059243Sobrien
81231990Smp/*
8259243Sobrien * Handle faults from casuword.  Clean up and return -1.
8359243Sobrien */
8459243Sobrien
85167465Smp.Lcasuwordfault:
86167465Smp	mov	r0, #0x00000000
8759243Sobrien	str	r0, [r3, #PCB_ONFAULT]
8859243Sobrien	mvn	r0, #0x00000000
8959243Sobrien	ldmfd	sp!, {r4, r5}
9059243Sobrien	RET
9159243Sobrien
9259243Sobrien/*
93145479Smp * fuword(caddr_t uaddr);
9459243Sobrien * Fetch an int from the user's address space.
9559243Sobrien */
9659243Sobrien
9759243SobrienENTRY_NP(fuword32)
9859243SobrienENTRY(fuword)
9959243Sobrien	GET_PCB(r2)
10059243Sobrien	ldr	r2, [r2]
10159243Sobrien
10259243Sobrien#ifdef DIAGNOSTIC
103167465Smp	teq	r2, #0x00000000
104145479Smp	beq	.Lfusupcbfault
105145479Smp#endif
106145479Smp
107145479Smp	adr	r1, .Lfusufault
10859243Sobrien	str	r1, [r2, #PCB_ONFAULT]
10959243Sobrien
110145479Smp	ldrt	r3, [r0]
11159243Sobrien
11269408Sache	mov	r1, #0x00000000
11359243Sobrien	str	r1, [r2, #PCB_ONFAULT]
11459243Sobrien	mov	r0, r3
11559243Sobrien	RET
11659243SobrienEND(fuword32)
11759243SobrienEND(fuword)
11859243Sobrien
11959243Sobrien/*
12059243Sobrien * fusword(caddr_t uaddr);
12159243Sobrien * Fetch a short from the user's address space.
12259243Sobrien */
123100616Smp
12459243SobrienENTRY(fusword)
125100616Smp	GET_PCB(r2)
126100616Smp	ldr	r2, [r2]
12759243Sobrien
12859243Sobrien#ifdef DIAGNOSTIC
12959243Sobrien	teq	r2, #0x00000000
13059243Sobrien	beq	.Lfusupcbfault
13159243Sobrien#endif
13259243Sobrien
13359243Sobrien	adr	r1, .Lfusufault
13459243Sobrien	str	r1, [r2, #PCB_ONFAULT]
13559243Sobrien
136145479Smp	ldrbt	r3, [r0], #1
13759243Sobrien	ldrbt	ip, [r0]
138167465Smp#ifdef __ARMEB__
13959243Sobrien	orr	r0, ip, r3, asl #8
140145479Smp#else
14159243Sobrien	orr	r0, r3, ip, asl #8
142195609Smp#endif
14359243Sobrien	mov	r1, #0x00000000
14459243Sobrien	str	r1, [r2, #PCB_ONFAULT]
145167465Smp	RET
14683098SmpEND(fusword)
147167465Smp
14883098Smp/*
149167465Smp * fuswintr(caddr_t uaddr);
15083098Smp * Fetch a short from the user's address space.  Can be called during an
151167465Smp * interrupt.
152167465Smp */
15359243Sobrien
154167465SmpENTRY(fuswintr)
15559243Sobrien	ldr	r2, Lblock_userspace_access
156167465Smp	ldr	r2, [r2]
157167465Smp	teq	r2, #0
158167465Smp	mvnne	r0, #0x00000000
159167465Smp	RETne
16059243Sobrien
161167465Smp	GET_PCB(r2)
16259243Sobrien	ldr	r2, [r2]
163231990Smp
164231990Smp#ifdef DIAGNOSTIC
165231990Smp	teq	r2, #0x00000000
166231990Smp	beq	.Lfusupcbfault
167231990Smp#endif
168231990Smp
169231990Smp	adr	r1, _C_LABEL(fusubailout)
170231990Smp	str	r1, [r2, #PCB_ONFAULT]
171231990Smp
172231990Smp	ldrbt	r3, [r0], #1
173231990Smp	ldrbt	ip, [r0]
174231990Smp#ifdef __ARMEB__
175231990Smp	orr	r0, ip, r3, asl #8
176231990Smp#else
177231990Smp	orr	r0, r3, ip, asl #8
178231990Smp#endif
179231990Smp
180231990Smp	mov	r1, #0x00000000
181231990Smp	str	r1, [r2, #PCB_ONFAULT]
182231990Smp	RET
183231990SmpEND(fuswintr)
184231990Smp
185231990SmpLblock_userspace_access:
186231990Smp	.word	_C_LABEL(block_userspace_access)
187231990Smp
188231990Smp	.data
189231990Smp	.align	0
190231990Smp	.global	_C_LABEL(block_userspace_access)
191231990Smp_C_LABEL(block_userspace_access):
192231990Smp	.word	0
193231990Smp	.text
194231990Smp
195231990Smp/*
196231990Smp * fubyte(caddr_t uaddr);
197231990Smp * Fetch a byte from the user's address space.
198231990Smp */
199231990Smp
200231990SmpENTRY(fubyte)
201231990Smp	GET_PCB(r2)
202231990Smp	ldr	r2, [r2]
203231990Smp
204231990Smp#ifdef DIAGNOSTIC
205231990Smp	teq	r2, #0x00000000
206231990Smp	beq	.Lfusupcbfault
207231990Smp#endif
208231990Smp
209231990Smp	adr	r1, .Lfusufault
210231990Smp	str	r1, [r2, #PCB_ONFAULT]
211231990Smp
212231990Smp	ldrbt	r3, [r0]
213231990Smp
214231990Smp	mov	r1, #0x00000000
215231990Smp	str	r1, [r2, #PCB_ONFAULT]
216231990Smp	mov	r0, r3
217231990Smp	RET
218231990SmpEND(fubyte)
219231990Smp
220231990Smp/*
221231990Smp * Handle faults from [fs]u*().  Clean up and return -1.
222231990Smp */
223231990Smp
224231990Smp.Lfusufault:
225231990Smp	mov	r0, #0x00000000
226231990Smp	str	r0, [r2, #PCB_ONFAULT]
227231990Smp	mvn	r0, #0x00000000
228231990Smp	RET
229231990Smp
230231990Smp/*
231231990Smp * Handle faults from [fs]u*().  Clean up and return -1.  This differs from
232231990Smp * fusufault() in that trap() will recognise it and return immediately rather
233231990Smp * than trying to page fault.
23459243Sobrien */
235167465Smp
23659243Sobrien/* label must be global as fault.c references it */
237167465Smp	.global	_C_LABEL(fusubailout)
238167465Smp_C_LABEL(fusubailout):
239167465Smp	mov	r0, #0x00000000
240167465Smp	str	r0, [r2, #PCB_ONFAULT]
241167465Smp	mvn	r0, #0x00000000
242167465Smp	RET
243145479Smp
24459243Sobrien#ifdef DIAGNOSTIC
245145479Smp/*
24659243Sobrien * Handle earlier faults from [fs]u*(), due to no pcb
247145479Smp */
248167465Smp
249145479Smp.Lfusupcbfault:
250131962Smp	mov	r1, r0
251167465Smp	adr	r0, fusupcbfaulttext
25259243Sobrien	b	_C_LABEL(panic)
253231990Smp
25469408Sachefusupcbfaulttext:
25559243Sobrien	.asciz	"Yikes - no valid PCB during fusuxxx() addr=%08x\n"
25669408Sache	.align	0
25759243Sobrien#endif
25859243Sobrien
25959243Sobrien/*
26059243Sobrien * suword(caddr_t uaddr, int x);
26159243Sobrien * Store an int in the user's address space.
26259243Sobrien */
26359243Sobrien
26459243SobrienENTRY_NP(suword32)
26559243SobrienENTRY(suword)
26659243Sobrien	GET_PCB(r2)
267231990Smp	ldr	r2, [r2]
268231990Smp
269231990Smp#ifdef DIAGNOSTIC
270231990Smp	teq	r2, #0x00000000
271231990Smp	beq	.Lfusupcbfault
272231990Smp#endif
273231990Smp
27459243Sobrien	adr	r3, .Lfusufault
27559243Sobrien	str	r3, [r2, #PCB_ONFAULT]
27659243Sobrien
277167465Smp	strt	r1, [r0]
278145479Smp
279145479Smp	mov	r0, #0x00000000
28059243Sobrien	str	r0, [r2, #PCB_ONFAULT]
28159243Sobrien	RET
28259243SobrienEND(suword32)
28359243SobrienEND(suword)
28459243Sobrien
28559243Sobrien/*
28659243Sobrien * suswintr(caddr_t uaddr, short x);
28759243Sobrien * Store a short in the user's address space.  Can be called during an
28859243Sobrien * interrupt.
28959243Sobrien */
29059243Sobrien
29159243SobrienENTRY(suswintr)
29259243Sobrien	ldr	r2, Lblock_userspace_access
29359243Sobrien	ldr	r2, [r2]
29459243Sobrien	teq	r2, #0
29559243Sobrien	mvnne	r0, #0x00000000
29659243Sobrien	RETne
29759243Sobrien
29859243Sobrien	GET_PCB(r2)
29959243Sobrien	ldr	r2, [r2]
30059243Sobrien
30159243Sobrien#ifdef DIAGNOSTIC
30259243Sobrien	teq	r2, #0x00000000
30359243Sobrien	beq	.Lfusupcbfault
30459243Sobrien#endif
305167465Smp
306167465Smp	adr	r3, _C_LABEL(fusubailout)
30759243Sobrien	str	r3, [r2, #PCB_ONFAULT]
30859243Sobrien
309167465Smp#ifdef __ARMEB__
31059243Sobrien	mov	ip, r1, lsr #8
31159243Sobrien	strbt	ip, [r0], #1
31259243Sobrien#else
31359243Sobrien	strbt	r1, [r0], #1
31459243Sobrien	mov	r1, r1, lsr #8
31559243Sobrien#endif
31659243Sobrien	strbt	r1, [r0]
31759243Sobrien
31859243Sobrien	mov	r0, #0x00000000
31969408Sache	str	r0, [r2, #PCB_ONFAULT]
32059243Sobrien	RET
32159243SobrienEND(suswintr)
32259243Sobrien
32359243Sobrien/*
32459243Sobrien * susword(caddr_t uaddr, short x);
32569408Sache * Store a short in the user's address space.
32659243Sobrien */
32759243Sobrien
32859243SobrienENTRY(susword)
329231990Smp	GET_PCB(r2)
33059243Sobrien	ldr	r2, [r2]
33159243Sobrien
33259243Sobrien#ifdef DIAGNOSTIC
33359243Sobrien	teq	r2, #0x00000000
33459243Sobrien	beq	.Lfusupcbfault
33559243Sobrien#endif
33659243Sobrien
33759243Sobrien	adr	r3, .Lfusufault
33859243Sobrien	str	r3, [r2, #PCB_ONFAULT]
33959243Sobrien
34059243Sobrien#ifdef __ARMEB__
34159243Sobrien	mov	ip, r1, lsr #8
34259243Sobrien	strbt	ip, [r0], #1
34359243Sobrien#else
34459243Sobrien	strbt	r1, [r0], #1
34559243Sobrien	mov	r1, r1, lsr #8
34659243Sobrien#endif
34759243Sobrien	strbt	r1, [r0]
34859243Sobrien
349231990Smp	mov	r0, #0x00000000
350231990Smp	str	r0, [r2, #PCB_ONFAULT]
35159243Sobrien	RET
35259243SobrienEND(susword)
353231990Smp
354231990Smp/*
35559243Sobrien * subyte(caddr_t uaddr, char x);
35659243Sobrien * Store a byte in the user's address space.
357167465Smp */
35859243Sobrien
35959243SobrienENTRY(subyte)
36059243Sobrien	GET_PCB(r2)
36159243Sobrien	ldr	r2, [r2]
36259243Sobrien
36359243Sobrien
36459243Sobrien#ifdef DIAGNOSTIC
36559243Sobrien	teq	r2, #0x00000000
36659243Sobrien	beq	.Lfusupcbfault
36759243Sobrien#endif
36859243Sobrien
36959243Sobrien	adr	r3, .Lfusufault
37059243Sobrien	str	r3, [r2, #PCB_ONFAULT]
37159243Sobrien
37259243Sobrien	strbt	r1, [r0]
37359243Sobrien	mov	r0, #0x00000000
37459243Sobrien	str	r0, [r2, #PCB_ONFAULT]
37559243Sobrien	RET
37659243SobrienEND(subyte)
37759243Sobrien
37859243Sobrien