support.S revision 139790
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 139790 2005-01-06 22:18:23Z imp $ 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 <machine/ia64_cpu.h> 57#include <assym.s> 58 59 .text 60 61/* 62 * ia64_change_mode: change mode to/from physical mode 63 * 64 * Arguments: 65 * r14 psr for desired mode 66 * 67 * Modifies: 68 * r15-r19 scratch 69 * ar.bsp tranlated to new mode 70 */ 71ENTRY_NOPROFILE(ia64_change_mode, 0) 72 rsm psr.i | psr.ic 73 mov r19=ar.rsc // save rsc while we change mode 74 tbit.nz p6,p7=r14,17 // physical or virtual ? 75 ;; 76 mov ar.rsc=0 // turn off RSE 77(p6) mov r15=7 // RR base for virtual addresses 78(p7) mov r15=0 // RR base for physical addresses 79 flushrs // no dirty registers please 80 srlz.i 81 ;; 82 mov r16=ar.bsp 83 mov r17=rp 84 mov r18=ar.rnat 85 ;; 86 dep r16=r15,r16,61,3 // new address of ar.bsp 87 dep r17=r15,r17,61,3 // new address of rp 88 dep sp=r15,sp,61,3 // new address of sp 89 ;; 90 mov ar.bspstore=r16 91 mov rp=r17 92 ;; 931: mov r16=ip 94 mov ar.rnat=r18 95 mov cr.ipsr=r14 // psr for new mode 96 ;; 97 add r16=2f-1b,r16 // address to rfi to 98 ;; 99 dep r16=r15,r16,61,3 // new mode address for rfi 100 ;; 101 mov cr.iip=r16 // setup for rfi 102 mov cr.ifs=r0 103 ;; 104 rfi 105 1062: mov ar.rsc=r19 // restore ar.rsc 107 br.ret.sptk.few rp // now in new mode 108END(ia64_change_mode) 109 110/* 111 * ia64_physical_mode: change mode to physical mode 112 * 113 * Return: 114 * ret0 psr to restore 115 * 116 * Modifies: 117 * r15-r18 scratch 118 * ar.bsp tranlated to physical mode 119 * psr.i cleared 120 */ 121ENTRY(ia64_physical_mode, 0) 122 mov r14=psr 123 mov ret0=psr 124 movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) 125 movl r16=IA64_PSR_BN 126 ;; 127 andcm r14=r14,r15 // clear various xT bits 128 ;; 129 or r14=r14,r16 // make sure BN=1 130 or ret0=ret0,r16 // make sure BN=1 131 132 br.cond.sptk.many ia64_change_mode 133END(ia64_physical_mode) 134 135/* 136 * ia64_call_efi_physical: call an EFI procedure in physical mode 137 * 138 * Arguments: 139 * in0 Address of EFI procedure descriptor 140 * in1-in5 Arguments to EFI procedure 141 * 142 * Return: 143 * ret0-ret3 return values from EFI 144 * 145 */ 146ENTRY(ia64_call_efi_physical, 6) 147 .prologue 148 .regstk 6,4,5,0 149 .save ar.pfs,loc0 150 alloc loc0=ar.pfs,6,4,5,0 151 ;; 152 .save rp,loc1 153 mov loc1=rp 154 ;; 155 .body 156 br.call.sptk.many rp=ia64_physical_mode 157 ;; 158 mov loc2=r8 // psr to restore mode 159 mov loc3=gp // save kernel gp 160 ld8 r14=[in0],8 // function address 161 ;; 162 mov out0=in1 163 mov out1=in2 164 mov out2=in3 165 mov out3=in4 166 mov out4=in5 167 ld8 gp=[in0] // function gp value 168 ;; 169 mov b6=r14 170 ;; 171 br.call.sptk.many rp=b6 // call EFI procedure 172 mov gp=loc3 // restore kernel gp 173 ;; 174 mov r14=loc2 // psr to restore mode 175 br.call.sptk.many rp=ia64_change_mode 176 ;; 177 mov rp=loc1 178 mov ar.pfs=loc0 179 ;; 180 br.ret.sptk.many rp 181END(ia64_call_efi_physical) 182 183/**************************************************************************/ 184 185ENTRY(fusufault, 0) 186{ .mib 187 st8.rel [r15]=r0 // Clear onfault. 188 add ret0=-1,r0 189 br.ret.sptk rp 190 ;; 191} 192END(fusufault) 193 194/* 195 * casuptr(intptr_t *p, intptr_t old, intptr_t new) 196 * Perform a compare-exchange in user space. 197 */ 198ENTRY(casuptr, 3) 199{ .mlx 200 add r15=PC_CURTHREAD,r13 201 movl r14=VM_MAX_ADDRESS 202 ;; 203} 204{ .mib 205 ld8 r15=[r15] // r15 = curthread 206 cmp.geu p6,p0=in0,r14 207(p6) br.dpnt.few 1f 208 ;; 209} 210{ .mlx 211 add r15=TD_PCB,r15 212 movl r14=fusufault 213 ;; 214} 215{ .mmi 216 ld8 r15=[r15] // r15 = PCB 217 ;; 218 mov ar.ccv=in1 219 add r15=PCB_ONFAULT,r15 220 ;; 221} 222{ .mmi 223 st8 [r15]=r14 // Set onfault 224 ;; 225 cmpxchg8.rel ret0=[in0],in2,ar.ccv 226 nop 0 227 ;; 228} 229{ .mfb 230 st8.rel [r15]=r0 // Clear onfault 231 nop 0 232 br.ret.sptk rp 233 ;; 234} 2351: 236{ .mfb 237 add ret0=-1,r0 238 nop 0 239 br.ret.sptk rp 240 ;; 241} 242END(casuptr) 243 244/* 245 * subyte(void *addr, int byte) 246 * suword16(void *addr, int word) 247 * suword32(void *addr, int word) 248 * suword64|suword(void *addr, long word) 249 * Store in user space 250 */ 251 252ENTRY(subyte, 2) 253{ .mlx 254 add r15=PC_CURTHREAD,r13 255 movl r14=VM_MAX_ADDRESS 256 ;; 257} 258{ .mib 259 ld8 r15=[r15] // r15 = curthread 260 cmp.geu p6,p0=in0,r14 261(p6) br.dpnt.few 1f 262 ;; 263} 264{ .mlx 265 add r15=TD_PCB,r15 266 movl r14=fusufault 267 ;; 268} 269{ .mmi 270 ld8 r15=[r15] // r15 = PCB 271 ;; 272 nop 0 273 add r15=PCB_ONFAULT,r15 274 ;; 275} 276{ .mmi 277 st8 [r15]=r14 // Set onfault 278 ;; 279 st1.rel [in0]=in1 280 nop 0 281 ;; 282} 283{ .mib 284 st8.rel [r15]=r0 // Clear onfault 285 mov ret0=r0 286 br.ret.sptk rp 287 ;; 288} 2891: 290{ .mfb 291 add ret0=-1,r0 292 nop 0 293 br.ret.sptk rp 294 ;; 295} 296END(subyte) 297 298ENTRY(suword16, 2) 299{ .mlx 300 add r15=PC_CURTHREAD,r13 301 movl r14=VM_MAX_ADDRESS 302 ;; 303} 304{ .mib 305 ld8 r15=[r15] // r15 = curthread 306 cmp.geu p6,p0=in0,r14 307(p6) br.dpnt.few 1f 308 ;; 309} 310{ .mlx 311 add r15=TD_PCB,r15 312 movl r14=fusufault 313 ;; 314} 315{ .mmi 316 ld8 r15=[r15] // r15 = PCB 317 ;; 318 nop 0 319 add r15=PCB_ONFAULT,r15 320 ;; 321} 322{ .mmi 323 st8 [r15]=r14 // Set onfault 324 ;; 325 st2.rel [in0]=in1 326 nop 0 327 ;; 328} 329{ .mib 330 st8.rel [r15]=r0 // Clear onfault 331 mov ret0=r0 332 br.ret.sptk rp 333 ;; 334} 3351: 336{ .mfb 337 add ret0=-1,r0 338 nop 0 339 br.ret.sptk rp 340 ;; 341} 342END(suword16) 343 344ENTRY(suword32, 2) 345{ .mlx 346 add r15=PC_CURTHREAD,r13 347 movl r14=VM_MAX_ADDRESS 348 ;; 349} 350{ .mib 351 ld8 r15=[r15] // r15 = curthread 352 cmp.geu p6,p0=in0,r14 353(p6) br.dpnt.few 1f 354 ;; 355} 356{ .mlx 357 add r15=TD_PCB,r15 358 movl r14=fusufault 359 ;; 360} 361{ .mmi 362 ld8 r15=[r15] // r15 = PCB 363 ;; 364 nop 0 365 add r15=PCB_ONFAULT,r15 366 ;; 367} 368{ .mmi 369 st8 [r15]=r14 // Set onfault 370 ;; 371 st4.rel [in0]=in1 372 nop 0 373 ;; 374} 375{ .mib 376 st8.rel [r15]=r0 // Clear onfault 377 mov ret0=r0 378 br.ret.sptk rp 379 ;; 380} 3811: 382{ .mfb 383 add ret0=-1,r0 384 nop 0 385 br.ret.sptk rp 386 ;; 387} 388END(suword32) 389 390ENTRY(suword64, 2) 391XENTRY(suword) 392{ .mlx 393 add r15=PC_CURTHREAD,r13 394 movl r14=VM_MAX_ADDRESS 395 ;; 396} 397{ .mib 398 ld8 r15=[r15] // r15 = curthread 399 cmp.geu p6,p0=in0,r14 400(p6) br.dpnt.few 1f 401 ;; 402} 403{ .mlx 404 add r15=TD_PCB,r15 405 movl r14=fusufault 406 ;; 407} 408{ .mmi 409 ld8 r15=[r15] // r15 = PCB 410 ;; 411 nop 0 412 add r15=PCB_ONFAULT,r15 413 ;; 414} 415{ .mmi 416 st8 [r15]=r14 // Set onfault 417 ;; 418 st8.rel [in0]=in1 419 nop 0 420 ;; 421} 422{ .mib 423 st8.rel [r15]=r0 // Clear onfault 424 mov ret0=r0 425 br.ret.sptk rp 426 ;; 427} 4281: 429{ .mfb 430 add ret0=-1,r0 431 nop 0 432 br.ret.sptk rp 433 ;; 434} 435END(suword64) 436 437/* 438 * fubyte(void *addr, int byte) 439 * fuword16(void *addr, int word) 440 * fuword32(void *addr, int word) 441 * fuword64|fuword(void *addr, long word) 442 * Fetch from user space 443 */ 444 445ENTRY(fubyte, 1) 446{ .mlx 447 add r15=PC_CURTHREAD,r13 448 movl r14=VM_MAX_ADDRESS 449 ;; 450} 451{ .mib 452 ld8 r15=[r15] // r15 = curthread 453 cmp.geu p6,p0=in0,r14 454(p6) br.dpnt.few 1f 455 ;; 456} 457{ .mlx 458 add r15=TD_PCB,r15 459 movl r14=fusufault 460 ;; 461} 462{ .mmi 463 ld8 r15=[r15] // r15 = PCB 464 ;; 465 nop 0 466 add r15=PCB_ONFAULT,r15 467 ;; 468} 469{ .mmi 470 st8 [r15]=r14 // Set onfault 471 ;; 472 mf 473 nop 0 474 ;; 475} 476{ .mmb 477 ld1 ret0=[in0] 478 st8.rel [r15]=r0 // Clear onfault 479 br.ret.sptk rp 480 ;; 481} 4821: 483{ .mfb 484 add ret0=-1,r0 485 nop 0 486 br.ret.sptk rp 487 ;; 488} 489END(fubyte) 490 491ENTRY(fuword16, 2) 492{ .mlx 493 add r15=PC_CURTHREAD,r13 494 movl r14=VM_MAX_ADDRESS 495 ;; 496} 497{ .mib 498 ld8 r15=[r15] // r15 = curthread 499 cmp.geu p6,p0=in0,r14 500(p6) br.dpnt.few 1f 501 ;; 502} 503{ .mlx 504 add r15=TD_PCB,r15 505 movl r14=fusufault 506 ;; 507} 508{ .mmi 509 ld8 r15=[r15] // r15 = PCB 510 ;; 511 nop 0 512 add r15=PCB_ONFAULT,r15 513 ;; 514} 515{ .mmi 516 st8 [r15]=r14 // Set onfault 517 ;; 518 mf 519 nop 0 520 ;; 521} 522{ .mmb 523 ld2 ret0=[in0] 524 st8.rel [r15]=r0 // Clear onfault 525 br.ret.sptk rp 526 ;; 527} 5281: 529{ .mfb 530 add ret0=-1,r0 531 nop 0 532 br.ret.sptk rp 533 ;; 534} 535END(fuword16) 536 537ENTRY(fuword32, 2) 538{ .mlx 539 add r15=PC_CURTHREAD,r13 540 movl r14=VM_MAX_ADDRESS 541 ;; 542} 543{ .mib 544 ld8 r15=[r15] // r15 = curthread 545 cmp.geu p6,p0=in0,r14 546(p6) br.dpnt.few 1f 547 ;; 548} 549{ .mlx 550 add r15=TD_PCB,r15 551 movl r14=fusufault 552 ;; 553} 554{ .mmi 555 ld8 r15=[r15] // r15 = PCB 556 ;; 557 nop 0 558 add r15=PCB_ONFAULT,r15 559 ;; 560} 561{ .mmi 562 st8 [r15]=r14 // Set onfault 563 ;; 564 mf 565 nop 0 566 ;; 567} 568{ .mmb 569 ld4 ret0=[in0] 570 st8.rel [r15]=r0 // Clear onfault 571 br.ret.sptk rp 572 ;; 573} 5741: 575{ .mfb 576 add ret0=-1,r0 577 nop 0 578 br.ret.sptk rp 579 ;; 580} 581END(fuword32) 582 583ENTRY(fuword64, 2) 584XENTRY(fuword) 585{ .mlx 586 add r15=PC_CURTHREAD,r13 587 movl r14=VM_MAX_ADDRESS 588 ;; 589} 590{ .mib 591 ld8 r15=[r15] // r15 = curthread 592 cmp.geu p6,p0=in0,r14 593(p6) br.dpnt.few 1f 594 ;; 595} 596{ .mlx 597 add r15=TD_PCB,r15 598 movl r14=fusufault 599 ;; 600} 601{ .mmi 602 ld8 r15=[r15] // r15 = PCB 603 ;; 604 nop 0 605 add r15=PCB_ONFAULT,r15 606 ;; 607} 608{ .mmi 609 st8 [r15]=r14 // Set onfault 610 ;; 611 mf 612 nop 0 613 ;; 614} 615{ .mmb 616 ld8 ret0=[in0] 617 st8.rel [r15]=r0 // Clear onfault 618 br.ret.sptk rp 619 ;; 620} 6211: 622{ .mfb 623 add ret0=-1,r0 624 nop 0 625 br.ret.sptk rp 626 ;; 627} 628END(fuword64) 629 630/* 631 * fuswintr(void *addr) 632 * suswintr(void *addr) 633 */ 634 635ENTRY(fuswintr, 1) 636{ .mfb 637 add ret0=-1,r0 638 nop 0 639 br.ret.sptk rp 640 ;; 641} 642END(fuswintr) 643 644ENTRY(suswintr, 0) 645{ .mfb 646 add ret0=-1,r0 647 nop 0 648 br.ret.sptk rp 649 ;; 650} 651END(suswintr) 652 653/**************************************************************************/ 654 655/* 656 * Copy a null-terminated string within the kernel's address space. 657 * If lenp is not NULL, store the number of chars copied in *lenp 658 * 659 * int copystr(char *from, char *to, size_t len, size_t *lenp); 660 */ 661ENTRY(copystr, 4) 662 mov r14=in2 // r14 = i = len 663 cmp.eq p6,p0=r0,in2 664(p6) br.cond.spnt.few 2f // if (len == 0), bail out 665 6661: ld1 r15=[in0],1 // read one byte 667 ;; 668 st1 [in1]=r15,1 // write that byte 669 add in2=-1,in2 // len-- 670 ;; 671 cmp.eq p6,p0=r0,r15 672 cmp.ne p7,p0=r0,in2 673 ;; 674(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 675(p7) br.cond.sptk.few 1b // if (len != 0) copy more 676 6772: cmp.eq p6,p0=r0,in3 678(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 679 sub r14=r14,in2 // *lenp = (i - len) 680 ;; 681 st8 [in3]=r14 682 6833: cmp.eq p6,p0=r0,r15 684(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 685 686 mov ret0=ENAMETOOLONG // *from != '\0'; error. 687 br.ret.sptk.few rp 688 6894: mov ret0=0 // return 0. 690 br.ret.sptk.few rp 691END(copystr) 692 693ENTRY(copyinstr, 4) 694 .prologue 695 .regstk 4, 3, 4, 0 696 .save ar.pfs,loc0 697 alloc loc0=ar.pfs,4,3,4,0 698 .save rp,loc1 699 mov loc1=rp 700 .body 701 702 movl loc2=VM_MAX_ADDRESS // make sure that src addr 703 ;; 704 cmp.geu p6,p0=in0,loc2 // is in user space. 705 ;; 706(p6) br.cond.spnt.few copyerr // if it's not, error out. 707 movl r14=copyerr // set up fault handler. 708 add r15=PC_CURTHREAD,r13 // find curthread 709 ;; 710 ld8 r15=[r15] 711 ;; 712 add r15=TD_PCB,r15 // find pcb 713 ;; 714 ld8 r15=[r15] 715 ;; 716 add loc2=PCB_ONFAULT,r15 717 ;; 718 st8 [loc2]=r14 719 ;; 720 mov out0=in0 721 mov out1=in1 722 mov out2=in2 723 mov out3=in3 724 ;; 725 br.call.sptk.few rp=copystr // do the copy. 726 st8 [loc2]=r0 // kill the fault handler. 727 mov ar.pfs=loc0 // restore ar.pfs 728 mov rp=loc1 // restore ra. 729 br.ret.sptk.few rp // ret0 left over from copystr 730END(copyinstr) 731 732/* 733 * Not the fastest bcopy in the world. 734 */ 735ENTRY(bcopy, 3) 736 mov ret0=r0 // return zero for copy{in,out} 737 ;; 738 cmp.le p6,p0=in2,r0 // bail if len <= 0 739(p6) br.ret.spnt.few rp 740 741 sub r14=in1,in0 ;; // check for overlap 742 cmp.ltu p6,p0=r14,in2 // dst-src < len 743(p6) br.cond.spnt.few 5f 744 745 extr.u r14=in0,0,3 // src & 7 746 extr.u r15=in1,0,3 ;; // dst & 7 747 cmp.eq p6,p0=r14,r15 // different alignment? 748(p6) br.cond.spnt.few 2f // branch if same alignment 749 7501: ld1 r14=[in0],1 ;; // copy bytewise 751 st1 [in1]=r14,1 752 add in2=-1,in2 ;; // len-- 753 cmp.ne p6,p0=r0,in2 754(p6) br.cond.dptk.few 1b // loop 755 br.ret.sptk.few rp // done 756 7572: cmp.eq p6,p0=r14,r0 // aligned? 758(p6) br.cond.sptk.few 4f 759 7603: ld1 r14=[in0],1 ;; // copy bytewise 761 st1 [in1]=r14,1 762 extr.u r15=in0,0,3 // src & 7 763 add in2=-1,in2 ;; // len-- 764 cmp.eq p6,p0=r0,in2 // done? 765 cmp.eq p7,p0=r0,r15 ;; // aligned now? 766(p6) br.ret.spnt.few rp // return if done 767(p7) br.cond.spnt.few 4f // go to main copy 768 br.cond.sptk.few 3b // more bytes to copy 769 770 // At this point, in2 is non-zero 771 7724: mov r14=8 ;; 773 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 774(p6) br.cond.spnt.few 1b // byte copy the end 775 ld8 r15=[in0],8 ;; // copy word 776 st8 [in1]=r15,8 777 add in2=-8,in2 ;; // len -= 8 778 cmp.ne p6,p0=r0,in2 // done? 779(p6) br.cond.spnt.few 4b // again 780 781 br.ret.sptk.few rp // return 782 783 // Don't bother optimising overlap case 784 7855: add in0=in0,in2 786 add in1=in1,in2 ;; 787 add in0=-1,in0 788 add in1=-1,in1 ;; 789 7906: ld1 r14=[in0],-1 ;; 791 st1 [in1]=r14,-1 792 add in2=-1,in2 ;; 793 cmp.ne p6,p0=r0,in2 794(p6) br.cond.spnt.few 6b 795 796 br.ret.sptk.few rp 797END(bcopy) 798 799ENTRY(memcpy,3) 800 mov r14=in0 ;; 801 mov in0=in1 ;; 802 mov in1=r14 803 br.cond.sptk.few bcopy 804END(memcpy) 805 806ENTRY(copyin, 3) 807 .prologue 808 .regstk 3, 3, 3, 0 809 .save ar.pfs,loc0 810 alloc loc0=ar.pfs,3,3,3,0 811 .save rp,loc1 812 mov loc1=rp 813 .body 814 815 movl loc2=VM_MAX_ADDRESS // make sure that src addr 816 ;; 817 cmp.geu p6,p0=in0,loc2 // is in user space. 818 ;; 819(p6) br.cond.spnt.few copyerr // if it's not, error out. 820 movl r14=copyerr // set up fault handler. 821 add r15=PC_CURTHREAD,r13 // find curthread 822 ;; 823 ld8 r15=[r15] 824 ;; 825 add r15=TD_PCB,r15 // find pcb 826 ;; 827 ld8 r15=[r15] 828 ;; 829 add loc2=PCB_ONFAULT,r15 830 ;; 831 st8 [loc2]=r14 832 ;; 833 mov out0=in0 834 mov out1=in1 835 mov out2=in2 836 ;; 837 br.call.sptk.few rp=bcopy // do the copy. 838 st8 [loc2]=r0 // kill the fault handler. 839 mov ar.pfs=loc0 // restore ar.pfs 840 mov rp=loc1 // restore ra. 841 br.ret.sptk.few rp // ret0 left over from bcopy 842END(copyin) 843 844ENTRY(copyout, 3) 845 .prologue 846 .regstk 3, 3, 3, 0 847 .save ar.pfs,loc0 848 alloc loc0=ar.pfs,3,3,3,0 849 .save rp,loc1 850 mov loc1=rp 851 .body 852 853 movl loc2=VM_MAX_ADDRESS // make sure that dest addr 854 ;; 855 cmp.geu p6,p0=in1,loc2 // is in user space. 856 ;; 857(p6) br.cond.spnt.few copyerr // if it's not, error out. 858 movl r14=copyerr // set up fault handler. 859 add r15=PC_CURTHREAD,r13 // find curthread 860 ;; 861 ld8 r15=[r15] 862 ;; 863 add r15=TD_PCB,r15 // find pcb 864 ;; 865 ld8 r15=[r15] 866 ;; 867 add loc2=PCB_ONFAULT,r15 868 ;; 869 st8 [loc2]=r14 870 ;; 871 mov out0=in0 872 mov out1=in1 873 mov out2=in2 874 ;; 875 br.call.sptk.few rp=bcopy // do the copy. 876 st8 [loc2]=r0 // kill the fault handler. 877 mov ar.pfs=loc0 // restore ar.pfs 878 mov rp=loc1 // restore ra. 879 br.ret.sptk.few rp // ret0 left over from bcopy 880END(copyout) 881 882ENTRY(copyerr, 0) 883 add r14=PC_CURTHREAD,r13 ;; // find curthread 884 ld8 r14=[r14] ;; 885 add r14=TD_PCB,r14 ;; // curthread->td_addr 886 ld8 r14=[r14] ;; 887 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 888 st8 [r14]=r0 // reset fault handler 889 890 mov ret0=EFAULT // return EFAULT 891 br.ret.sptk.few rp 892END(copyerr) 893 894#if defined(GPROF) 895/* 896 * Important registers: 897 * r8 structure return address 898 * rp our return address 899 * in0 caller's ar.pfs 900 * in1 caller's gp 901 * in2 caller's rp 902 * in3 GOT entry 903 * ar.pfs our pfs 904 */ 905ENTRY_NOPROFILE(_mcount, 4) 906 alloc loc0 = ar.pfs, 4, 3, 2, 0 907 mov loc1 = r8 908 mov loc2 = rp 909 ;; 910 mov out0 = in2 911 mov out1 = rp 912 br.call.sptk rp = __mcount 913 ;; 9141: 915 mov gp = in1 916 mov r14 = ip 917 mov b7 = loc2 918 ;; 919 add r14 = 2f - 1b, r14 920 mov ar.pfs = loc0 921 mov rp = in2 922 ;; 923 mov b7 = r14 924 mov b6 = loc2 925 mov r8 = loc1 926 mov r14 = in0 927 br.ret.sptk b7 928 ;; 9292: 930 mov ar.pfs = r14 931 br.sptk b6 932 ;; 933END(_mcount) 934#endif 935