xref: /freebsd/sys/arm/arm/fusu.S (revision b00ab754)
1/*	$NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $	*/
2
3/*-
4 * Copyright (c) 1996-1998 Mark Brinicombe.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Mark Brinicombe
18 * 4. The name of the company nor the name of the author may be used to
19 *    endorse or promote products derived from this software without specific
20 *    prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * 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 */
35
36#include <machine/asm.h>
37#include <machine/armreg.h>
38#include "assym.inc"
39__FBSDID("$FreeBSD$");
40
41	.syntax	unified
42
43#if __ARM_ARCH >= 6
44#define GET_PCB(tmp) \
45	mrc p15, 0, tmp, c13, c0, 4; \
46	add	tmp, tmp, #(TD_PCB)
47#else
48.Lcurpcb:
49	.word	_C_LABEL(__pcpu) + PC_CURPCB
50#define GET_PCB(tmp) \
51	ldr	tmp, .Lcurpcb
52#endif
53
54/*
55 * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
56 *    uint32_t newval);
57 */
58
59ENTRY(casueword)
60EENTRY_NP(casueword32)
61	stmfd	sp!, {r4, r5, r6}
62
63	ldr	r4, =(VM_MAXUSER_ADDRESS-3)
64	cmp	r0, r4
65	mvncs	r0, #0
66	bcs	2f
67
68	GET_PCB(r6)
69	ldr	r6, [r6]
70
71#ifdef DIAGNOSTIC
72	teq	r6, #0x00000000
73	ldmfdeq	sp!, {r4, r5, r6}
74	beq	.Lfusupcbfault
75#endif
76
77	adr	r4, .Lcasuwordfault
78	str	r4, [r6, #PCB_ONFAULT]
79
80#if __ARM_ARCH >= 6
811:
82	ldrex	r4, [r0]
83	cmp	r4, r1
84	strexeq	r5, r3, [r0]
85	cmpeq	r5, #1
86	beq	1b
87#else
88	ldrt	r4, [r0]
89	cmp	r4, r1
90	strteq	r3, [r0]
91#endif
92	str	r4, [r2]
93	mov	r0, #0
94	str	r0, [r6, #PCB_ONFAULT]
952:
96	ldmfd	sp!, {r4, r5, r6}
97	RET
98EEND(casueword32)
99END(casueword)
100
101/*
102 * Handle faults from casuword.  Clean up and return -1.
103 */
104
105.Lcasuwordfault:
106	mov	r0, #0x00000000
107	str	r0, [r6, #PCB_ONFAULT]
108	mvn	r0, #0
109	ldmfd	sp!, {r4, r5, r6}
110	RET
111
112/*
113 * fueword(caddr_t uaddr, long *val);
114 * Fetch an int from the user's address space.
115 */
116
117ENTRY(fueword)
118EENTRY_NP(fueword32)
119	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
120	cmp	r0, r3
121	mvncs	r0, #0
122	RETc(cs)
123
124	GET_PCB(r2)
125	ldr	r2, [r2]
126
127#ifdef DIAGNOSTIC
128	teq	r2, #0x00000000
129	beq	.Lfusupcbfault
130#endif
131
132	adr	r3, .Lfusufault
133	str	r3, [r2, #PCB_ONFAULT]
134
135	ldrt	r3, [r0]
136	str	r3, [r1]
137
138	mov	r0, #0x00000000
139	str	r0, [r2, #PCB_ONFAULT]
140	RET
141EEND(fueword32)
142END(fueword)
143
144/*
145 * fusword(caddr_t uaddr);
146 * Fetch a short from the user's address space.
147 */
148
149ENTRY(fusword)
150	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
151	cmp	r0, r3
152	mvncs	r0, #0
153	RETc(cs)
154
155	GET_PCB(r2)
156	ldr	r2, [r2]
157
158#ifdef DIAGNOSTIC
159	teq	r2, #0x00000000
160	beq	.Lfusupcbfault
161#endif
162
163	adr	r1, .Lfusufault
164	str	r1, [r2, #PCB_ONFAULT]
165
166	ldrbt	r3, [r0], #1
167	ldrbt	ip, [r0]
168#ifdef __ARMEB__
169	orr	r0, ip, r3, asl #8
170#else
171	orr	r0, r3, ip, asl #8
172#endif
173	mov	r1, #0x00000000
174	str	r1, [r2, #PCB_ONFAULT]
175	RET
176END(fusword)
177
178/*
179 * fubyte(caddr_t uaddr);
180 * Fetch a byte from the user's address space.
181 */
182
183ENTRY(fubyte)
184	ldr	r3, =VM_MAXUSER_ADDRESS
185	cmp	r0, r3
186	mvncs	r0, #0
187	RETc(cs)
188
189	GET_PCB(r2)
190	ldr	r2, [r2]
191
192#ifdef DIAGNOSTIC
193	teq	r2, #0x00000000
194	beq	.Lfusupcbfault
195#endif
196
197	adr	r1, .Lfusufault
198	str	r1, [r2, #PCB_ONFAULT]
199
200	ldrbt	r3, [r0]
201
202	mov	r1, #0x00000000
203	str	r1, [r2, #PCB_ONFAULT]
204	mov	r0, r3
205	RET
206END(fubyte)
207
208/*
209 * Handle faults from [fs]u*().  Clean up and return -1.
210 */
211
212.Lfusufault:
213	mov	r0, #0x00000000
214	str	r0, [r2, #PCB_ONFAULT]
215	mvn	r0, #0x00000000
216	RET
217
218#ifdef DIAGNOSTIC
219/*
220 * Handle earlier faults from [fs]u*(), due to no pcb
221 */
222
223.Lfusupcbfault:
224	mov	r1, r0
225	adr	r0, fusupcbfaulttext
226	b	_C_LABEL(panic)
227
228fusupcbfaulttext:
229	.asciz	"Yikes - no valid PCB during fusuxxx() addr=%08x\n"
230	.align	2
231#endif
232
233/*
234 * suword(caddr_t uaddr, int x);
235 * Store an int in the user's address space.
236 */
237
238ENTRY(suword)
239EENTRY_NP(suword32)
240	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
241	cmp	r0, r3
242	mvncs	r0, #0
243	RETc(cs)
244
245	GET_PCB(r2)
246	ldr	r2, [r2]
247
248#ifdef DIAGNOSTIC
249	teq	r2, #0x00000000
250	beq	.Lfusupcbfault
251#endif
252
253	adr	r3, .Lfusufault
254	str	r3, [r2, #PCB_ONFAULT]
255
256	strt	r1, [r0]
257
258	mov	r0, #0x00000000
259	str	r0, [r2, #PCB_ONFAULT]
260	RET
261EEND(suword32)
262END(suword)
263
264/*
265 * susword(caddr_t uaddr, short x);
266 * Store a short in the user's address space.
267 */
268
269ENTRY(susword)
270	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
271	cmp	r0, r3
272	mvncs	r0, #0
273	RETc(cs)
274
275	GET_PCB(r2)
276	ldr	r2, [r2]
277
278#ifdef DIAGNOSTIC
279	teq	r2, #0x00000000
280	beq	.Lfusupcbfault
281#endif
282
283	adr	r3, .Lfusufault
284	str	r3, [r2, #PCB_ONFAULT]
285
286#ifdef __ARMEB__
287	mov	ip, r1, lsr #8
288	strbt	ip, [r0], #1
289#else
290	strbt	r1, [r0], #1
291	mov	r1, r1, lsr #8
292#endif
293	strbt	r1, [r0]
294
295	mov	r0, #0x00000000
296	str	r0, [r2, #PCB_ONFAULT]
297	RET
298END(susword)
299
300/*
301 * subyte(caddr_t uaddr, char x);
302 * Store a byte in the user's address space.
303 */
304
305ENTRY(subyte)
306	ldr	r3, =VM_MAXUSER_ADDRESS
307	cmp	r0, r3
308	mvncs	r0, #0
309	RETc(cs)
310
311	GET_PCB(r2)
312	ldr	r2, [r2]
313
314
315#ifdef DIAGNOSTIC
316	teq	r2, #0x00000000
317	beq	.Lfusupcbfault
318#endif
319
320	adr	r3, .Lfusufault
321	str	r3, [r2, #PCB_ONFAULT]
322
323	strbt	r1, [r0]
324	mov	r0, #0x00000000
325	str	r0, [r2, #PCB_ONFAULT]
326	RET
327END(subyte)
328