fusu.S revision 137463
1129198Scognet/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */ 2129198Scognet 3129198Scognet/* 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/asmacros.h> 38129198Scognet#include <machine/armreg.h> 39129198Scognet#include "assym.s" 40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/fusu.S 137463 2004-11-09 16:47:47Z cognet $"); 41129198Scognet 42129198Scognet#ifdef MULTIPROCESSOR 43129198Scognet.Lcpu_info: 44129198Scognet .word _C_LABEL(cpu_info) 45129198Scognet#else 46129198Scognet.Lcurpcb: 47129198Scognet .word _C_LABEL(__pcpu) + PC_CURPCB 48129198Scognet#endif 49129198Scognet 50129198Scognet/* 51129198Scognet * fuword(caddr_t uaddr); 52129198Scognet * Fetch an int from the user's address space. 53129198Scognet */ 54129198Scognet 55137271ScognetENTRY(casuptr) 56137271Scognet#ifdef MULTIPROCESSOR 57137271Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 58137271Scognet stmfd sp!, {r0, r14} 59137271Scognet bl _C_LABEL(cpu_number) 60137271Scognet ldr r2, .Lcpu_info 61137271Scognet ldr r2, [r2, r0, lsl #2] 62137271Scognet ldr r2, [r2, #CI_CURPCB] 63137271Scognet ldmfd sp!, {r0, r14} 64137271Scognet#else 65137271Scognet ldr r3, .Lcurpcb 66137271Scognet ldr r3, [r3] 67137271Scognet#endif 68137271Scognet 69137271Scognet#ifdef DIAGNOSTIC 70137271Scognet teq r3, #0x00000000 71137271Scognet beq .Lfusupcbfault 72137271Scognet#endif 73137271Scognet stmfd sp!, {r4} 74137271Scognet adr r4, .Lfusufault 75137271Scognet str r4, [r3, #PCB_ONFAULT] 76137271Scognet ldmfd sp!, {r4} 77137271Scognet ldrt r3, [r0] 78137271Scognet cmp r3, r1 79137271Scognet movne r0, r3 80137463Scognet RETne 81137271Scognet strt r2, [r0] 82137271Scognet mov r0, r1 83137271Scognet#ifdef MULTIPROCESSOR 84137271Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 85137271Scognet stmfd sp!, {r0, r14} 86137271Scognet bl _C_LABEL(cpu_number) 87137271Scognet ldr r2, .Lcpu_info 88137271Scognet ldr r2, [r2, r0, lsl #2] 89137271Scognet ldr r2, [r2, #CI_CURPCB] 90137271Scognet ldmfd sp!, {r0, r14} 91137271Scognet#else 92137271Scognet ldr r3, .Lcurpcb 93137271Scognet ldr r3, [r3] 94137271Scognet#endif 95137271Scognet mov r1, #0x00000000 96137271Scognet str r1, [r3, #PCB_ONFAULT] 97137463Scognet RET 98137271Scognet 99137271Scognet 100137271Scognet/* 101137271Scognet * fuword(caddr_t uaddr); 102137271Scognet * Fetch an int from the user's address space. 103137271Scognet */ 104137271Scognet 105135881ScognetENTRY(fuword32) 106129198ScognetENTRY(fuword) 107129198Scognet#ifdef MULTIPROCESSOR 108129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 109129198Scognet stmfd sp!, {r0, r14} 110129198Scognet bl _C_LABEL(cpu_number) 111129198Scognet ldr r2, .Lcpu_info 112129198Scognet ldr r2, [r2, r0, lsl #2] 113129198Scognet ldr r2, [r2, #CI_CURPCB] 114129198Scognet ldmfd sp!, {r0, r14} 115129198Scognet#else 116129198Scognet ldr r2, .Lcurpcb 117129198Scognet ldr r2, [r2] 118129198Scognet#endif 119129198Scognet 120129198Scognet#ifdef DIAGNOSTIC 121129198Scognet teq r2, #0x00000000 122129198Scognet beq .Lfusupcbfault 123129198Scognet#endif 124129198Scognet 125129198Scognet adr r1, .Lfusufault 126129198Scognet str r1, [r2, #PCB_ONFAULT] 127129198Scognet 128129198Scognet ldrt r3, [r0] 129129198Scognet 130129198Scognet mov r1, #0x00000000 131129198Scognet str r1, [r2, #PCB_ONFAULT] 132129198Scognet mov r0, r3 133137463Scognet RET 134129198Scognet 135129198Scognet/* 136129198Scognet * fusword(caddr_t uaddr); 137129198Scognet * Fetch a short from the user's address space. 138129198Scognet */ 139129198Scognet 140129198ScognetENTRY(fusword) 141129198Scognet#ifdef MULTIPROCESSOR 142129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 143129198Scognet stmfd sp!, {r0, r14} 144129198Scognet bl _C_LABEL(cpu_number) 145129198Scognet ldr r2, .Lcpu_info 146129198Scognet ldr r2, [r2, r0, lsl #2] 147129198Scognet ldr r2, [r2, #CI_CURPCB] 148129198Scognet ldmfd sp!, {r0, r14} 149129198Scognet#else 150129198Scognet ldr r2, .Lcurpcb 151129198Scognet ldr r2, [r2] 152129198Scognet#endif 153129198Scognet 154129198Scognet#ifdef DIAGNOSTIC 155129198Scognet teq r2, #0x00000000 156129198Scognet beq .Lfusupcbfault 157129198Scognet#endif 158129198Scognet 159129198Scognet adr r1, .Lfusufault 160129198Scognet str r1, [r2, #PCB_ONFAULT] 161129198Scognet 162129198Scognet ldrbt r3, [r0], #1 163129198Scognet ldrbt ip, [r0] 164129198Scognet#ifdef __ARMEB__ 165129198Scognet orr r0, ip, r3, asl #8 166129198Scognet#else 167129198Scognet orr r0, r3, ip, asl #8 168129198Scognet#endif 169129198Scognet mov r1, #0x00000000 170129198Scognet str r1, [r2, #PCB_ONFAULT] 171137463Scognet RET 172129198Scognet 173129198Scognet/* 174129198Scognet * fuswintr(caddr_t uaddr); 175129198Scognet * Fetch a short from the user's address space. Can be called during an 176129198Scognet * interrupt. 177129198Scognet */ 178129198Scognet 179129198ScognetENTRY(fuswintr) 180129198Scognet ldr r2, Lblock_userspace_access 181129198Scognet ldr r2, [r2] 182129198Scognet teq r2, #0 183129198Scognet mvnne r0, #0x00000000 184137463Scognet RETne 185129198Scognet 186129198Scognet#ifdef MULTIPROCESSOR 187129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 188129198Scognet stmfd sp!, {r0, r14} 189129198Scognet bl _C_LABEL(cpu_number) 190129198Scognet ldr r2, .Lcpu_info 191129198Scognet ldr r2, [r2, r0, lsl #2] 192129198Scognet ldr r2, [r2, #CI_CURPCB] 193129198Scognet ldmfd sp!, {r0, r14} 194129198Scognet#else 195129198Scognet ldr r2, .Lcurpcb 196129198Scognet ldr r2, [r2] 197129198Scognet#endif 198129198Scognet 199129198Scognet#ifdef DIAGNOSTIC 200129198Scognet teq r2, #0x00000000 201129198Scognet beq .Lfusupcbfault 202129198Scognet#endif 203129198Scognet 204129198Scognet adr r1, _C_LABEL(fusubailout) 205129198Scognet str r1, [r2, #PCB_ONFAULT] 206129198Scognet 207129198Scognet ldrbt r3, [r0], #1 208129198Scognet ldrbt ip, [r0] 209129198Scognet#ifdef __ARMEB__ 210129198Scognet orr r0, ip, r3, asl #8 211129198Scognet#else 212129198Scognet orr r0, r3, ip, asl #8 213129198Scognet#endif 214129198Scognet 215129198Scognet mov r1, #0x00000000 216129198Scognet str r1, [r2, #PCB_ONFAULT] 217137463Scognet RET 218129198Scognet 219129198ScognetLblock_userspace_access: 220129198Scognet .word _C_LABEL(block_userspace_access) 221129198Scognet 222129198Scognet .data 223129198Scognet .align 0 224129198Scognet .global _C_LABEL(block_userspace_access) 225129198Scognet_C_LABEL(block_userspace_access): 226129198Scognet .word 0 227129198Scognet .text 228129198Scognet 229129198Scognet/* 230129198Scognet * fubyte(caddr_t uaddr); 231129198Scognet * Fetch a byte from the user's address space. 232129198Scognet */ 233129198Scognet 234129198ScognetENTRY(fubyte) 235129198Scognet#ifdef MULTIPROCESSOR 236129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 237129198Scognet stmfd sp!, {r0, r14} 238129198Scognet bl _C_LABEL(cpu_number) 239129198Scognet ldr r2, .Lcpu_info 240129198Scognet ldr r2, [r2, r0, lsl #2] 241129198Scognet ldr r2, [r2, #CI_CURPCB] 242129198Scognet ldmfd sp!, {r0, r14} 243129198Scognet#else 244129198Scognet ldr r2, .Lcurpcb 245129198Scognet ldr r2, [r2] 246129198Scognet#endif 247129198Scognet 248129198Scognet#ifdef DIAGNOSTIC 249129198Scognet teq r2, #0x00000000 250129198Scognet beq .Lfusupcbfault 251129198Scognet#endif 252129198Scognet 253129198Scognet adr r1, .Lfusufault 254129198Scognet str r1, [r2, #PCB_ONFAULT] 255129198Scognet 256129198Scognet ldrbt r3, [r0] 257129198Scognet 258129198Scognet mov r1, #0x00000000 259129198Scognet str r1, [r2, #PCB_ONFAULT] 260129198Scognet mov r0, r3 261137463Scognet RET 262129198Scognet 263129198Scognet/* 264129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. 265129198Scognet */ 266129198Scognet 267129198Scognet.Lfusufault: 268129198Scognet mov r0, #0x00000000 269129198Scognet str r0, [r2, #PCB_ONFAULT] 270129198Scognet mvn r0, #0x00000000 271137463Scognet RET 272129198Scognet 273129198Scognet/* 274129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. This differs from 275129198Scognet * fusufault() in that trap() will recognise it and return immediately rather 276129198Scognet * than trying to page fault. 277129198Scognet */ 278129198Scognet 279129198Scognet/* label must be global as fault.c references it */ 280129198Scognet .global _C_LABEL(fusubailout) 281129198Scognet_C_LABEL(fusubailout): 282129198Scognet mov r0, #0x00000000 283129198Scognet str r0, [r2, #PCB_ONFAULT] 284129198Scognet mvn r0, #0x00000000 285137463Scognet RET 286129198Scognet 287129198Scognet#ifdef DIAGNOSTIC 288129198Scognet/* 289129198Scognet * Handle earlier faults from [fs]u*(), due to no pcb 290129198Scognet */ 291129198Scognet 292129198Scognet.Lfusupcbfault: 293129198Scognet mov r1, r0 294129198Scognet adr r0, fusupcbfaulttext 295129198Scognet b _C_LABEL(panic) 296129198Scognet 297129198Scognetfusupcbfaulttext: 298129198Scognet .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 299129198Scognet .align 0 300129198Scognet#endif 301129198Scognet 302129198Scognet/* 303129198Scognet * suword(caddr_t uaddr, int x); 304129198Scognet * Store an int in the user's address space. 305129198Scognet */ 306129198Scognet 307137271ScognetENTRY(suword32) 308129198ScognetENTRY(suword) 309129198Scognet#ifdef MULTIPROCESSOR 310129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 311129198Scognet stmfd sp!, {r0, r1, r14} 312129198Scognet bl _C_LABEL(cpu_number) 313129198Scognet ldr r2, .Lcpu_info 314129198Scognet ldr r2, [r2, r0, lsl #2] 315129198Scognet ldr r2, [r2, #CI_CURPCB] 316129198Scognet ldmfd sp!, {r0, r1, r14} 317129198Scognet#else 318129198Scognet ldr r2, .Lcurpcb 319129198Scognet ldr r2, [r2] 320129198Scognet#endif 321129198Scognet 322129198Scognet#ifdef DIAGNOSTIC 323129198Scognet teq r2, #0x00000000 324129198Scognet beq .Lfusupcbfault 325129198Scognet#endif 326129198Scognet 327129198Scognet adr r3, .Lfusufault 328129198Scognet str r3, [r2, #PCB_ONFAULT] 329129198Scognet 330129198Scognet strt r1, [r0] 331129198Scognet 332129198Scognet mov r0, #0x00000000 333129198Scognet str r0, [r2, #PCB_ONFAULT] 334137463Scognet RET 335129198Scognet 336129198Scognet/* 337129198Scognet * suswintr(caddr_t uaddr, short x); 338129198Scognet * Store a short in the user's address space. Can be called during an 339129198Scognet * interrupt. 340129198Scognet */ 341129198Scognet 342129198ScognetENTRY(suswintr) 343129198Scognet ldr r2, Lblock_userspace_access 344129198Scognet ldr r2, [r2] 345129198Scognet teq r2, #0 346129198Scognet mvnne r0, #0x00000000 347137463Scognet RETne 348129198Scognet 349129198Scognet#ifdef MULTIPROCESSOR 350129198Scognet stmfd sp!, {r0, r1, r14} 351129198Scognet bl _C_LABEL(cpu_number) 352129198Scognet ldr r2, .Lcpu_info 353129198Scognet ldr r2, [r2, r0, lsl #2] 354129198Scognet ldr r2, [r2, #CI_CURPCB] 355129198Scognet ldmfd sp!, {r0, r1, r14} 356129198Scognet#else 357129198Scognet ldr r2, .Lcurpcb 358129198Scognet ldr r2, [r2] 359129198Scognet#endif 360129198Scognet 361129198Scognet#ifdef DIAGNOSTIC 362129198Scognet teq r2, #0x00000000 363129198Scognet beq .Lfusupcbfault 364129198Scognet#endif 365129198Scognet 366129198Scognet adr r3, _C_LABEL(fusubailout) 367129198Scognet str r3, [r2, #PCB_ONFAULT] 368129198Scognet 369129198Scognet#ifdef __ARMEB__ 370129198Scognet mov ip, r1, lsr #8 371129198Scognet strbt ip, [r0], #1 372129198Scognet#else 373129198Scognet strbt r1, [r0], #1 374129198Scognet mov r1, r1, lsr #8 375129198Scognet#endif 376129198Scognet strbt r1, [r0] 377129198Scognet 378129198Scognet mov r0, #0x00000000 379129198Scognet str r0, [r2, #PCB_ONFAULT] 380137463Scognet RET 381129198Scognet 382129198Scognet/* 383129198Scognet * susword(caddr_t uaddr, short x); 384129198Scognet * Store a short in the user's address space. 385129198Scognet */ 386129198Scognet 387129198ScognetENTRY(susword) 388129198Scognet#ifdef MULTIPROCESSOR 389129198Scognet stmfd sp!, {r0, r1, r14} 390129198Scognet bl _C_LABEL(cpu_number) 391129198Scognet ldr r2, .Lcpu_info 392129198Scognet ldr r2, [r2, r0, lsl #2] 393129198Scognet ldr r2, [r2, #CI_CURPCB] 394129198Scognet ldmfd sp!, {r0, r1, r14} 395129198Scognet#else 396129198Scognet ldr r2, .Lcurpcb 397129198Scognet ldr r2, [r2] 398129198Scognet#endif 399129198Scognet 400129198Scognet#ifdef DIAGNOSTIC 401129198Scognet teq r2, #0x00000000 402129198Scognet beq .Lfusupcbfault 403129198Scognet#endif 404129198Scognet 405129198Scognet adr r3, .Lfusufault 406129198Scognet str r3, [r2, #PCB_ONFAULT] 407129198Scognet 408129198Scognet#ifdef __ARMEB__ 409129198Scognet mov ip, r1, lsr #8 410129198Scognet strbt ip, [r0], #1 411129198Scognet#else 412129198Scognet strbt r1, [r0], #1 413129198Scognet mov r1, r1, lsr #8 414129198Scognet#endif 415129198Scognet strbt r1, [r0] 416129198Scognet 417129198Scognet mov r0, #0x00000000 418129198Scognet str r0, [r2, #PCB_ONFAULT] 419137463Scognet RET 420129198Scognet 421129198Scognet/* 422129198Scognet * subyte(caddr_t uaddr, char x); 423129198Scognet * Store a byte in the user's address space. 424129198Scognet */ 425129198Scognet 426129198ScognetENTRY(subyte) 427129198Scognet#ifdef MULTIPROCESSOR 428129198Scognet stmfd sp!, {r0, r1, r14} 429129198Scognet bl _C_LABEL(cpu_number) 430129198Scognet ldr r2, .Lcpu_info 431129198Scognet ldr r2, [r2, r0, lsl #2] 432129198Scognet ldr r2, [r2, #CI_CURPCB] 433129198Scognet ldmfd sp!, {r0, r1, r14} 434129198Scognet#else 435129198Scognet ldr r2, .Lcurpcb 436129198Scognet ldr r2, [r2] 437129198Scognet#endif 438129198Scognet 439129198Scognet 440129198Scognet#ifdef DIAGNOSTIC 441129198Scognet teq r2, #0x00000000 442129198Scognet beq .Lfusupcbfault 443129198Scognet#endif 444129198Scognet 445129198Scognet adr r3, .Lfusufault 446129198Scognet str r3, [r2, #PCB_ONFAULT] 447129198Scognet 448129198Scognet strbt r1, [r0] 449129198Scognet mov r0, #0x00000000 450129198Scognet str r0, [r2, #PCB_ONFAULT] 451137463Scognet RET 452