fusu.S revision 163449
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/asmacros.h> 38129198Scognet#include <machine/armreg.h> 39129198Scognet#include "assym.s" 40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/fusu.S 163449 2006-10-17 02:24:47Z davidxu $"); 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 55161734ScognetENTRY_NP(casuword32) 56163449SdavidxuENTRY(casuword) 57137271Scognet#ifdef MULTIPROCESSOR 58137271Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 59137271Scognet stmfd sp!, {r0, r14} 60137271Scognet bl _C_LABEL(cpu_number) 61137271Scognet ldr r2, .Lcpu_info 62137271Scognet ldr r2, [r2, r0, lsl #2] 63137271Scognet ldr r2, [r2, #CI_CURPCB] 64137271Scognet ldmfd sp!, {r0, r14} 65137271Scognet#else 66137271Scognet ldr r3, .Lcurpcb 67137271Scognet ldr r3, [r3] 68137271Scognet#endif 69137271Scognet 70137271Scognet#ifdef DIAGNOSTIC 71137271Scognet teq r3, #0x00000000 72137271Scognet beq .Lfusupcbfault 73137271Scognet#endif 74145452Scognet stmfd sp!, {r4, r5} 75163449Sdavidxu adr r4, .Lcasuwordfault 76137271Scognet str r4, [r3, #PCB_ONFAULT] 77145452Scognet ldrt r5, [r0] 78145452Scognet cmp r5, r1 79145452Scognet movne r0, r5 80145452Scognet streqt r2, [r0] 81145452Scognet moveq r0, r1 82145452Scognet ldmfd sp!, {r4, r5} 83137271Scognet mov r1, #0x00000000 84137271Scognet str r1, [r3, #PCB_ONFAULT] 85137463Scognet RET 86137271Scognet 87137271Scognet/* 88163449Sdavidxu * Handle faults from casuword. Clean up and return -1. 89145452Scognet */ 90145452Scognet 91163449Sdavidxu.Lcasuwordfault: 92145452Scognet mov r0, #0x00000000 93145452Scognet str r0, [r3, #PCB_ONFAULT] 94145452Scognet mvn r0, #0x00000000 95145452Scognet ldmfd sp!, {r4, r5} 96145452Scognet RET 97145452Scognet/* 98137271Scognet * fuword(caddr_t uaddr); 99137271Scognet * Fetch an int from the user's address space. 100137271Scognet */ 101137271Scognet 102161734ScognetENTRY_NP(fuword32) 103129198ScognetENTRY(fuword) 104129198Scognet#ifdef MULTIPROCESSOR 105129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 106129198Scognet stmfd sp!, {r0, r14} 107129198Scognet bl _C_LABEL(cpu_number) 108129198Scognet ldr r2, .Lcpu_info 109129198Scognet ldr r2, [r2, r0, lsl #2] 110129198Scognet ldr r2, [r2, #CI_CURPCB] 111129198Scognet ldmfd sp!, {r0, r14} 112129198Scognet#else 113129198Scognet ldr r2, .Lcurpcb 114129198Scognet ldr r2, [r2] 115129198Scognet#endif 116129198Scognet 117129198Scognet#ifdef DIAGNOSTIC 118129198Scognet teq r2, #0x00000000 119129198Scognet beq .Lfusupcbfault 120129198Scognet#endif 121129198Scognet 122129198Scognet adr r1, .Lfusufault 123129198Scognet str r1, [r2, #PCB_ONFAULT] 124129198Scognet 125129198Scognet ldrt r3, [r0] 126129198Scognet 127129198Scognet mov r1, #0x00000000 128129198Scognet str r1, [r2, #PCB_ONFAULT] 129129198Scognet mov r0, r3 130137463Scognet RET 131129198Scognet 132129198Scognet/* 133129198Scognet * fusword(caddr_t uaddr); 134129198Scognet * Fetch a short from the user's address space. 135129198Scognet */ 136129198Scognet 137129198ScognetENTRY(fusword) 138129198Scognet#ifdef MULTIPROCESSOR 139129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 140129198Scognet stmfd sp!, {r0, r14} 141129198Scognet bl _C_LABEL(cpu_number) 142129198Scognet ldr r2, .Lcpu_info 143129198Scognet ldr r2, [r2, r0, lsl #2] 144129198Scognet ldr r2, [r2, #CI_CURPCB] 145129198Scognet ldmfd sp!, {r0, r14} 146129198Scognet#else 147129198Scognet ldr r2, .Lcurpcb 148129198Scognet ldr r2, [r2] 149129198Scognet#endif 150129198Scognet 151129198Scognet#ifdef DIAGNOSTIC 152129198Scognet teq r2, #0x00000000 153129198Scognet beq .Lfusupcbfault 154129198Scognet#endif 155129198Scognet 156129198Scognet adr r1, .Lfusufault 157129198Scognet str r1, [r2, #PCB_ONFAULT] 158129198Scognet 159129198Scognet ldrbt r3, [r0], #1 160129198Scognet ldrbt ip, [r0] 161129198Scognet#ifdef __ARMEB__ 162129198Scognet orr r0, ip, r3, asl #8 163129198Scognet#else 164129198Scognet orr r0, r3, ip, asl #8 165129198Scognet#endif 166129198Scognet mov r1, #0x00000000 167129198Scognet str r1, [r2, #PCB_ONFAULT] 168137463Scognet RET 169129198Scognet 170129198Scognet/* 171129198Scognet * fuswintr(caddr_t uaddr); 172129198Scognet * Fetch a short from the user's address space. Can be called during an 173129198Scognet * interrupt. 174129198Scognet */ 175129198Scognet 176129198ScognetENTRY(fuswintr) 177129198Scognet ldr r2, Lblock_userspace_access 178129198Scognet ldr r2, [r2] 179129198Scognet teq r2, #0 180129198Scognet mvnne r0, #0x00000000 181137463Scognet RETne 182129198Scognet 183129198Scognet#ifdef MULTIPROCESSOR 184129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 185129198Scognet stmfd sp!, {r0, r14} 186129198Scognet bl _C_LABEL(cpu_number) 187129198Scognet ldr r2, .Lcpu_info 188129198Scognet ldr r2, [r2, r0, lsl #2] 189129198Scognet ldr r2, [r2, #CI_CURPCB] 190129198Scognet ldmfd sp!, {r0, r14} 191129198Scognet#else 192129198Scognet ldr r2, .Lcurpcb 193129198Scognet ldr r2, [r2] 194129198Scognet#endif 195129198Scognet 196129198Scognet#ifdef DIAGNOSTIC 197129198Scognet teq r2, #0x00000000 198129198Scognet beq .Lfusupcbfault 199129198Scognet#endif 200129198Scognet 201129198Scognet adr r1, _C_LABEL(fusubailout) 202129198Scognet str r1, [r2, #PCB_ONFAULT] 203129198Scognet 204129198Scognet ldrbt r3, [r0], #1 205129198Scognet ldrbt ip, [r0] 206129198Scognet#ifdef __ARMEB__ 207129198Scognet orr r0, ip, r3, asl #8 208129198Scognet#else 209129198Scognet orr r0, r3, ip, asl #8 210129198Scognet#endif 211129198Scognet 212129198Scognet mov r1, #0x00000000 213129198Scognet str r1, [r2, #PCB_ONFAULT] 214137463Scognet RET 215129198Scognet 216129198ScognetLblock_userspace_access: 217129198Scognet .word _C_LABEL(block_userspace_access) 218129198Scognet 219129198Scognet .data 220129198Scognet .align 0 221129198Scognet .global _C_LABEL(block_userspace_access) 222129198Scognet_C_LABEL(block_userspace_access): 223129198Scognet .word 0 224129198Scognet .text 225129198Scognet 226129198Scognet/* 227129198Scognet * fubyte(caddr_t uaddr); 228129198Scognet * Fetch a byte from the user's address space. 229129198Scognet */ 230129198Scognet 231129198ScognetENTRY(fubyte) 232129198Scognet#ifdef MULTIPROCESSOR 233129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 234129198Scognet stmfd sp!, {r0, r14} 235129198Scognet bl _C_LABEL(cpu_number) 236129198Scognet ldr r2, .Lcpu_info 237129198Scognet ldr r2, [r2, r0, lsl #2] 238129198Scognet ldr r2, [r2, #CI_CURPCB] 239129198Scognet ldmfd sp!, {r0, r14} 240129198Scognet#else 241129198Scognet ldr r2, .Lcurpcb 242129198Scognet ldr r2, [r2] 243129198Scognet#endif 244129198Scognet 245129198Scognet#ifdef DIAGNOSTIC 246129198Scognet teq r2, #0x00000000 247129198Scognet beq .Lfusupcbfault 248129198Scognet#endif 249129198Scognet 250129198Scognet adr r1, .Lfusufault 251129198Scognet str r1, [r2, #PCB_ONFAULT] 252129198Scognet 253129198Scognet ldrbt r3, [r0] 254129198Scognet 255129198Scognet mov r1, #0x00000000 256129198Scognet str r1, [r2, #PCB_ONFAULT] 257129198Scognet mov r0, r3 258137463Scognet RET 259129198Scognet 260129198Scognet/* 261129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. 262129198Scognet */ 263129198Scognet 264129198Scognet.Lfusufault: 265129198Scognet mov r0, #0x00000000 266129198Scognet str r0, [r2, #PCB_ONFAULT] 267129198Scognet mvn r0, #0x00000000 268137463Scognet RET 269129198Scognet 270129198Scognet/* 271129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. This differs from 272129198Scognet * fusufault() in that trap() will recognise it and return immediately rather 273129198Scognet * than trying to page fault. 274129198Scognet */ 275129198Scognet 276129198Scognet/* label must be global as fault.c references it */ 277129198Scognet .global _C_LABEL(fusubailout) 278129198Scognet_C_LABEL(fusubailout): 279129198Scognet mov r0, #0x00000000 280129198Scognet str r0, [r2, #PCB_ONFAULT] 281129198Scognet mvn r0, #0x00000000 282137463Scognet RET 283129198Scognet 284129198Scognet#ifdef DIAGNOSTIC 285129198Scognet/* 286129198Scognet * Handle earlier faults from [fs]u*(), due to no pcb 287129198Scognet */ 288129198Scognet 289129198Scognet.Lfusupcbfault: 290129198Scognet mov r1, r0 291129198Scognet adr r0, fusupcbfaulttext 292129198Scognet b _C_LABEL(panic) 293129198Scognet 294129198Scognetfusupcbfaulttext: 295129198Scognet .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 296129198Scognet .align 0 297129198Scognet#endif 298129198Scognet 299129198Scognet/* 300129198Scognet * suword(caddr_t uaddr, int x); 301129198Scognet * Store an int in the user's address space. 302129198Scognet */ 303129198Scognet 304161734ScognetENTRY_NP(suword32) 305129198ScognetENTRY(suword) 306129198Scognet#ifdef MULTIPROCESSOR 307129198Scognet /* XXX Probably not appropriate for non-Hydra SMPs */ 308129198Scognet stmfd sp!, {r0, r1, r14} 309129198Scognet bl _C_LABEL(cpu_number) 310129198Scognet ldr r2, .Lcpu_info 311129198Scognet ldr r2, [r2, r0, lsl #2] 312129198Scognet ldr r2, [r2, #CI_CURPCB] 313129198Scognet ldmfd sp!, {r0, r1, r14} 314129198Scognet#else 315129198Scognet ldr r2, .Lcurpcb 316129198Scognet ldr r2, [r2] 317129198Scognet#endif 318129198Scognet 319129198Scognet#ifdef DIAGNOSTIC 320129198Scognet teq r2, #0x00000000 321129198Scognet beq .Lfusupcbfault 322129198Scognet#endif 323129198Scognet 324129198Scognet adr r3, .Lfusufault 325129198Scognet str r3, [r2, #PCB_ONFAULT] 326129198Scognet 327129198Scognet strt r1, [r0] 328129198Scognet 329129198Scognet mov r0, #0x00000000 330129198Scognet str r0, [r2, #PCB_ONFAULT] 331137463Scognet RET 332129198Scognet 333129198Scognet/* 334129198Scognet * suswintr(caddr_t uaddr, short x); 335129198Scognet * Store a short in the user's address space. Can be called during an 336129198Scognet * interrupt. 337129198Scognet */ 338129198Scognet 339129198ScognetENTRY(suswintr) 340129198Scognet ldr r2, Lblock_userspace_access 341129198Scognet ldr r2, [r2] 342129198Scognet teq r2, #0 343129198Scognet mvnne r0, #0x00000000 344137463Scognet RETne 345129198Scognet 346129198Scognet#ifdef MULTIPROCESSOR 347129198Scognet stmfd sp!, {r0, r1, r14} 348129198Scognet bl _C_LABEL(cpu_number) 349129198Scognet ldr r2, .Lcpu_info 350129198Scognet ldr r2, [r2, r0, lsl #2] 351129198Scognet ldr r2, [r2, #CI_CURPCB] 352129198Scognet ldmfd sp!, {r0, r1, r14} 353129198Scognet#else 354129198Scognet ldr r2, .Lcurpcb 355129198Scognet ldr r2, [r2] 356129198Scognet#endif 357129198Scognet 358129198Scognet#ifdef DIAGNOSTIC 359129198Scognet teq r2, #0x00000000 360129198Scognet beq .Lfusupcbfault 361129198Scognet#endif 362129198Scognet 363129198Scognet adr r3, _C_LABEL(fusubailout) 364129198Scognet str r3, [r2, #PCB_ONFAULT] 365129198Scognet 366129198Scognet#ifdef __ARMEB__ 367129198Scognet mov ip, r1, lsr #8 368129198Scognet strbt ip, [r0], #1 369129198Scognet#else 370129198Scognet strbt r1, [r0], #1 371129198Scognet mov r1, r1, lsr #8 372129198Scognet#endif 373129198Scognet strbt r1, [r0] 374129198Scognet 375129198Scognet mov r0, #0x00000000 376129198Scognet str r0, [r2, #PCB_ONFAULT] 377137463Scognet RET 378129198Scognet 379129198Scognet/* 380129198Scognet * susword(caddr_t uaddr, short x); 381129198Scognet * Store a short in the user's address space. 382129198Scognet */ 383129198Scognet 384129198ScognetENTRY(susword) 385129198Scognet#ifdef MULTIPROCESSOR 386129198Scognet stmfd sp!, {r0, r1, r14} 387129198Scognet bl _C_LABEL(cpu_number) 388129198Scognet ldr r2, .Lcpu_info 389129198Scognet ldr r2, [r2, r0, lsl #2] 390129198Scognet ldr r2, [r2, #CI_CURPCB] 391129198Scognet ldmfd sp!, {r0, r1, r14} 392129198Scognet#else 393129198Scognet ldr r2, .Lcurpcb 394129198Scognet ldr r2, [r2] 395129198Scognet#endif 396129198Scognet 397129198Scognet#ifdef DIAGNOSTIC 398129198Scognet teq r2, #0x00000000 399129198Scognet beq .Lfusupcbfault 400129198Scognet#endif 401129198Scognet 402129198Scognet adr r3, .Lfusufault 403129198Scognet str r3, [r2, #PCB_ONFAULT] 404129198Scognet 405129198Scognet#ifdef __ARMEB__ 406129198Scognet mov ip, r1, lsr #8 407129198Scognet strbt ip, [r0], #1 408129198Scognet#else 409129198Scognet strbt r1, [r0], #1 410129198Scognet mov r1, r1, lsr #8 411129198Scognet#endif 412129198Scognet strbt r1, [r0] 413129198Scognet 414129198Scognet mov r0, #0x00000000 415129198Scognet str r0, [r2, #PCB_ONFAULT] 416137463Scognet RET 417129198Scognet 418129198Scognet/* 419129198Scognet * subyte(caddr_t uaddr, char x); 420129198Scognet * Store a byte in the user's address space. 421129198Scognet */ 422129198Scognet 423129198ScognetENTRY(subyte) 424129198Scognet#ifdef MULTIPROCESSOR 425129198Scognet stmfd sp!, {r0, r1, r14} 426129198Scognet bl _C_LABEL(cpu_number) 427129198Scognet ldr r2, .Lcpu_info 428129198Scognet ldr r2, [r2, r0, lsl #2] 429129198Scognet ldr r2, [r2, #CI_CURPCB] 430129198Scognet ldmfd sp!, {r0, r1, r14} 431129198Scognet#else 432129198Scognet ldr r2, .Lcurpcb 433129198Scognet ldr r2, [r2] 434129198Scognet#endif 435129198Scognet 436129198Scognet 437129198Scognet#ifdef DIAGNOSTIC 438129198Scognet teq r2, #0x00000000 439129198Scognet beq .Lfusupcbfault 440129198Scognet#endif 441129198Scognet 442129198Scognet adr r3, .Lfusufault 443129198Scognet str r3, [r2, #PCB_ONFAULT] 444129198Scognet 445129198Scognet strbt r1, [r0] 446129198Scognet mov r0, #0x00000000 447129198Scognet str r0, [r2, #PCB_ONFAULT] 448137463Scognet RET 449