Home | History | Annotate | Line # | Download | only in ia64
      1 /*	$NetBSD: support.S,v 1.11 2025/08/18 20:59:55 andvar Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 Doug Rabson
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  * $FreeBSD$
     29  */
     30 
     31 /*-
     32  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
     33  * All rights reserved.
     34  *
     35  * Author: Chris G. Demetriou
     36  *
     37  * Permission to use, copy, modify and distribute this software and
     38  * its documentation is hereby granted, provided that both the copyright
     39  * notice and this permission notice appear in all copies of the
     40  * software, derivative works or modified versions, and any portions
     41  * thereof, and that both notices appear in supporting documentation.
     42  *
     43  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     44  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     45  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     46  *
     47  * Carnegie Mellon requests users of this software to return to
     48  *
     49  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     50  *  School of Computer Science
     51  *  Carnegie Mellon University
     52  *  Pittsburgh PA 15213-3890
     53  *
     54  * any improvements or extensions that they make and grant Carnegie the
     55  * rights to redistribute these changes.
     56  */
     57 
     58 #include <machine/asm.h>
     59 
     60 #include "assym.h"
     61 
     62 .text
     63 
     64 /*
     65  * ia64_change_mode:	change mode to/from physical mode
     66  *
     67  * Arguments:
     68  *	r14	psr for desired mode
     69  *
     70  * Modifies:
     71  *	r15-r19	scratch
     72  *	ar.bsp	translated to new mode
     73  */
     74 ENTRY_NOPROFILE(ia64_change_mode, 0)
     75 	rsm	psr.i | psr.ic
     76 	mov	r19=ar.rsc		// save rsc while we change mode
     77 	tbit.nz	p6,p7=r14,17		// physical or virtual ?
     78 	;;
     79 	mov	ar.rsc=0		// turn off RSE
     80 (p6)	mov	r15=7			// RR base for virtual addresses
     81 (p7)	mov	r15=0			// RR base for physical addresses
     82 	flushrs				// no dirty registers please
     83 	srlz.i
     84 	;;
     85 	mov	r16=ar.bsp
     86 	mov	r17=rp
     87 	mov	r18=ar.rnat
     88 	;;
     89 	dep	r16=r15,r16,61,3	// new address of ar.bsp
     90 	dep	r17=r15,r17,61,3	// new address of rp
     91 	dep	sp=r15,sp,61,3		// new address of sp
     92 	;;
     93 	mov	ar.bspstore=r16
     94 	mov	rp=r17
     95 	;;
     96 1:	mov	r16=ip
     97 	mov	ar.rnat=r18
     98 	mov	cr.ipsr=r14		// psr for new mode
     99 	;;
    100 	add	r16=2f-1b,r16		// address to rfi to
    101 	;;
    102 	dep	r16=r15,r16,61,3	// new mode address for rfi
    103 	;;
    104 	mov	cr.iip=r16		// setup for rfi
    105 	mov	cr.ifs=r0
    106 	;;
    107 	rfi
    108 
    109 2:	mov	ar.rsc=r19		// restore ar.rsc
    110 	br.ret.sptk.few rp		// now in new mode
    111 END(ia64_change_mode)
    112 
    113 /*
    114  * ia64_physical_mode:	change mode to physical mode
    115  *
    116  * Return:
    117  *	ret0	psr to restore
    118  *
    119  * Modifies:
    120  *	r15-r18	scratch
    121  *	ar.bsp	translated to physical mode
    122  *	psr.i	cleared
    123  */
    124 ENTRY(ia64_physical_mode, 0)
    125 	mov	r14=psr
    126 	mov	ret0=psr
    127 	movl	r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH)
    128 	movl	r16=IA64_PSR_BN
    129 	;;
    130 	andcm	r14=r14,r15		// clear various xT bits
    131 	;;
    132 	or	r14=r14,r16		// make sure BN=1
    133 	or	ret0=ret0,r16		// make sure BN=1
    134 
    135 	br.cond.sptk.many ia64_change_mode
    136 END(ia64_physical_mode)
    137 
    138 /*
    139  * ia64_call_efi_physical:	call an EFI procedure in physical mode
    140  *
    141  * Arguments:
    142  *	in0		Address of EFI procedure descriptor
    143  *	in1-in5		Arguments to EFI procedure
    144  *
    145  * Return:
    146  *	ret0-ret3	return values from EFI
    147  *
    148  */
    149 ENTRY(ia64_call_efi_physical, 6)
    150 	.prologue
    151 	.regstk	6,4,5,0
    152 	.save	ar.pfs,loc0
    153 	alloc	loc0=ar.pfs,6,4,5,0
    154 	;;
    155 	.save	rp,loc1
    156 	mov	loc1=rp
    157 	;;
    158 	.body
    159 	br.call.sptk.many rp=ia64_physical_mode
    160 	;;
    161 	mov	loc2=r8			// psr to restore mode
    162 	mov	loc3=gp			// save kernel gp
    163 	ld8	r14=[in0],8		// function address
    164 	;;
    165 	mov	out0=in1
    166 	mov	out1=in2
    167 	mov	out2=in3
    168 	mov	out3=in4
    169 	mov	out4=in5
    170 	ld8	gp=[in0]		// function gp value
    171 	;;
    172 	mov	b6=r14
    173 	;;
    174 	br.call.sptk.many rp=b6		// call EFI procedure
    175 	mov	gp=loc3			// restore kernel gp
    176 	;;
    177 	mov	r14=loc2		// psr to restore mode
    178 	br.call.sptk.many rp=ia64_change_mode
    179 	;;
    180 	mov	rp=loc1
    181 	mov	ar.pfs=loc0
    182 	;;
    183 	br.ret.sptk.many rp
    184 END(ia64_call_efi_physical)
    185 
    186 /**************************************************************************/
    187 
    188 ENTRY(fusufault, 0)
    189 {	.mib
    190 	st8.rel		[r15]=r0		// Clear onfault.
    191 	add		ret0=-1,r0
    192 	br.ret.sptk	rp
    193 	;;
    194 }
    195 END(fusufault)
    196 
    197 /*
    198  * casuptr(intptr_t *p, intptr_t old, intptr_t new)
    199  *	Perform a compare-exchange in user space.
    200  */
    201 ENTRY(casuptr, 3)
    202 {	.mlx
    203 	add		r15=PC_CURLWP,r13
    204 	movl		r14=VM_MAX_ADDRESS
    205 	;;
    206 }
    207 {	.mib
    208 	ld8		r15=[r15]		// r15 = curthread
    209 	cmp.geu		p6,p0=in0,r14
    210 (p6)	br.dpnt.few	1f
    211 	;;
    212 }
    213 {	.mlx
    214 	add		r15=L_PCB,r15
    215 	movl		r14=fusufault
    216 	;;
    217 }
    218 {	.mmi
    219 	ld8		r15=[r15]		// r15 = PCB
    220 	;;
    221 	mov		ar.ccv=in1
    222 	add		r15=PCB_ONFAULT,r15
    223 	;;
    224 }
    225 {	.mmi
    226 	st8		[r15]=r14		// Set onfault
    227 	;;
    228 	cmpxchg8.rel	ret0=[in0],in2,ar.ccv
    229 	nop		0
    230 	;;
    231 }
    232 {	.mfb
    233 	st8.rel		[r15]=r0		// Clear onfault
    234 	nop		0
    235 	br.ret.sptk	rp
    236 	;;
    237 }
    238 1:
    239 {	.mfb
    240 	add		ret0=-1,r0
    241 	nop		0
    242 	br.ret.sptk	rp
    243 	;;
    244 }
    245 END(casuptr)
    246 
    247 /**************************************************************************/
    248 
    249 ENTRY(ufetchstore_fault, 0)
    250 {	.mfb
    251 	st8.rel		[r15]=r0	/* curpcb->pcb_onfault = NULL */
    252 	nop		0		/* ret0 already has error */
    253 	br.ret.sptk	rp
    254 	;;
    255 }
    256 END(ufetchstore_fault)
    257 
    258 #define	UFETCH(load_insn, store_insn)					  \
    259 {	.mlx								 ;\
    260 	add		r15=PC_CURLWP,r13				 ;\
    261 	movl		r14=VM_MAX_ADDRESS				;;\
    262 }									 ;\
    263 {	.mib								 ;\
    264 	ld8		r15=[r15]	/* r15 = curlwp */		 ;\
    265 	cmp.geu		p6,p0=in0,r14					 ;\
    266 (p6)	br.dpnt.few	1f						;;\
    267 }									 ;\
    268 {	.mlx								 ;\
    269 	add		r15=L_PCB,r15					 ;\
    270 	movl		r14=ufetchstore_fault				;;\
    271 }									 ;\
    272 {	.mmi								 ;\
    273 	ld8		r15=[r15]	/*r15 = curlwp->l_pcb */	;;\
    274 	nop		0						 ;\
    275 	add		r15=PCB_ONFAULT,r15				;;\
    276 }									 ;\
    277 {	.mmi								 ;\
    278 	st8		[r15]=r14	/* curpcb->pcb_onfault = */	;;\
    279 					/*     ufetchstore_fault */	  \
    280 	mf								 ;\
    281 	nop		0						;;\
    282 }									 ;\
    283 {	.mmi								 ;\
    284 	load_insn	r14=[in0]	/* r14 = *uaddr */		;;\
    285 	st8.rel		[r15]=r0	/* curpcb->pcb_onfault = NULL */ ;\
    286 	nop		0						;;\
    287 }									 ;\
    288 {	.mib								 ;\
    289 	store_insn	[in1]=r14	/* *valp = r14 */		 ;\
    290 	mov		ret0=r0		/* ret0 = 0 (success!) */	 ;\
    291 	br.ret.sptk	rp						;;\
    292 }									 ;\
    293 1:									  \
    294 {	.mfb								 ;\
    295 	mov		ret0=EFAULT	/* return EFAULT */		 ;\
    296 	nop		0						 ;\
    297 	br.ret.sptk	rp						;;\
    298 }
    299 
    300 /* LINTSTUB: int _ufetch_8(const uint8_t *uaddr, uint8_t *valp); */
    301 ENTRY(_ufetch_8, 2)
    302 	UFETCH(ld1, st1)
    303 END(_ufetch_8)
    304 
    305 /* LINTSTUB: int _ufetch_16(const uint16_t *uaddr, uint16_t *valp); */
    306 ENTRY(_ufetch_16, 2)
    307 	UFETCH(ld2, st2)
    308 END(_ufetch_16)
    309 
    310 /* LINTSTUB: int _ufetch_32(const uint32_t *uaddr, uint32_t *valp); */
    311 ENTRY(_ufetch_32, 2)
    312 	UFETCH(ld4, st4)
    313 END(_ufetch_32)
    314 
    315 /* LINTSTUB: int _ufetch_64(const uint64_t *uaddr, uint64_t *valp); */
    316 ENTRY(_ufetch_64, 2)
    317 	UFETCH(ld8, st8)
    318 END(_ufetch_64)
    319 
    320 #define	USTORE(store_insn)						  \
    321 {	.mlx								 ;\
    322 	add		r15=PC_CURLWP,r13				 ;\
    323 	movl		r14=VM_MAX_ADDRESS				;;\
    324 }									 ;\
    325 {	.mib								 ;\
    326 	ld8		r15=[r15]	/* r15 = curlwp */		 ;\
    327 	cmp.geu		p6,p0=in0,r14					 ;\
    328 (p6)	br.dpnt.few	1f						;;\
    329 }									 ;\
    330 {	.mlx								 ;\
    331 	add		r15=L_PCB,r15					 ;\
    332 	movl		r14=ufetchstore_fault				;;\
    333 }									 ;\
    334 {	.mmi								 ;\
    335 	ld8		r15=[r15]	/*r15 = curlwp->l_pcb */	;;\
    336 	nop		0						 ;\
    337 	add		r15=PCB_ONFAULT,r15				;;\
    338 }									 ;\
    339 {	.mmi								 ;\
    340 	st8		[r15]=r14	/* curpcb->pcb_onfault = */	;;\
    341 					/*     ufetchstore_fault */	  \
    342 	store_insn	[in0]=in1	/* *uaddr = val */		 ;\
    343 	nop		0						;;\
    344 }									 ;\
    345 {	.mib								 ;\
    346 	st8.rel		[r15]=r0	/* curpcb->pcb_onfault = NULL */ ;\
    347 	mov		ret0=r0		/* ret0 = 0 (success!) */	 ;\
    348 	br.ret.sptk	rp						;;\
    349 }									 ;\
    350 1:									  \
    351 {	.mfb								 ;\
    352 	mov		ret0=EFAULT	/* return EFAULT */		 ;\
    353 	nop		0						 ;\
    354 	br.ret.sptk	rp						;;\
    355 }
    356 
    357 /* LINTSTUB: int _ustore_8(uint8_t *uaddr, uint8_t val); */
    358 ENTRY(_ustore_8, 2)
    359 	USTORE(st1.rel)
    360 END(_ustore_8)
    361 
    362 /* LINTSTUB: int _ustore_16(uint16_t *uaddr, uint16_t val); */
    363 ENTRY(_ustore_16, 2)
    364 	USTORE(st2.rel)
    365 END(_ustore_16)
    366 
    367 /* LINTSTUB: int _ustore_32(uint32_t *uaddr, uint32_t val); */
    368 ENTRY(_ustore_32, 2)
    369 	USTORE(st4.rel)
    370 END(_ustore_32)
    371 
    372 /* LINTSTUB: int _ustore_64(uint64_t *uaddr, uint64_t val); */
    373 ENTRY(_ustore_64, 2)
    374 	USTORE(st8.rel)
    375 END(_ustore_64)
    376 
    377 /**************************************************************************/
    378 
    379 /*
    380  * XXX XXX XXX: Should be removed?
    381  */
    382 ENTRY(ia64_copystr, 4)
    383 	mov	r14=in2			// r14 = i = len
    384 	cmp.eq	p6,p0=r0,in2
    385 (p6)	br.cond.spnt.few 2f		// if (len == 0), bail out
    386 
    387 1:	ld1	r15=[in0],1		// read one byte
    388 	;;
    389 	st1	[in1]=r15,1		// write that byte
    390 	add	in2=-1,in2		// len--
    391 	;;
    392 	cmp.eq	p6,p0=r0,r15
    393 	cmp.ne	p7,p0=r0,in2
    394 	;;
    395 (p6)	br.cond.spnt.few 2f		// if (*from == 0), bail out
    396 (p7)	br.cond.sptk.few 1b		// if (len != 0) copy more
    397 
    398 2:	cmp.eq	p6,p0=r0,in3
    399 (p6)	br.cond.dpnt.few 3f		// if (lenp != NULL)
    400 	sub	r14=r14,in2		// *lenp = (i - len)
    401 	;;
    402 	st8	[in3]=r14
    403 
    404 3:	cmp.eq	p6,p0=r0,r15
    405 (p6)	br.cond.spnt.few 4f		// *from == '\0'; leave quietly
    406 
    407 	mov	ret0=ENAMETOOLONG	// *from != '\0'; error.
    408 	br.ret.sptk.few rp
    409 
    410 4:	mov	ret0=0			// return 0.
    411 	br.ret.sptk.few rp
    412 END(ia64_copystr)
    413 
    414 ENTRY(copyinstr, 4)
    415 	.prologue
    416 	.regstk	4, 3, 4, 0
    417 	.save	ar.pfs,loc0
    418 	alloc	loc0=ar.pfs,4,3,4,0
    419 	.save	rp,loc1
    420 	mov	loc1=rp
    421 	.body
    422 
    423 	movl	loc2=VM_MAX_ADDRESS		// make sure that src addr
    424 	;;
    425 	cmp.geu	p6,p0=in0,loc2			// is in user space.
    426 	;;
    427 (p6)	br.cond.spnt.few copyefault		// if it's not, error out.
    428 	movl	r14=copyerr			// set up fault handler.
    429 	add	r15=PC_CURLWP,r13		// find curthread
    430 	;;
    431 	ld8	r15=[r15]
    432 	;;
    433 	add	r15=L_PCB,r15			// find pcb
    434 	;;
    435 	ld8	r15=[r15]
    436 	;;
    437 	add	loc2=PCB_ONFAULT,r15
    438 	;;
    439 	st8	[loc2]=r14
    440 	;;
    441 	mov	out0=in0
    442 	mov	out1=in1
    443 	mov	out2=in2
    444 	mov	out3=in3
    445 	;;
    446 	br.call.sptk.few rp=ia64_copystr	// do the copy.
    447 	st8	[loc2]=r0			// kill the fault handler.
    448 	mov	ar.pfs=loc0			// restore ar.pfs
    449 	mov	rp=loc1				// restore ra.
    450 	br.ret.sptk.few rp			// ret0 left over from copystr
    451 END(copyinstr)
    452 
    453 ENTRY(copyoutstr, 4)
    454 	.prologue
    455 	.regstk	4, 3, 4, 0
    456 	.save	ar.pfs,loc0
    457 	alloc	loc0=ar.pfs,4,3,4,0
    458 	.save	rp,loc1
    459 	mov	loc1=rp
    460 	.body
    461 
    462 	movl	loc2=VM_MAX_ADDRESS		// make sure that dest addr
    463 	;;
    464 	cmp.geu	p6,p0=in1,loc2			// is in user space.
    465 	;;
    466 (p6)	br.cond.spnt.few copyefault		// if it's not, error out.
    467 	movl	r14=copyerr			// set up fault handler.
    468 	add	r15=PC_CURLWP,r13		// find curthread
    469 	;;
    470 	ld8	r15=[r15]
    471 	;;
    472 	add	r15=L_PCB,r15			// find pcb
    473 	;;
    474 	ld8	r15=[r15]
    475 	;;
    476 	add	loc2=PCB_ONFAULT,r15
    477 	;;
    478 	st8	[loc2]=r14
    479 	;;
    480 	mov	out0=in0
    481 	mov	out1=in1
    482 	mov	out2=in2
    483 	mov	out3=in3
    484 	;;
    485 	br.call.sptk.few rp=ia64_copystr	// do the copy.
    486 	st8	[loc2]=r0			// kill the fault handler.
    487 	mov	ar.pfs=loc0			// restore ar.pfs
    488 	mov	rp=loc1				// restore ra.
    489 	br.ret.sptk.few rp			// ret0 left over from copystr
    490 END(copyoutstr)
    491 
    492 /*
    493  * int kcopy(const void *from, void *to, size_t len);
    494  * Copy len bytes, abort on fault.
    495  */
    496 
    497 ENTRY(kcopy, 3)
    498 	.prologue
    499 	.regstk	3, 3, 3, 0
    500 	.save	ar.pfs,loc0
    501 	alloc	loc0=ar.pfs,3,3,3,0
    502 	.save	rp,loc1
    503 	mov	loc1=rp
    504 	.body
    505 
    506 	movl	r14=copyerr			// set up fault handler.
    507 	add	r15=PC_CURLWP,r13		// find curthread
    508 	;;
    509 	ld8	r15=[r15]
    510 	;;
    511 	add	r15=L_PCB,r15			// find pcb
    512 	;;
    513 	ld8	r15=[r15]
    514 	;;
    515 	add	loc2=PCB_ONFAULT,r15
    516 	;;
    517 	st8	[loc2]=r14
    518 	;;
    519 	mov	out0=in0
    520 	mov	out1=in1
    521 	mov	out2=in2
    522 	mov	ret0=r0				// XXX netbsd kcopy same as freebsd?
    523 	;;
    524 	br.call.sptk.few rp=bcopy		// do the copy.
    525 	st8	[loc2]=r0			// kill the fault handler.
    526 	mov	ar.pfs=loc0			// restore ar.pfs
    527 	mov	rp=loc1				// restore ra.
    528 	br.ret.sptk.few rp
    529 END(kcopy)
    530 
    531 ENTRY(copyin, 3)
    532 	.prologue
    533 	.regstk	3, 3, 3, 0
    534 	.save	ar.pfs,loc0
    535 	alloc	loc0=ar.pfs,3,3,3,0
    536 	.save	rp,loc1
    537 	mov	loc1=rp
    538 	.body
    539 
    540 	movl	loc2=VM_MAX_ADDRESS		// make sure that src addr
    541 	;;
    542 	cmp.geu	p6,p0=in0,loc2			// is in user space.
    543 	;;
    544 (p6)	br.cond.spnt.few copyefault		// if it's not, error out.
    545 	movl	r14=copyerr			// set up fault handler.
    546 	add	r15=PC_CURLWP,r13		// find curthread
    547 	;;
    548 	ld8	r15=[r15]
    549 	;;
    550 	add	r15=L_PCB,r15			// find pcb
    551 	;;
    552 	ld8	r15=[r15]
    553 	;;
    554 	add	loc2=PCB_ONFAULT,r15
    555 	;;
    556 	st8	[loc2]=r14
    557 	;;
    558 	mov	out0=in0
    559 	mov	out1=in1
    560 	mov	out2=in2
    561 	mov	ret0=r0				// return zero for copy{in,out}
    562 	;;
    563 	br.call.sptk.few rp=bcopy		// do the copy.
    564 	st8	[loc2]=r0			// kill the fault handler.
    565 	mov	ar.pfs=loc0			// restore ar.pfs
    566 	mov	rp=loc1				// restore ra.
    567 	br.ret.sptk.few rp
    568 END(copyin)
    569 
    570 ENTRY(copyout, 3)
    571 	.prologue
    572 	.regstk	3, 3, 3, 0
    573 	.save	ar.pfs,loc0
    574 	alloc	loc0=ar.pfs,3,3,3,0
    575 	.save	rp,loc1
    576 	mov	loc1=rp
    577 	.body
    578 
    579 	movl	loc2=VM_MAX_ADDRESS		// make sure that dest addr
    580 	;;
    581 	cmp.geu	p6,p0=in1,loc2			// is in user space.
    582 	;;
    583 (p6)	br.cond.spnt.few copyefault		// if it's not, error out.
    584 	movl	r14=copyerr			// set up fault handler.
    585 	add	r15=PC_CURLWP,r13		// find curthread
    586 	;;
    587 	ld8	r15=[r15]
    588 	;;
    589 	add	r15=L_PCB,r15			// find pcb
    590 	;;
    591 	ld8	r15=[r15]
    592 	;;
    593 	add	loc2=PCB_ONFAULT,r15
    594 	;;
    595 	st8	[loc2]=r14
    596 	;;
    597 	mov	out0=in0
    598 	mov	out1=in1
    599 	mov	out2=in2
    600 	mov	ret0=r0				// return zero for copy{in,out}
    601 	;;
    602 	br.call.sptk.few rp=bcopy		// do the copy.
    603 	st8	[loc2]=r0			// kill the fault handler.
    604 	mov	ar.pfs=loc0			// restore ar.pfs
    605 	mov	rp=loc1				// restore ra.
    606 	br.ret.sptk.few rp
    607 END(copyout)
    608 
    609 ENTRY(copyerr, 0)
    610 	add	r14=PC_CURLWP,r13 ;;		// find curthread
    611 	ld8	r14=[r14] ;;
    612 	add	r14=L_PCB,r14 ;;		// curthread->td_addr
    613 	ld8	r14=[r14] ;;
    614 	add	r14=PCB_ONFAULT,r14 ;;		// &curthread->td_pcb->pcb_onfault
    615 	st8	[r14]=r0			// reset fault handler
    616 
    617 	br.ret.sptk.few rp
    618 END(copyerr)
    619 
    620 ENTRY(copyefault, 0)
    621 	add	r14=PC_CURLWP,r13 ;;		// find curthread
    622 	ld8	r14=[r14] ;;
    623 	add	r14=L_PCB,r14 ;;		// curthread->td_addr
    624 	ld8	r14=[r14] ;;
    625 	add	r14=PCB_ONFAULT,r14 ;;		// &curthread->td_pcb->pcb_onfault
    626 	st8	[r14]=r0			// reset fault handler
    627 
    628 	mov	ret0=EFAULT			// return EFAULT
    629 	br.ret.sptk.few rp
    630 END(copyefault)
    631 
    632 #if defined(GPROF)
    633 /*
    634  * Important registers:
    635  *      r8      structure return address
    636  *      rp      our return address
    637  *      in0     caller's ar.pfs
    638  *      in1     caller's gp
    639  *      in2     caller's rp
    640  *      in3     GOT entry
    641  *      ar.pfs  our pfs
    642  */
    643 ENTRY_NOPROFILE(_mcount, 4)
    644 	alloc		loc0 = ar.pfs, 4, 3, 2, 0
    645 	mov		loc1 = r8
    646 	mov		loc2 = rp
    647 	;;
    648 	mov		out0 = in2
    649 	mov		out1 = rp
    650 	br.call.sptk	rp = __mcount
    651 	;;
    652 1:
    653 	mov		gp = in1
    654 	mov		r14 = ip
    655 	mov		b7 = loc2
    656 	;;
    657 	add		r14 = 2f - 1b, r14
    658 	mov		ar.pfs = loc0
    659 	mov		rp = in2
    660 	;;
    661 	mov		b7 = r14
    662 	mov		b6 = loc2
    663 	mov		r8 = loc1
    664 	mov		r14 = in0
    665 	br.ret.sptk	b7
    666 	;;
    667 2:
    668 	mov		ar.pfs = r14
    669 	br.sptk		b6
    670 	;;
    671 END(_mcount)
    672 #endif
    673