xref: /freebsd/sys/arm/arm/fusu.S (revision 61e21613)
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	.syntax	unified
40
41#define GET_PCB(tmp) \
42	mrc p15, 0, tmp, c13, c0, 4; \
43	add	tmp, tmp, #(TD_PCB)
44
45/*
46 * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
47 *    uint32_t newval);
48 */
49
50ENTRY(casueword)
51EENTRY_NP(casueword32)
52	stmfd	sp!, {r4, r5, r6}
53
54	ldr	r4, =(VM_MAXUSER_ADDRESS-3)
55	cmp	r0, r4
56	mvncs	r0, #0
57	bcs	1f
58
59	GET_PCB(r6)
60	ldr	r6, [r6]
61
62#ifdef DIAGNOSTIC
63	teq	r6, #0x00000000
64	ldmfdeq	sp!, {r4, r5, r6}
65	beq	.Lfusupcbfault
66#endif
67
68	adr	r4, .Lcasuwordfault
69	str	r4, [r6, #PCB_ONFAULT]
70
71	mov	r5, #1
72	ldrex	r4, [r0]
73	cmp	r4, r1
74	strexeq	r5, r3, [r0]
75	str	r4, [r2]
76	mov	r0, #0
77	str	r0, [r6, #PCB_ONFAULT]
78	mov	r0, r5
791:
80	ldmfd	sp!, {r4, r5, r6}
81	RET
82EEND(casueword32)
83END(casueword)
84
85/*
86 * Handle faults from casuword.  Clean up and return -1.
87 */
88
89.Lcasuwordfault:
90	mov	r0, #0x00000000
91	str	r0, [r6, #PCB_ONFAULT]
92	mvn	r0, #0
93	ldmfd	sp!, {r4, r5, r6}
94	RET
95
96/*
97 * fueword(caddr_t uaddr, long *val);
98 * Fetch an int from the user's address space.
99 */
100
101ENTRY(fueword)
102EENTRY_NP(fueword32)
103	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
104	cmp	r0, r3
105	mvncs	r0, #0
106	RETc(cs)
107
108	GET_PCB(r2)
109	ldr	r2, [r2]
110
111#ifdef DIAGNOSTIC
112	teq	r2, #0x00000000
113	beq	.Lfusupcbfault
114#endif
115
116	adr	r3, .Lfusufault
117	str	r3, [r2, #PCB_ONFAULT]
118
119	ldrt	r3, [r0]
120	str	r3, [r1]
121
122	mov	r0, #0x00000000
123	str	r0, [r2, #PCB_ONFAULT]
124	RET
125EEND(fueword32)
126END(fueword)
127
128/*
129 * fusword(caddr_t uaddr);
130 * Fetch a short from the user's address space.
131 */
132
133ENTRY(fusword)
134	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
135	cmp	r0, r3
136	mvncs	r0, #0
137	RETc(cs)
138
139	GET_PCB(r2)
140	ldr	r2, [r2]
141
142#ifdef DIAGNOSTIC
143	teq	r2, #0x00000000
144	beq	.Lfusupcbfault
145#endif
146
147	adr	r1, .Lfusufault
148	str	r1, [r2, #PCB_ONFAULT]
149
150	ldrbt	r3, [r0], #1
151	ldrbt	ip, [r0]
152	orr	r0, r3, ip, asl #8
153	mov	r1, #0x00000000
154	str	r1, [r2, #PCB_ONFAULT]
155	RET
156END(fusword)
157
158/*
159 * fubyte(caddr_t uaddr);
160 * Fetch a byte from the user's address space.
161 */
162
163ENTRY(fubyte)
164	ldr	r3, =VM_MAXUSER_ADDRESS
165	cmp	r0, r3
166	mvncs	r0, #0
167	RETc(cs)
168
169	GET_PCB(r2)
170	ldr	r2, [r2]
171
172#ifdef DIAGNOSTIC
173	teq	r2, #0x00000000
174	beq	.Lfusupcbfault
175#endif
176
177	adr	r1, .Lfusufault
178	str	r1, [r2, #PCB_ONFAULT]
179
180	ldrbt	r3, [r0]
181
182	mov	r1, #0x00000000
183	str	r1, [r2, #PCB_ONFAULT]
184	mov	r0, r3
185	RET
186END(fubyte)
187
188/*
189 * Handle faults from [fs]u*().  Clean up and return -1.
190 */
191
192.Lfusufault:
193	mov	r0, #0x00000000
194	str	r0, [r2, #PCB_ONFAULT]
195	mvn	r0, #0x00000000
196	RET
197
198#ifdef DIAGNOSTIC
199/*
200 * Handle earlier faults from [fs]u*(), due to no pcb
201 */
202
203.Lfusupcbfault:
204	mov	r1, r0
205	adr	r0, fusupcbfaulttext
206	b	_C_LABEL(panic)
207
208fusupcbfaulttext:
209	.asciz	"Yikes - no valid PCB during fusuxxx() addr=%08x\n"
210	.align	2
211#endif
212
213/*
214 * suword16(caddr_t uaddr, int x);
215 * Store an uint16_t in the user's address space.
216 */
217
218ENTRY(suword16)
219	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
220	cmp	r0, r3
221	mvncs	r0, #0
222	RETc(cs)
223
224	GET_PCB(r2)
225	ldr	r2, [r2]
226
227#ifdef DIAGNOSTIC
228	teq	r2, #0x00000000
229	beq	.Lfusupcbfault
230#endif
231
232	adr	r3, .Lfusufault
233	str	r3, [r2, #PCB_ONFAULT]
234
235	strht	r1, [r0], #0
236
237	mov	r0, #0x00000000
238	str	r0, [r2, #PCB_ONFAULT]
239	RET
240END(suword16)
241
242/*
243 * suword(caddr_t uaddr, int x);
244 * Store an int in the user's address space.
245 */
246
247ENTRY(suword)
248EENTRY_NP(suword32)
249	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
250	cmp	r0, r3
251	mvncs	r0, #0
252	RETc(cs)
253
254	GET_PCB(r2)
255	ldr	r2, [r2]
256
257#ifdef DIAGNOSTIC
258	teq	r2, #0x00000000
259	beq	.Lfusupcbfault
260#endif
261
262	adr	r3, .Lfusufault
263	str	r3, [r2, #PCB_ONFAULT]
264
265	strt	r1, [r0]
266
267	mov	r0, #0x00000000
268	str	r0, [r2, #PCB_ONFAULT]
269	RET
270EEND(suword32)
271END(suword)
272
273/*
274 * susword(caddr_t uaddr, short x);
275 * Store a short in the user's address space.
276 */
277
278ENTRY(susword)
279	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
280	cmp	r0, r3
281	mvncs	r0, #0
282	RETc(cs)
283
284	GET_PCB(r2)
285	ldr	r2, [r2]
286
287#ifdef DIAGNOSTIC
288	teq	r2, #0x00000000
289	beq	.Lfusupcbfault
290#endif
291
292	adr	r3, .Lfusufault
293	str	r3, [r2, #PCB_ONFAULT]
294
295	strbt	r1, [r0], #1
296	mov	r1, r1, lsr #8
297	strbt	r1, [r0]
298
299	mov	r0, #0x00000000
300	str	r0, [r2, #PCB_ONFAULT]
301	RET
302END(susword)
303
304/*
305 * subyte(caddr_t uaddr, char x);
306 * Store a byte in the user's address space.
307 */
308
309ENTRY(subyte)
310	ldr	r3, =VM_MAXUSER_ADDRESS
311	cmp	r0, r3
312	mvncs	r0, #0
313	RETc(cs)
314
315	GET_PCB(r2)
316	ldr	r2, [r2]
317
318
319#ifdef DIAGNOSTIC
320	teq	r2, #0x00000000
321	beq	.Lfusupcbfault
322#endif
323
324	adr	r3, .Lfusufault
325	str	r3, [r2, #PCB_ONFAULT]
326
327	strbt	r1, [r0]
328	mov	r0, #0x00000000
329	str	r0, [r2, #PCB_ONFAULT]
330	RET
331END(subyte)
332