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