support.S revision 66486
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 66486 2000-09-30 17:48:44Z 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 66LEAF(suword, 1) 67#if 0 68 LDGP(pv) 69 70 ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ 71 cmpult a0, t0, t1 72 beq t1, fusufault 73 74 lda t0, fusufault /* trap faults */ 75 ldq t2, curproc 76 ldq t2, P_ADDR(t2) 77 stq t0, U_PCB_ONFAULT(t2) 78 79 stq a1, 0(a0) /* try the store */ 80 81 stq zero, U_PCB_ONFAULT(t2) /* clean up */ 82 83 mov zero, v0 84 RET 85#endif 86END(suword) 87 88LEAF(subyte, 1) 89#if 0 90 LDGP(pv) 91 92 ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ 93 cmpult a0, t0, t1 94 beq t1, fusufault 95 96 lda t0, fusufault /* trap faults */ 97 ldq t2, curproc 98 ldq t2, P_ADDR(t2) 99 stq t0, U_PCB_ONFAULT(t2) 100 101 zap a1, 0xfe, a1 /* mask off the byte to store */ 102 insbl a1, a0, a1 /* shift it to the right place */ 103 ldq_u t0, 0(a0) /* read the qword to store it in */ 104 mskbl t0, a0, t0 /* make a place for our byte */ 105 or a1, t0, a1 /* move it in */ 106 stq_u a1, 0(a0) /* and put the byte back */ 107 108 stq zero, U_PCB_ONFAULT(t2) /* clean up */ 109 110 mov zero, v0 111 RET 112#endif 113END(subyte) 114 115LEAF(fuword, 1) 116#if 0 117 LDGP(pv) 118 119 ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ 120 cmpult a0, t0, t1 121 beq t1, fusufault 122 123 lda t0, fusufault /* trap faults */ 124 ldq t2, curproc 125 ldq t2, P_ADDR(t2) 126 stq t0, U_PCB_ONFAULT(t2) 127 128 ldq v0, 0(a0) /* try the fetch */ 129 130 stq zero, U_PCB_ONFAULT(t2) /* clean up */ 131 132 RET 133#endif 134END(fuword) 135 136LEAF(fubyte, 1) 137#if 0 138 LDGP(pv) 139 140 ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ 141 cmpult a0, t0, t1 142 beq t1, fusufault 143 144 lda t0, fusufault /* trap faults */ 145 ldq t2, curproc 146 ldq t2, P_ADDR(t2) 147 stq t0, U_PCB_ONFAULT(t2) 148 149 ldq_u v0, 0(a0) /* get the word containing our byte */ 150 extbl v0, a0, v0 /* extract the byte */ 151 152 stq zero, U_PCB_ONFAULT(t2) /* clean up */ 153 154 RET 155#endif 156END(fubyte) 157 158LEAF(suibyte, 2) 159#if 0 160 ldiq v0, -1 161 RET 162#endif 163 END(suibyte) 164 165 LEAF(fusufault, 0) 166#if 0 167 ldq t0, curproc 168 ldq t0, P_ADDR(t0) 169 stq zero, U_PCB_ONFAULT(t0) 170 ldiq v0, -1 171 RET 172#endif 173END(fusufault) 174 175LEAF(fswintrberr, 0) 176XLEAF(fuswintr) /* XXX what is a 'word'? */ 177XLEAF(suswintr) /* XXX what is a 'word'? */ 178#if 0 179 LDGP(pv) 180 ldiq v0, -1 181 RET 182#endif 183END(fswintrberr) 184 185/**************************************************************************/ 186 187/* 188 * Copy a null-terminated string within the kernel's address space. 189 * If lenp is not NULL, store the number of chars copied in *lenp 190 * 191 * int copystr(char *from, char *to, size_t len, size_t *lenp); 192 */ 193LEAF(copystr, 4) 194 mov r14=in2 // r14 = i = len 195 cmp.eq p6,p0=r0,in2 196(p6) br.cond.spnt.few 2f // if (len == 0), bail out 197 1981: ld1 r15=[in0],1 // read one byte 199 ;; 200 st1 [in1]=r15,1 // write that byte 201 add in2=-1,in2 // len-- 202 ;; 203 cmp.eq p6,p0=r0,r15 204 cmp.ne p7,p0=r0,in2 205 ;; 206(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 207(p7) br.cond.sptk.few 1b // if (len != 0) copy more 208 2092: cmp.eq p6,p0=r0,in3 210(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 211 sub r14=in2,r14 // *lenp = (i - len) 212 ;; 213 st8 [in3]=r14 214 2153: cmp.eq p6,p0=r0,r15 216(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 217 218 mov ret0=ENAMETOOLONG // *from != '\0'; error. 219 br.ret.sptk.few rp 220 2214: mov ret0=0 // return 0. 222 br.ret.sptk.few rp 223 224END(copystr) 225 226NESTED(copyinstr, 4) 227 alloc loc0=ar.pfs,4,3,4,0 228 mov loc1=rp 229 230 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 231 ;; 232 cmp.ltu p6,p0=in0,loc2 // is in user space. 233 ;; 234(p6) br.cond.spnt.few copyerr // if it's not, error out. 235 movl r14=copyerr // set up fault handler. 236 add r15=GD_CURPROC,r13 // find curproc 237 ;; 238 ld8 r15=[r15] 239 ;; 240 add r15=P_ADDR,r15 // find pcb 241 ;; 242 ld8 r15=[r15] 243 ;; 244 add loc2=U_PCB_ONFAULT,r15 245 ;; 246 st8 [loc2]=r14 247 ;; 248 mov out0=in0 249 mov out1=in1 250 mov out2=in2 251 mov out3=in3 252 ;; 253 br.call.sptk.few rp=copystr // do the copy. 254 st8 [loc2]=r0 // kill the fault handler. 255 mov rp=loc1 // restore ra. 256 br.ret.sptk.few rp // ret0 left over from copystr 257 258END(copyinstr) 259 260NESTED(copyoutstr, 4) 261 alloc loc0=ar.pfs,4,3,4,0 262 mov loc1=rp 263 264 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 265 ;; 266 cmp.ltu p6,p0=in1,loc2 // is in user space. 267 ;; 268(p6) br.cond.spnt.few copyerr // if it's not, error out. 269 movl r14=copyerr // set up fault handler. 270 add r15=GD_CURPROC,r13 // find curproc 271 ;; 272 ld8 r15=[r15] 273 ;; 274 add r15=P_ADDR,r15 // find pcb 275 ;; 276 ld8 r15=[r15] 277 ;; 278 add loc2=U_PCB_ONFAULT,r15 279 ;; 280 st8 [loc2]=r14 281 ;; 282 mov out0=in0 283 mov out1=in1 284 mov out2=in2 285 mov out3=in3 286 ;; 287 br.call.sptk.few rp=copystr // do the copy. 288 st8 [loc2]=r0 // kill the fault handler. 289 mov rp=loc1 // restore ra. 290 br.ret.sptk.few rp // ret0 left over from copystr 291 292END(copyoutstr) 293 294/* 295 * Not the fastest bcopy in the world. 296 */ 297LEAF(bcopy, 3) 298XLEAF(ovbcopy) 299 300 mov ret0=r0 // return zero for copy{in,out} 301 ;; 302 cmp.le p6,p0=in2,r0 // bail if len <= 0 303(p6) br.ret.spnt.few rp 304 305 sub r14=in1,in0 ;; // check for overlap 306 cmp.ltu p6,p0=r14,in2 // dst-src < len 307(p6) br.cond.spnt.few 5f 308 309 extr.u r14=in0,0,3 // src & 7 310 extr.u r15=in1,0,3 ;; // dst & 7 311 cmp.eq p6,p0=r14,r15 // different alignment? 312(p6) br.cond.spnt.few 2f // branch if same alignment 313 3141: ld1 r14=[in0],1 ;; // copy bytewise 315 st1 [in1]=r14,1 316 add in2=-1,in2 ;; // len-- 317 cmp.ne p6,p0=r0,in2 318(p6) br.cond.dptk.few 1b // loop 319 br.ret.sptk.few rp // done 320 3212: cmp.eq p6,p0=r14,r0 // aligned? 322(p6) br.cond.sptk.few 4f 323 3243: ld1 r14=[in0],1 ;; // copy bytewise 325 st1 [in1]=r14,1 326 extr.u r15=in0,0,3 // src & 7 327 add in2=-1,in2 ;; // len-- 328 cmp.eq p6,p0=r0,in2 // done? 329 cmp.eq p7,p0=r0,r15 ;; // aligned now? 330(p6) br.ret.spnt.few rp // return if done 331(p7) br.cond.spnt.few 4f // go to main copy 332 br.cond.sptk.few 3b // more bytes to copy 333 334 // At this point, in2 is non-zero 335 3364: mov r14=8 ;; 337 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 338(p6) br.cond.spnt.few 1b // byte copy the end 339 ld8 r15=[in0],8 ;; // copy word 340 st8 [in1]=r15,8 341 add in2=-8,in2 ;; // len -= 8 342 cmp.ne p6,p0=r0,in2 // done? 343(p6) br.cond.spnt.few 4b // again 344 345 br.ret.sptk.few rp // return 346 347 // Don't bother optimising overlap case 348 3495: add in0=in0,in2 350 add in1=in1,in2 ;; 351 add in0=-1,in0 352 add in1=-1,in1 ;; 353 3546: ld1 r14=[in0],-1 ;; 355 st1 [in1]=r14,-1 356 add in2=-1,in2 ;; 357 cmp.ne p6,p0=r0,in2 358(p6) br.cond.spnt.few 6b 359 360 br.ret.sptk.few rp 361 362END(bcopy) 363 364LEAF(memcpy,3) 365 366 mov r14=in0 ;; 367 mov in0=in1 ;; 368 mov in1=r14 369 br.cond.sptk.few bcopy 370 371END(memcpy) 372 373NESTED(copyin, 3) 374 375 alloc loc0=ar.pfs,3,3,3,0 376 mov loc1=rp 377 378 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 379 ;; 380 cmp.ltu p6,p0=in0,loc2 // is in user space. 381 ;; 382(p6) br.cond.spnt.few copyerr // if it's not, error out. 383 movl r14=copyerr // set up fault handler. 384 add r15=GD_CURPROC,r13 // find curproc 385 ;; 386 ld8 r15=[r15] 387 ;; 388 add r15=P_ADDR,r15 // find pcb 389 ;; 390 ld8 r15=[r15] 391 ;; 392 add loc2=U_PCB_ONFAULT,r15 393 ;; 394 st8 [loc2]=r14 395 ;; 396 mov out0=in0 397 mov out1=in1 398 mov out2=in2 399 ;; 400 br.call.sptk.few rp=bcopy // do the copy. 401 st8 [loc2]=r0 // kill the fault handler. 402 mov rp=loc1 // restore ra. 403 br.ret.sptk.few rp // ret0 left over from bcopy 404 405END(copyin) 406 407NESTED(copyout, 3) 408 409 alloc loc0=ar.pfs,3,3,3,0 410 mov loc1=rp 411 412 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 413 ;; 414 cmp.ltu p6,p0=in1,loc2 // is in user space. 415 ;; 416(p6) br.cond.spnt.few copyerr // if it's not, error out. 417 movl r14=copyerr // set up fault handler. 418 add r15=GD_CURPROC,r13 // find curproc 419 ;; 420 ld8 r15=[r15] 421 ;; 422 add r15=P_ADDR,r15 // find pcb 423 ;; 424 ld8 r15=[r15] 425 ;; 426 add loc2=U_PCB_ONFAULT,r15 427 ;; 428 st8 [loc2]=r14 429 ;; 430 mov out0=in0 431 mov out1=in1 432 mov out2=in2 433 ;; 434 br.call.sptk.few rp=bcopy // do the copy. 435 st8 [loc2]=r0 // kill the fault handler. 436 mov rp=loc1 // restore ra. 437 br.ret.sptk.few rp // ret0 left over from bcopy 438 439END(copyout) 440 441LEAF(copyerr, 0) 442 443 add r14=GD_CURPROC,r13 ;; // find curproc 444 ld8 r14=[r14] ;; 445 add r14=P_ADDR,r14 ;; // curproc->p_addr 446 ld8 r14=[r14] ;; 447 add r14=U_PCB_ONFAULT,r14 ;; // &curproc->p_addr->u_pcb.pcb_onfault 448 st8 [r14]=r0 // reset fault handler 449 450 mov ret0=EFAULT // return EFAULT 451 br.ret.sptk.few rp 452 453END(copyerr) 454 455/**************************************************************************/ 456 457/* 458 * Kernel setjmp and longjmp. Rather minimalist. 459 * 460 * longjmp(label_t *a) 461 * will generate a "return (1)" from the last call to 462 * setjmp(label_t *a) 463 * by restoring registers from the stack, 464 */ 465 466 467LEAF(setjmp, 1) 468#if 0 469 LDGP(pv) 470 471 stq ra, (0 * 8)(a0) /* return address */ 472 stq s0, (1 * 8)(a0) /* callee-saved registers */ 473 stq s1, (2 * 8)(a0) 474 stq s2, (3 * 8)(a0) 475 stq s3, (4 * 8)(a0) 476 stq s4, (5 * 8)(a0) 477 stq s5, (6 * 8)(a0) 478 stq s6, (7 * 8)(a0) 479 stq sp, (8 * 8)(a0) 480 481 ldiq t0, 0xbeeffedadeadbabe /* set magic number */ 482 stq t0, (9 * 8)(a0) 483 484 mov zero, v0 /* return zero */ 485 RET 486#endif 487END(setjmp) 488 489LEAF(longjmp, 1) 490#if 0 491 LDGP(pv) 492 493 ldiq t0, 0xbeeffedadeadbabe /* check magic number */ 494 ldq t1, (9 * 8)(a0) 495 cmpeq t0, t1, t0 496 beq t0, longjmp_botch /* if bad, punt */ 497 498 ldq ra, (0 * 8)(a0) /* return address */ 499 ldq s0, (1 * 8)(a0) /* callee-saved registers */ 500 ldq s1, (2 * 8)(a0) 501 ldq s2, (3 * 8)(a0) 502 ldq s3, (4 * 8)(a0) 503 ldq s4, (5 * 8)(a0) 504 ldq s5, (6 * 8)(a0) 505 ldq s6, (7 * 8)(a0) 506 ldq sp, (8 * 8)(a0) 507 508 ldiq v0, 1 509 RET 510 511longjmp_botch: 512 lda a0, longjmp_botchmsg 513 mov ra, a1 514 CALL(panic) 515 call_pal PAL_bugchk 516 517 .data 518longjmp_botchmsg: 519 .asciz "longjmp botch from %p" 520 .text 521#endif 522END(longjmp) 523