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