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 * suword(caddr_t uaddr, int x); 217 * Store an int in the user's address space. 218 */ 219 220ENTRY(suword) 221EENTRY_NP(suword32) 222 ldr r3, =(VM_MAXUSER_ADDRESS-3) 223 cmp r0, r3 224 mvncs r0, #0 225 RETc(cs) 226 227 GET_PCB(r2) 228 ldr r2, [r2] 229 230#ifdef DIAGNOSTIC 231 teq r2, #0x00000000 232 beq .Lfusupcbfault 233#endif 234 235 adr r3, .Lfusufault 236 str r3, [r2, #PCB_ONFAULT] 237 238 strt r1, [r0] 239 240 mov r0, #0x00000000 241 str r0, [r2, #PCB_ONFAULT] 242 RET 243EEND(suword32) 244END(suword) 245 246/* 247 * susword(caddr_t uaddr, short x); 248 * Store a short in the user's address space. 249 */ 250 251ENTRY(susword) 252 ldr r3, =(VM_MAXUSER_ADDRESS-1) 253 cmp r0, r3 254 mvncs r0, #0 255 RETc(cs) 256 257 GET_PCB(r2) 258 ldr r2, [r2] 259 260#ifdef DIAGNOSTIC 261 teq r2, #0x00000000 262 beq .Lfusupcbfault 263#endif 264 265 adr r3, .Lfusufault 266 str r3, [r2, #PCB_ONFAULT] 267 268 strbt r1, [r0], #1 269 mov r1, r1, lsr #8 270 strbt r1, [r0] 271 272 mov r0, #0x00000000 273 str r0, [r2, #PCB_ONFAULT] 274 RET 275END(susword) 276 277/* 278 * subyte(caddr_t uaddr, char x); 279 * Store a byte in the user's address space. 280 */ 281 282ENTRY(subyte) 283 ldr r3, =VM_MAXUSER_ADDRESS 284 cmp r0, r3 285 mvncs r0, #0 286 RETc(cs) 287 288 GET_PCB(r2) 289 ldr r2, [r2] 290 291 292#ifdef DIAGNOSTIC 293 teq r2, #0x00000000 294 beq .Lfusupcbfault 295#endif 296 297 adr r3, .Lfusufault 298 str r3, [r2, #PCB_ONFAULT] 299 300 strbt r1, [r0] 301 mov r0, #0x00000000 302 str r0, [r2, #PCB_ONFAULT] 303 RET 304END(subyte) 305