1129198Scognet/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 1996-1998 Mark Brinicombe. 5129198Scognet * All rights reserved. 6129198Scognet * 7129198Scognet * Redistribution and use in source and binary forms, with or without 8129198Scognet * modification, are permitted provided that the following conditions 9129198Scognet * are met: 10129198Scognet * 1. Redistributions of source code must retain the above copyright 11129198Scognet * notice, this list of conditions and the following disclaimer. 12129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer in the 14129198Scognet * documentation and/or other materials provided with the distribution. 15129198Scognet * 3. All advertising materials mentioning features or use of this software 16129198Scognet * must display the following acknowledgement: 17129198Scognet * This product includes software developed by Mark Brinicombe 18129198Scognet * 4. The name of the company nor the name of the author may be used to 19129198Scognet * endorse or promote products derived from this software without specific 20129198Scognet * prior written permission. 21129198Scognet * 22129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32129198Scognet * SUCH DAMAGE. 33129198Scognet * 34129198Scognet */ 35129198Scognet 36129198Scognet#include <machine/asm.h> 37129198Scognet#include <machine/armreg.h> 38129198Scognet#include "assym.s" 39129198Scognet__FBSDID("$FreeBSD$"); 40129198Scognet 41275520Sandrew .syntax unified 42275520Sandrew 43282763Sandrew#if __ARM_ARCH >= 6 44239268Sgonzo#define GET_PCB(tmp) \ 45239268Sgonzo mrc p15, 0, tmp, c13, c0, 4; \ 46261415Scognet add tmp, tmp, #(TD_PCB) 47129198Scognet#else 48129198Scognet.Lcurpcb: 49129198Scognet .word _C_LABEL(__pcpu) + PC_CURPCB 50239268Sgonzo#define GET_PCB(tmp) \ 51239268Sgonzo ldr tmp, .Lcurpcb 52129198Scognet#endif 53129198Scognet 54129198Scognet/* 55289372Skib * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, 56289372Skib * uint32_t newval); 57129198Scognet */ 58129198Scognet 59289372SkibENTRY(casueword) 60289372SkibEENTRY_NP(casueword32) 61289372Skib stmfd sp!, {r4, r5, r6} 62137271Scognet 63289372Skib ldr r4, =(VM_MAXUSER_ADDRESS-3) 64289372Skib cmp r0, r4 65289372Skib mvncs r0, #0 66289372Skib bcs 2f 67289372Skib 68289372Skib GET_PCB(r6) 69289372Skib ldr r6, [r6] 70289372Skib 71137271Scognet#ifdef DIAGNOSTIC 72289372Skib teq r6, #0x00000000 73289372Skib ldmfdeq sp!, {r4, r5, r6} 74137271Scognet beq .Lfusupcbfault 75137271Scognet#endif 76289372Skib 77163449Sdavidxu adr r4, .Lcasuwordfault 78289372Skib str r4, [r6, #PCB_ONFAULT] 79289372Skib 80282763Sandrew#if __ARM_ARCH >= 6 81283366Sandrew1: 82289372Skib ldrex r4, [r0] 83289372Skib cmp r4, r1 84289372Skib strexeq r5, r3, [r0] 85289372Skib cmpeq r5, #1 86289372Skib beq 1b 87256691Scognet#else 88289372Skib ldrt r4, [r0] 89289372Skib cmp r4, r1 90289372Skib strteq r3, [r0] 91256691Scognet#endif 92289372Skib str r4, [r2] 93289372Skib mov r0, #0 94289372Skib str r0, [r6, #PCB_ONFAULT] 95256691Scognet2: 96289372Skib ldmfd sp!, {r4, r5, r6} 97137463Scognet RET 98289372SkibEEND(casueword32) 99289372SkibEND(casueword) 100137271Scognet 101137271Scognet/* 102163449Sdavidxu * Handle faults from casuword. Clean up and return -1. 103145452Scognet */ 104145452Scognet 105163449Sdavidxu.Lcasuwordfault: 106145452Scognet mov r0, #0x00000000 107289372Skib str r0, [r6, #PCB_ONFAULT] 108289372Skib mvn r0, #0 109289372Skib ldmfd sp!, {r4, r5, r6} 110283366Sandrew RET 111248361Sandrew 112145452Scognet/* 113289372Skib * fueword(caddr_t uaddr, long *val); 114137271Scognet * Fetch an int from the user's address space. 115137271Scognet */ 116137271Scognet 117289372SkibENTRY(fueword) 118289372SkibEENTRY_NP(fueword32) 119289372Skib ldr r3, =(VM_MAXUSER_ADDRESS-3) 120289372Skib cmp r0, r3 121289372Skib mvncs r0, #0 122289372Skib RETc(cs) 123289372Skib 124239268Sgonzo GET_PCB(r2) 125129198Scognet ldr r2, [r2] 126129198Scognet 127129198Scognet#ifdef DIAGNOSTIC 128129198Scognet teq r2, #0x00000000 129129198Scognet beq .Lfusupcbfault 130129198Scognet#endif 131129198Scognet 132289372Skib adr r3, .Lfusufault 133289372Skib str r3, [r2, #PCB_ONFAULT] 134129198Scognet 135129198Scognet ldrt r3, [r0] 136289372Skib str r3, [r1] 137129198Scognet 138289372Skib mov r0, #0x00000000 139289372Skib str r0, [r2, #PCB_ONFAULT] 140137463Scognet RET 141293830SianEEND(fueword32) 142293830SianEND(fueword) 143129198Scognet 144129198Scognet/* 145129198Scognet * fusword(caddr_t uaddr); 146129198Scognet * Fetch a short from the user's address space. 147129198Scognet */ 148129198Scognet 149129198ScognetENTRY(fusword) 150289372Skib ldr r3, =(VM_MAXUSER_ADDRESS-1) 151289372Skib cmp r0, r3 152289372Skib mvncs r0, #0 153289372Skib RETc(cs) 154289372Skib 155239268Sgonzo GET_PCB(r2) 156129198Scognet ldr r2, [r2] 157129198Scognet 158129198Scognet#ifdef DIAGNOSTIC 159129198Scognet teq r2, #0x00000000 160129198Scognet beq .Lfusupcbfault 161129198Scognet#endif 162129198Scognet 163129198Scognet adr r1, .Lfusufault 164129198Scognet str r1, [r2, #PCB_ONFAULT] 165129198Scognet 166129198Scognet ldrbt r3, [r0], #1 167129198Scognet ldrbt ip, [r0] 168129198Scognet#ifdef __ARMEB__ 169129198Scognet orr r0, ip, r3, asl #8 170129198Scognet#else 171129198Scognet orr r0, r3, ip, asl #8 172129198Scognet#endif 173129198Scognet mov r1, #0x00000000 174129198Scognet str r1, [r2, #PCB_ONFAULT] 175137463Scognet RET 176248361SandrewEND(fusword) 177129198Scognet 178129198Scognet/* 179129198Scognet * fuswintr(caddr_t uaddr); 180129198Scognet * Fetch a short from the user's address space. Can be called during an 181129198Scognet * interrupt. 182129198Scognet */ 183129198Scognet 184129198ScognetENTRY(fuswintr) 185295267Smmel mov r0, #-1 186137463Scognet RET 187248361SandrewEND(fuswintr) 188129198Scognet 189129198Scognet/* 190129198Scognet * fubyte(caddr_t uaddr); 191129198Scognet * Fetch a byte from the user's address space. 192129198Scognet */ 193129198Scognet 194129198ScognetENTRY(fubyte) 195289372Skib ldr r3, =VM_MAXUSER_ADDRESS 196289372Skib cmp r0, r3 197289372Skib mvncs r0, #0 198289372Skib RETc(cs) 199289372Skib 200239268Sgonzo GET_PCB(r2) 201129198Scognet ldr r2, [r2] 202129198Scognet 203129198Scognet#ifdef DIAGNOSTIC 204129198Scognet teq r2, #0x00000000 205129198Scognet beq .Lfusupcbfault 206129198Scognet#endif 207129198Scognet 208129198Scognet adr r1, .Lfusufault 209129198Scognet str r1, [r2, #PCB_ONFAULT] 210129198Scognet 211129198Scognet ldrbt r3, [r0] 212129198Scognet 213129198Scognet mov r1, #0x00000000 214129198Scognet str r1, [r2, #PCB_ONFAULT] 215129198Scognet mov r0, r3 216137463Scognet RET 217248361SandrewEND(fubyte) 218129198Scognet 219129198Scognet/* 220129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. 221129198Scognet */ 222129198Scognet 223129198Scognet.Lfusufault: 224129198Scognet mov r0, #0x00000000 225129198Scognet str r0, [r2, #PCB_ONFAULT] 226129198Scognet mvn r0, #0x00000000 227137463Scognet RET 228129198Scognet 229129198Scognet#ifdef DIAGNOSTIC 230129198Scognet/* 231129198Scognet * Handle earlier faults from [fs]u*(), due to no pcb 232129198Scognet */ 233129198Scognet 234129198Scognet.Lfusupcbfault: 235129198Scognet mov r1, r0 236129198Scognet adr r0, fusupcbfaulttext 237129198Scognet b _C_LABEL(panic) 238129198Scognet 239129198Scognetfusupcbfaulttext: 240129198Scognet .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 241275521Sandrew .align 2 242129198Scognet#endif 243129198Scognet 244129198Scognet/* 245129198Scognet * suword(caddr_t uaddr, int x); 246129198Scognet * Store an int in the user's address space. 247129198Scognet */ 248129198Scognet 249129198ScognetENTRY(suword) 250269390SianEENTRY_NP(suword32) 251289372Skib ldr r3, =(VM_MAXUSER_ADDRESS-3) 252289372Skib cmp r0, r3 253289372Skib mvncs r0, #0 254289372Skib RETc(cs) 255289372Skib 256239268Sgonzo GET_PCB(r2) 257129198Scognet ldr r2, [r2] 258129198Scognet 259129198Scognet#ifdef DIAGNOSTIC 260129198Scognet teq r2, #0x00000000 261129198Scognet beq .Lfusupcbfault 262129198Scognet#endif 263129198Scognet 264129198Scognet adr r3, .Lfusufault 265129198Scognet str r3, [r2, #PCB_ONFAULT] 266129198Scognet 267129198Scognet strt r1, [r0] 268129198Scognet 269129198Scognet mov r0, #0x00000000 270129198Scognet str r0, [r2, #PCB_ONFAULT] 271137463Scognet RET 272275322SandrewEEND(suword32) 273248361SandrewEND(suword) 274129198Scognet 275129198Scognet/* 276129198Scognet * suswintr(caddr_t uaddr, short x); 277129198Scognet * Store a short in the user's address space. Can be called during an 278129198Scognet * interrupt. 279129198Scognet */ 280129198Scognet 281129198ScognetENTRY(suswintr) 282295267Smmel mov r0, #-1 283137463Scognet RET 284248361SandrewEND(suswintr) 285129198Scognet 286129198Scognet/* 287129198Scognet * susword(caddr_t uaddr, short x); 288129198Scognet * Store a short in the user's address space. 289129198Scognet */ 290129198Scognet 291129198ScognetENTRY(susword) 292289372Skib ldr r3, =(VM_MAXUSER_ADDRESS-1) 293289372Skib cmp r0, r3 294289372Skib mvncs r0, #0 295289372Skib RETc(cs) 296289372Skib 297239268Sgonzo GET_PCB(r2) 298129198Scognet ldr r2, [r2] 299129198Scognet 300129198Scognet#ifdef DIAGNOSTIC 301129198Scognet teq r2, #0x00000000 302129198Scognet beq .Lfusupcbfault 303129198Scognet#endif 304129198Scognet 305129198Scognet adr r3, .Lfusufault 306129198Scognet str r3, [r2, #PCB_ONFAULT] 307129198Scognet 308129198Scognet#ifdef __ARMEB__ 309129198Scognet mov ip, r1, lsr #8 310129198Scognet strbt ip, [r0], #1 311129198Scognet#else 312129198Scognet strbt r1, [r0], #1 313129198Scognet mov r1, r1, lsr #8 314129198Scognet#endif 315129198Scognet strbt r1, [r0] 316129198Scognet 317129198Scognet mov r0, #0x00000000 318129198Scognet str r0, [r2, #PCB_ONFAULT] 319137463Scognet RET 320248361SandrewEND(susword) 321129198Scognet 322129198Scognet/* 323129198Scognet * subyte(caddr_t uaddr, char x); 324129198Scognet * Store a byte in the user's address space. 325129198Scognet */ 326129198Scognet 327129198ScognetENTRY(subyte) 328289372Skib ldr r3, =VM_MAXUSER_ADDRESS 329289372Skib cmp r0, r3 330289372Skib mvncs r0, #0 331289372Skib RETc(cs) 332289372Skib 333239268Sgonzo GET_PCB(r2) 334129198Scognet ldr r2, [r2] 335129198Scognet 336129198Scognet 337129198Scognet#ifdef DIAGNOSTIC 338129198Scognet teq r2, #0x00000000 339129198Scognet beq .Lfusupcbfault 340129198Scognet#endif 341129198Scognet 342129198Scognet adr r3, .Lfusufault 343129198Scognet str r3, [r2, #PCB_ONFAULT] 344129198Scognet 345129198Scognet strbt r1, [r0] 346129198Scognet mov r0, #0x00000000 347129198Scognet str r0, [r2, #PCB_ONFAULT] 348137463Scognet RET 349248361SandrewEND(subyte) 350