]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/fusu.S
Merge OpenSSL 1.0.2o.
[FreeBSD/FreeBSD.git] / sys / arm / arm / fusu.S
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
59 ENTRY(casueword)
60 EENTRY_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
81 1:
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]
95 2:
96         ldmfd   sp!, {r4, r5, r6}
97         RET
98 EEND(casueword32)
99 END(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
117 ENTRY(fueword)
118 EENTRY_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
141 EEND(fueword32)
142 END(fueword)
143
144 /*
145  * fusword(caddr_t uaddr);
146  * Fetch a short from the user's address space.
147  */
148
149 ENTRY(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
176 END(fusword)
177
178 /*
179  * fuswintr(caddr_t uaddr);
180  * Fetch a short from the user's address space.  Can be called during an
181  * interrupt.
182  */
183
184 ENTRY(fuswintr)
185         mov     r0, #-1
186         RET
187 END(fuswintr)
188
189 /*
190  * fubyte(caddr_t uaddr);
191  * Fetch a byte from the user's address space.
192  */
193
194 ENTRY(fubyte)
195         ldr     r3, =VM_MAXUSER_ADDRESS
196         cmp     r0, r3
197         mvncs   r0, #0
198         RETc(cs)
199
200         GET_PCB(r2)
201         ldr     r2, [r2]
202
203 #ifdef DIAGNOSTIC
204         teq     r2, #0x00000000
205         beq     .Lfusupcbfault
206 #endif
207
208         adr     r1, .Lfusufault
209         str     r1, [r2, #PCB_ONFAULT]
210
211         ldrbt   r3, [r0]
212
213         mov     r1, #0x00000000
214         str     r1, [r2, #PCB_ONFAULT]
215         mov     r0, r3
216         RET
217 END(fubyte)
218
219 /*
220  * Handle faults from [fs]u*().  Clean up and return -1.
221  */
222
223 .Lfusufault:
224         mov     r0, #0x00000000
225         str     r0, [r2, #PCB_ONFAULT]
226         mvn     r0, #0x00000000
227         RET
228
229 #ifdef DIAGNOSTIC
230 /*
231  * Handle earlier faults from [fs]u*(), due to no pcb
232  */
233
234 .Lfusupcbfault:
235         mov     r1, r0
236         adr     r0, fusupcbfaulttext
237         b       _C_LABEL(panic)
238
239 fusupcbfaulttext:
240         .asciz  "Yikes - no valid PCB during fusuxxx() addr=%08x\n"
241         .align  2
242 #endif
243
244 /*
245  * suword(caddr_t uaddr, int x);
246  * Store an int in the user's address space.
247  */
248
249 ENTRY(suword)
250 EENTRY_NP(suword32)
251         ldr     r3, =(VM_MAXUSER_ADDRESS-3)
252         cmp     r0, r3
253         mvncs   r0, #0
254         RETc(cs)
255
256         GET_PCB(r2)
257         ldr     r2, [r2]
258
259 #ifdef DIAGNOSTIC
260         teq     r2, #0x00000000
261         beq     .Lfusupcbfault
262 #endif
263
264         adr     r3, .Lfusufault
265         str     r3, [r2, #PCB_ONFAULT]
266
267         strt    r1, [r0]
268
269         mov     r0, #0x00000000
270         str     r0, [r2, #PCB_ONFAULT]
271         RET
272 EEND(suword32)
273 END(suword)
274
275 /*
276  * suswintr(caddr_t uaddr, short x);
277  * Store a short in the user's address space.  Can be called during an
278  * interrupt.
279  */
280
281 ENTRY(suswintr)
282         mov     r0, #-1
283         RET
284 END(suswintr)
285
286 /*
287  * susword(caddr_t uaddr, short x);
288  * Store a short in the user's address space.
289  */
290
291 ENTRY(susword)
292         ldr     r3, =(VM_MAXUSER_ADDRESS-1)
293         cmp     r0, r3
294         mvncs   r0, #0
295         RETc(cs)
296
297         GET_PCB(r2)
298         ldr     r2, [r2]
299
300 #ifdef DIAGNOSTIC
301         teq     r2, #0x00000000
302         beq     .Lfusupcbfault
303 #endif
304
305         adr     r3, .Lfusufault
306         str     r3, [r2, #PCB_ONFAULT]
307
308 #ifdef __ARMEB__
309         mov     ip, r1, lsr #8
310         strbt   ip, [r0], #1
311 #else
312         strbt   r1, [r0], #1
313         mov     r1, r1, lsr #8
314 #endif
315         strbt   r1, [r0]
316
317         mov     r0, #0x00000000
318         str     r0, [r2, #PCB_ONFAULT]
319         RET
320 END(susword)
321
322 /*
323  * subyte(caddr_t uaddr, char x);
324  * Store a byte in the user's address space.
325  */
326
327 ENTRY(subyte)
328         ldr     r3, =VM_MAXUSER_ADDRESS
329         cmp     r0, r3
330         mvncs   r0, #0
331         RETc(cs)
332
333         GET_PCB(r2)
334         ldr     r2, [r2]
335
336
337 #ifdef DIAGNOSTIC
338         teq     r2, #0x00000000
339         beq     .Lfusupcbfault
340 #endif
341
342         adr     r3, .Lfusufault
343         str     r3, [r2, #PCB_ONFAULT]
344
345         strbt   r1, [r0]
346         mov     r0, #0x00000000
347         str     r0, [r2, #PCB_ONFAULT]
348         RET
349 END(subyte)