support.S revision 66633
1/*- 2 * Copyright (c) 1998 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/ia64/ia64/support.S 66633 2000-10-04 17:53:03Z dfr $ 27 */ 28/* 29 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 30 * All rights reserved. 31 * 32 * Author: Chris G. Demetriou 33 * 34 * Permission to use, copy, modify and distribute this software and 35 * its documentation is hereby granted, provided that both the copyright 36 * notice and this permission notice appear in all copies of the 37 * software, derivative works or modified versions, and any portions 38 * thereof, and that both notices appear in supporting documentation. 39 * 40 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 41 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 42 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 43 * 44 * Carnegie Mellon requests users of this software to return to 45 * 46 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 47 * School of Computer Science 48 * Carnegie Mellon University 49 * Pittsburgh PA 15213-3890 50 * 51 * any improvements or extensions that they make and grant Carnegie the 52 * rights to redistribute these changes. 53 */ 54 55#include <machine/asm.h> 56#include <assym.s> 57 58 .text 59 60/**************************************************************************/ 61 62/* 63 * fu{byte,word} : fetch a byte (word) from user memory 64 */ 65 66ENTRY(suword, 2) 67 68 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 69 cmp.geu p6,p0=in0,r14 70(p6) br.dpnt.few fusufault 71 72 movl r14=fusufault // set up fault handler. 73 add r15=GD_CURPROC,r13 // find curproc 74 ;; 75 ld8 r15=[r15] 76 ;; 77 add r15=P_ADDR,r15 // find pcb 78 ;; 79 ld8 r15=[r15] 80 ;; 81 add r15=U_PCB_ONFAULT,r15 82 ;; 83 st8 [r15]=r14 84 ;; 85 st8.rel [in0]=in1 // try the store 86 ;; 87 st8 [r15]=r0 // clean up 88 89 mov ret0=r0 90 br.ret.sptk.few rp 91 92END(suword) 93 94ENTRY(subyte, 2) 95 96 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 97 cmp.geu p6,p0=in0,r14 98(p6) br.dpnt.few fusufault 99 100 movl r14=fusufault // set up fault handler. 101 add r15=GD_CURPROC,r13 // find curproc 102 ;; 103 ld8 r15=[r15] 104 ;; 105 add r15=P_ADDR,r15 // find pcb 106 ;; 107 ld8 r15=[r15] 108 ;; 109 add r15=U_PCB_ONFAULT,r15 110 ;; 111 st8 [r15]=r14 112 ;; 113 st1.rel [in0]=in1 // try the store 114 ;; 115 st8 [r15]=r0 // clean up 116 117 mov ret0=r0 118 br.ret.sptk.few rp 119 120END(subyte) 121 122ENTRY(fuword, 1) 123 124 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 125 cmp.geu p6,p0=in0,r14 126(p6) br.dpnt.few fusufault 127 128 movl r14=fusufault // set up fault handler. 129 add r15=GD_CURPROC,r13 // find curproc 130 ;; 131 ld8 r15=[r15] 132 ;; 133 add r15=P_ADDR,r15 // find pcb 134 ;; 135 ld8 r15=[r15] 136 ;; 137 add r15=U_PCB_ONFAULT,r15 138 ;; 139 st8 [r15]=r14 140 ;; 141 ld8.acq ret0=[in0] // try the fetch 142 ;; 143 st8 [r15]=r0 // clean up 144 145 br.ret.sptk.few rp 146 147END(fuword) 148 149ENTRY(fubyte, 1) 150 151 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 152 cmp.geu p6,p0=in0,r14 153(p6) br.dpnt.few fusufault 154 155 movl r14=fusufault // set up fault handler. 156 add r15=GD_CURPROC,r13 // find curproc 157 ;; 158 ld8 r15=[r15] 159 ;; 160 add r15=P_ADDR,r15 // find pcb 161 ;; 162 ld8 r15=[r15] 163 ;; 164 add r15=U_PCB_ONFAULT,r15 165 ;; 166 st8 [r15]=r14 167 ;; 168 ld1.acq ret0=[in0] // try the fetch 169 ;; 170 st8 [r15]=r0 // clean up 171 172 br.ret.sptk.few rp 173 174END(fubyte) 175 176ENTRY(suibyte, 2) 177 mov ret0=-1 178 br.ret.sptk.few rp 179END(suibyte) 180 181ENTRY(fusufault, 0) 182 st8 [r15]=r0 ;; // r15 points at onfault 183 mov ret0=r0 184 br.ret.sptk.few rp 185END(fusufault) 186 187ENTRY(fswintrberr, 0) 188XENTRY(fuswintr) /* XXX what is a 'word'? */ 189XENTRY(suswintr) /* XXX what is a 'word'? */ 190 mov ret0=-1 191 br.ret.sptk.few rp 192END(fswintrberr) 193 194/**************************************************************************/ 195 196/* 197 * Copy a null-terminated string within the kernel's address space. 198 * If lenp is not NULL, store the number of chars copied in *lenp 199 * 200 * int copystr(char *from, char *to, size_t len, size_t *lenp); 201 */ 202ENTRY(copystr, 4) 203 mov r14=in2 // r14 = i = len 204 cmp.eq p6,p0=r0,in2 205(p6) br.cond.spnt.few 2f // if (len == 0), bail out 206 2071: ld1 r15=[in0],1 // read one byte 208 ;; 209 st1 [in1]=r15,1 // write that byte 210 add in2=-1,in2 // len-- 211 ;; 212 cmp.eq p6,p0=r0,r15 213 cmp.ne p7,p0=r0,in2 214 ;; 215(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 216(p7) br.cond.sptk.few 1b // if (len != 0) copy more 217 2182: cmp.eq p6,p0=r0,in3 219(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 220 sub r14=in2,r14 // *lenp = (i - len) 221 ;; 222 st8 [in3]=r14 223 2243: cmp.eq p6,p0=r0,r15 225(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 226 227 mov ret0=ENAMETOOLONG // *from != '\0'; error. 228 br.ret.sptk.few rp 229 2304: mov ret0=0 // return 0. 231 br.ret.sptk.few rp 232 233END(copystr) 234 235ENTRY(copyinstr, 4) 236 alloc loc0=ar.pfs,4,3,4,0 237 mov loc1=rp 238 239 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 240 ;; 241 cmp.geu p6,p0=in0,loc2 // is in user space. 242 ;; 243(p6) br.cond.spnt.few copyerr // if it's not, error out. 244 movl r14=copyerr // set up fault handler. 245 add r15=GD_CURPROC,r13 // find curproc 246 ;; 247 ld8 r15=[r15] 248 ;; 249 add r15=P_ADDR,r15 // find pcb 250 ;; 251 ld8 r15=[r15] 252 ;; 253 add loc2=U_PCB_ONFAULT,r15 254 ;; 255 st8 [loc2]=r14 256 ;; 257 mov out0=in0 258 mov out1=in1 259 mov out2=in2 260 mov out3=in3 261 ;; 262 br.call.sptk.few rp=copystr // do the copy. 263 st8 [loc2]=r0 // kill the fault handler. 264 mov rp=loc1 // restore ra. 265 br.ret.sptk.few rp // ret0 left over from copystr 266 267END(copyinstr) 268 269ENTRY(copyoutstr, 4) 270 alloc loc0=ar.pfs,4,3,4,0 271 mov loc1=rp 272 273 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 274 ;; 275 cmp.geu p6,p0=in1,loc2 // is in user space. 276 ;; 277(p6) br.cond.spnt.few copyerr // if it's not, error out. 278 movl r14=copyerr // set up fault handler. 279 add r15=GD_CURPROC,r13 // find curproc 280 ;; 281 ld8 r15=[r15] 282 ;; 283 add r15=P_ADDR,r15 // find pcb 284 ;; 285 ld8 r15=[r15] 286 ;; 287 add loc2=U_PCB_ONFAULT,r15 288 ;; 289 st8 [loc2]=r14 290 ;; 291 mov out0=in0 292 mov out1=in1 293 mov out2=in2 294 mov out3=in3 295 ;; 296 br.call.sptk.few rp=copystr // do the copy. 297 st8 [loc2]=r0 // kill the fault handler. 298 mov rp=loc1 // restore ra. 299 br.ret.sptk.few rp // ret0 left over from copystr 300 301END(copyoutstr) 302 303/* 304 * Not the fastest bcopy in the world. 305 */ 306ENTRY(bcopy, 3) 307XENTRY(ovbcopy) 308 309 mov ret0=r0 // return zero for copy{in,out} 310 ;; 311 cmp.le p6,p0=in2,r0 // bail if len <= 0 312(p6) br.ret.spnt.few rp 313 314 sub r14=in1,in0 ;; // check for overlap 315 cmp.ltu p6,p0=r14,in2 // dst-src < len 316(p6) br.cond.spnt.few 5f 317 318 extr.u r14=in0,0,3 // src & 7 319 extr.u r15=in1,0,3 ;; // dst & 7 320 cmp.eq p6,p0=r14,r15 // different alignment? 321(p6) br.cond.spnt.few 2f // branch if same alignment 322 3231: ld1 r14=[in0],1 ;; // copy bytewise 324 st1 [in1]=r14,1 325 add in2=-1,in2 ;; // len-- 326 cmp.ne p6,p0=r0,in2 327(p6) br.cond.dptk.few 1b // loop 328 br.ret.sptk.few rp // done 329 3302: cmp.eq p6,p0=r14,r0 // aligned? 331(p6) br.cond.sptk.few 4f 332 3333: ld1 r14=[in0],1 ;; // copy bytewise 334 st1 [in1]=r14,1 335 extr.u r15=in0,0,3 // src & 7 336 add in2=-1,in2 ;; // len-- 337 cmp.eq p6,p0=r0,in2 // done? 338 cmp.eq p7,p0=r0,r15 ;; // aligned now? 339(p6) br.ret.spnt.few rp // return if done 340(p7) br.cond.spnt.few 4f // go to main copy 341 br.cond.sptk.few 3b // more bytes to copy 342 343 // At this point, in2 is non-zero 344 3454: mov r14=8 ;; 346 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 347(p6) br.cond.spnt.few 1b // byte copy the end 348 ld8 r15=[in0],8 ;; // copy word 349 st8 [in1]=r15,8 350 add in2=-8,in2 ;; // len -= 8 351 cmp.ne p6,p0=r0,in2 // done? 352(p6) br.cond.spnt.few 4b // again 353 354 br.ret.sptk.few rp // return 355 356 // Don't bother optimising overlap case 357 3585: add in0=in0,in2 359 add in1=in1,in2 ;; 360 add in0=-1,in0 361 add in1=-1,in1 ;; 362 3636: ld1 r14=[in0],-1 ;; 364 st1 [in1]=r14,-1 365 add in2=-1,in2 ;; 366 cmp.ne p6,p0=r0,in2 367(p6) br.cond.spnt.few 6b 368 369 br.ret.sptk.few rp 370 371END(bcopy) 372 373ENTRY(memcpy,3) 374 375 mov r14=in0 ;; 376 mov in0=in1 ;; 377 mov in1=r14 378 br.cond.sptk.few bcopy 379 380END(memcpy) 381 382ENTRY(copyin, 3) 383 384 alloc loc0=ar.pfs,3,3,3,0 385 mov loc1=rp 386 387 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 388 ;; 389 cmp.ltu p6,p0=in0,loc2 // is in user space. 390 ;; 391(p6) br.cond.spnt.few copyerr // if it's not, error out. 392 movl r14=copyerr // set up fault handler. 393 add r15=GD_CURPROC,r13 // find curproc 394 ;; 395 ld8 r15=[r15] 396 ;; 397 add r15=P_ADDR,r15 // find pcb 398 ;; 399 ld8 r15=[r15] 400 ;; 401 add loc2=U_PCB_ONFAULT,r15 402 ;; 403 st8 [loc2]=r14 404 ;; 405 mov out0=in0 406 mov out1=in1 407 mov out2=in2 408 ;; 409 br.call.sptk.few rp=bcopy // do the copy. 410 st8 [loc2]=r0 // kill the fault handler. 411 mov rp=loc1 // restore ra. 412 br.ret.sptk.few rp // ret0 left over from bcopy 413 414END(copyin) 415 416ENTRY(copyout, 3) 417 418 alloc loc0=ar.pfs,3,3,3,0 419 mov loc1=rp 420 421 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 422 ;; 423 cmp.ltu p6,p0=in1,loc2 // is in user space. 424 ;; 425(p6) br.cond.spnt.few copyerr // if it's not, error out. 426 movl r14=copyerr // set up fault handler. 427 add r15=GD_CURPROC,r13 // find curproc 428 ;; 429 ld8 r15=[r15] 430 ;; 431 add r15=P_ADDR,r15 // find pcb 432 ;; 433 ld8 r15=[r15] 434 ;; 435 add loc2=U_PCB_ONFAULT,r15 436 ;; 437 st8 [loc2]=r14 438 ;; 439 mov out0=in0 440 mov out1=in1 441 mov out2=in2 442 ;; 443 br.call.sptk.few rp=bcopy // do the copy. 444 st8 [loc2]=r0 // kill the fault handler. 445 mov rp=loc1 // restore ra. 446 br.ret.sptk.few rp // ret0 left over from bcopy 447 448END(copyout) 449 450ENTRY(copyerr, 0) 451 452 add r14=GD_CURPROC,r13 ;; // find curproc 453 ld8 r14=[r14] ;; 454 add r14=P_ADDR,r14 ;; // curproc->p_addr 455 ld8 r14=[r14] ;; 456 add r14=U_PCB_ONFAULT,r14 ;; // &curproc->p_addr->u_pcb.pcb_onfault 457 st8 [r14]=r0 // reset fault handler 458 459 mov ret0=EFAULT // return EFAULT 460 br.ret.sptk.few rp 461 462END(copyerr) 463 464/**************************************************************************/ 465 466/* 467 * Kernel setjmp and longjmp. Rather minimalist. 468 * 469 * longjmp(label_t *a) 470 * will generate a "return (1)" from the last call to 471 * setjmp(label_t *a) 472 * by restoring registers from the stack, 473 */ 474 475 476ENTRY(setjmp, 1) 477#if 0 478 LDGP(pv) 479 480 stq ra, (0 * 8)(a0) /* return address */ 481 stq s0, (1 * 8)(a0) /* callee-saved registers */ 482 stq s1, (2 * 8)(a0) 483 stq s2, (3 * 8)(a0) 484 stq s3, (4 * 8)(a0) 485 stq s4, (5 * 8)(a0) 486 stq s5, (6 * 8)(a0) 487 stq s6, (7 * 8)(a0) 488 stq sp, (8 * 8)(a0) 489 490 ldiq t0, 0xbeeffedadeadbabe /* set magic number */ 491 stq t0, (9 * 8)(a0) 492 493 mov zero, v0 /* return zero */ 494 RET 495#endif 496END(setjmp) 497 498ENTRY(longjmp, 1) 499#if 0 500 LDGP(pv) 501 502 ldiq t0, 0xbeeffedadeadbabe /* check magic number */ 503 ldq t1, (9 * 8)(a0) 504 cmpeq t0, t1, t0 505 beq t0, longjmp_botch /* if bad, punt */ 506 507 ldq ra, (0 * 8)(a0) /* return address */ 508 ldq s0, (1 * 8)(a0) /* callee-saved registers */ 509 ldq s1, (2 * 8)(a0) 510 ldq s2, (3 * 8)(a0) 511 ldq s3, (4 * 8)(a0) 512 ldq s4, (5 * 8)(a0) 513 ldq s5, (6 * 8)(a0) 514 ldq s6, (7 * 8)(a0) 515 ldq sp, (8 * 8)(a0) 516 517 ldiq v0, 1 518 RET 519 520longjmp_botch: 521 lda a0, longjmp_botchmsg 522 mov ra, a1 523 CALL(panic) 524 call_pal PAL_bugchk 525 526 .data 527longjmp_botchmsg: 528 .asciz "longjmp botch from %p" 529 .text 530#endif 531END(longjmp) 532