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