support.S revision 85682
166458Sdfr/*- 266458Sdfr * Copyright (c) 1998 Doug Rabson 366458Sdfr * All rights reserved. 466458Sdfr * 566458Sdfr * Redistribution and use in source and binary forms, with or without 666458Sdfr * modification, are permitted provided that the following conditions 766458Sdfr * are met: 866458Sdfr * 1. Redistributions of source code must retain the above copyright 966458Sdfr * notice, this list of conditions and the following disclaimer. 1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1166458Sdfr * notice, this list of conditions and the following disclaimer in the 1266458Sdfr * documentation and/or other materials provided with the distribution. 1366458Sdfr * 1466458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1566458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1666458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1766458Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1866458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1966458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2066458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2166458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2266458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2366458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2466458Sdfr * SUCH DAMAGE. 2566458Sdfr * 2666458Sdfr * $FreeBSD: head/sys/ia64/ia64/support.S 85682 2001-10-29 11:30:54Z dfr $ 2766458Sdfr */ 2866458Sdfr/* 2966458Sdfr * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 3066458Sdfr * All rights reserved. 3166458Sdfr * 3266458Sdfr * Author: Chris G. Demetriou 3366458Sdfr * 3466458Sdfr * Permission to use, copy, modify and distribute this software and 3566458Sdfr * its documentation is hereby granted, provided that both the copyright 3666458Sdfr * notice and this permission notice appear in all copies of the 3766458Sdfr * software, derivative works or modified versions, and any portions 3866458Sdfr * thereof, and that both notices appear in supporting documentation. 3966458Sdfr * 4066458Sdfr * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 4166458Sdfr * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 4266458Sdfr * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 4366458Sdfr * 4466458Sdfr * Carnegie Mellon requests users of this software to return to 4566458Sdfr * 4666458Sdfr * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 4766458Sdfr * School of Computer Science 4866458Sdfr * Carnegie Mellon University 4966458Sdfr * Pittsburgh PA 15213-3890 5066458Sdfr * 5166458Sdfr * any improvements or extensions that they make and grant Carnegie the 5266458Sdfr * rights to redistribute these changes. 5366458Sdfr */ 5466458Sdfr 5566458Sdfr#include <machine/asm.h> 5683893Sdfr#include <machine/ia64_cpu.h> 5766458Sdfr#include <assym.s> 5866458Sdfr 5966458Sdfr .text 6066458Sdfr 6183893Sdfr/* 6283893Sdfr * ia64_change_mode: change mode to/from physical mode 6383893Sdfr * 6483893Sdfr * Arguments: 6583893Sdfr * r14 psr for desired mode 6684114Sdfr * 6784114Sdfr * Modifies: 6884114Sdfr * r15-r19 scratch 6984114Sdfr * ar.bsp tranlated to new mode 7083893Sdfr */ 7183893SdfrENTRY(ia64_change_mode, 0) 7283893Sdfr 7383893Sdfr rsm psr.i | psr.ic 7484114Sdfr mov r19=ar.rsc // save rsc while we change mode 7583893Sdfr tbit.nz p6,p7=r14,17 // physical or virtual ? 7683893Sdfr ;; 7784114Sdfr mov ar.rsc=0 // turn off RSE 7883893Sdfr(p6) mov r15=7 // RR base for virtual addresses 7983893Sdfr(p7) mov r15=0 // RR base for physical addresses 8083893Sdfr flushrs // no dirty registers please 8183893Sdfr srlz.i 8283893Sdfr ;; 8383893Sdfr mov r16=ar.bsp 8483893Sdfr mov r17=rp 8583893Sdfr mov r18=ar.rnat 8683893Sdfr ;; 8783893Sdfr dep r16=r15,r16,61,3 // new address of ar.bsp 8883893Sdfr dep r17=r15,r17,61,3 // new address of rp 8984114Sdfr dep sp=r15,sp,61,3 // new address of sp 9083893Sdfr ;; 9183893Sdfr mov ar.bspstore=r16 9283893Sdfr mov rp=r17 9383893Sdfr ;; 9483893Sdfr1: mov r16=ip 9583893Sdfr mov ar.rnat=r18 9683895Sdfr mov cr.ipsr=r14 // psr for new mode 9783893Sdfr ;; 9883893Sdfr add r16=2f-1b,r16 // address to rfi to 9983893Sdfr ;; 10083895Sdfr dep r16=r15,r16,61,3 // new mode address for rfi 10183893Sdfr ;; 10283893Sdfr mov cr.iip=r16 // setup for rfi 10383893Sdfr mov cr.ifs=r0 10483893Sdfr ;; 10583893Sdfr rfi 10683893Sdfr 10784114Sdfr2: mov ar.rsc=r19 // restore ar.rsc 10884114Sdfr br.ret.sptk.few rp // now in new mode 10983893Sdfr 11083893SdfrEND(ia64_change_mode) 11183893Sdfr 11283893Sdfr/* 11383893Sdfr * ia64_physical_mode: change mode to physical mode 11483893Sdfr * 11583893Sdfr * Return: 11683893Sdfr * ret0 psr to restore 11784114Sdfr * 11884114Sdfr * Modifies: 11984114Sdfr * r15-r18 scratch 12084114Sdfr * ar.bsp tranlated to physical mode 12184114Sdfr * psr.i cleared 12283893Sdfr */ 12383893SdfrENTRY(ia64_physical_mode, 0) 12483893Sdfr 12583893Sdfr mov r14=psr 12683893Sdfr mov ret0=psr 12784114Sdfr movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) 12883893Sdfr movl r16=IA64_PSR_BN 12983893Sdfr ;; 13083893Sdfr andcm r14=r14,r15 // clear various xT bits 13183893Sdfr ;; 13283893Sdfr or r14=r14,r16 // make sure BN=1 13383893Sdfr or ret0=ret0,r16 // make sure BN=1 13483893Sdfr 13583893Sdfr br.cond.sptk.many ia64_change_mode 13683893Sdfr 13783893SdfrEND(ia64_physical_mode) 13883893Sdfr 13984114Sdfr/* 14084114Sdfr * ia64_call_efi_physical: call an EFI procedure in physical mode 14184114Sdfr * 14284114Sdfr * Arguments: 14384114Sdfr * in0 Address of EFI procedure descriptor 14484114Sdfr * in1-in5 Arguments to EFI procedure 14584114Sdfr * 14684114Sdfr * Return: 14784114Sdfr * ret0-ret3 return values from EFI 14884114Sdfr * 14984114Sdfr */ 15084114SdfrENTRY(ia64_call_efi_physical, 6) 15184114Sdfr 15285682Sdfr .prologue 15385682Sdfr .regstk 6,4,5,0 15485682Sdfr .save ar.pfs,loc0 15584114Sdfr alloc loc0=ar.pfs,6,4,5,0 15684114Sdfr ;; 15785682Sdfr .save rp,loc1 15884114Sdfr mov loc1=rp 15984114Sdfr ;; 16085682Sdfr .body 16184114Sdfr br.call.sptk.many rp=ia64_physical_mode 16284114Sdfr ;; 16384114Sdfr mov loc2=r8 // psr to restore mode 16484114Sdfr mov loc3=gp // save kernel gp 16584114Sdfr ld8 r14=[in0],8 // function address 16684114Sdfr ;; 16784114Sdfr mov out0=in1 16884114Sdfr mov out1=in2 16984114Sdfr mov out2=in3 17084114Sdfr mov out3=in4 17184114Sdfr mov out4=in5 17284114Sdfr ld8 gp=[in0] // function gp value 17384114Sdfr ;; 17484114Sdfr mov b6=r14 17584114Sdfr ;; 17684114Sdfr br.call.sptk.many rp=b6 // call EFI procedure 17784114Sdfr mov gp=loc3 // restore kernel gp 17884114Sdfr ;; 17984114Sdfr mov r14=loc2 // psr to restore mode 18084114Sdfr br.call.sptk.many rp=ia64_change_mode 18184114Sdfr ;; 18284114Sdfr mov rp=loc1 18384114Sdfr mov ar.pfs=loc0 18484114Sdfr ;; 18584114Sdfr br.ret.sptk.many rp 18684114Sdfr 18784114SdfrEND(ia64_call_efi_physical) 18884114Sdfr 18966458Sdfr/**************************************************************************/ 19066458Sdfr 19166458Sdfr/* 19266458Sdfr * fu{byte,word} : fetch a byte (word) from user memory 19366458Sdfr */ 19466458Sdfr 19566633SdfrENTRY(suword, 2) 19666458Sdfr 19766633Sdfr movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 19866633Sdfr cmp.geu p6,p0=in0,r14 19966633Sdfr(p6) br.dpnt.few fusufault 20066458Sdfr 20166633Sdfr movl r14=fusufault // set up fault handler. 20283366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 20366633Sdfr ;; 20466633Sdfr ld8 r15=[r15] 20566633Sdfr ;; 20683366Sjulian add r15=TD_PCB,r15 // find pcb 20766633Sdfr ;; 20866633Sdfr ld8 r15=[r15] 20966633Sdfr ;; 21083366Sjulian add r15=PCB_ONFAULT,r15 21166633Sdfr ;; 21266633Sdfr st8 [r15]=r14 21366633Sdfr ;; 21466633Sdfr st8.rel [in0]=in1 // try the store 21566633Sdfr ;; 21666633Sdfr st8 [r15]=r0 // clean up 21766458Sdfr 21866633Sdfr mov ret0=r0 21966633Sdfr br.ret.sptk.few rp 22066458Sdfr 22166486SdfrEND(suword) 22266458Sdfr 22366633SdfrENTRY(subyte, 2) 22466458Sdfr 22566633Sdfr movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 22666633Sdfr cmp.geu p6,p0=in0,r14 22766633Sdfr(p6) br.dpnt.few fusufault 22866458Sdfr 22966633Sdfr movl r14=fusufault // set up fault handler. 23083366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 23166633Sdfr ;; 23266633Sdfr ld8 r15=[r15] 23366633Sdfr ;; 23483366Sjulian add r15=TD_PCB,r15 // find pcb 23566633Sdfr ;; 23666633Sdfr ld8 r15=[r15] 23766633Sdfr ;; 23883366Sjulian add r15=PCB_ONFAULT,r15 23966633Sdfr ;; 24066633Sdfr st8 [r15]=r14 24166633Sdfr ;; 24266633Sdfr st1.rel [in0]=in1 // try the store 24366633Sdfr ;; 24466633Sdfr st8 [r15]=r0 // clean up 24566458Sdfr 24666633Sdfr mov ret0=r0 24766633Sdfr br.ret.sptk.few rp 24866458Sdfr 24966486SdfrEND(subyte) 25066458Sdfr 25166633SdfrENTRY(fuword, 1) 25266458Sdfr 25366633Sdfr movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 25466633Sdfr cmp.geu p6,p0=in0,r14 25566633Sdfr(p6) br.dpnt.few fusufault 25666458Sdfr 25766633Sdfr movl r14=fusufault // set up fault handler. 25883366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 25966633Sdfr ;; 26066633Sdfr ld8 r15=[r15] 26166633Sdfr ;; 26283366Sjulian add r15=TD_PCB,r15 // find pcb 26366633Sdfr ;; 26466633Sdfr ld8 r15=[r15] 26566633Sdfr ;; 26683366Sjulian add r15=PCB_ONFAULT,r15 26766633Sdfr ;; 26866633Sdfr st8 [r15]=r14 26966633Sdfr ;; 27066633Sdfr ld8.acq ret0=[in0] // try the fetch 27166633Sdfr ;; 27266633Sdfr st8 [r15]=r0 // clean up 27366458Sdfr 27466633Sdfr br.ret.sptk.few rp 27566458Sdfr 27666486SdfrEND(fuword) 27766458Sdfr 27866633SdfrENTRY(fubyte, 1) 27966458Sdfr 28066633Sdfr movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 28166633Sdfr cmp.geu p6,p0=in0,r14 28266633Sdfr(p6) br.dpnt.few fusufault 28366458Sdfr 28466633Sdfr movl r14=fusufault // set up fault handler. 28583366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 28666633Sdfr ;; 28766633Sdfr ld8 r15=[r15] 28866633Sdfr ;; 28983366Sjulian add r15=TD_PCB,r15 // find pcb 29066633Sdfr ;; 29166633Sdfr ld8 r15=[r15] 29266633Sdfr ;; 29383366Sjulian add r15=PCB_ONFAULT,r15 29466633Sdfr ;; 29566633Sdfr st8 [r15]=r14 29666633Sdfr ;; 29766633Sdfr ld1.acq ret0=[in0] // try the fetch 29866633Sdfr ;; 29966633Sdfr st8 [r15]=r0 // clean up 30066458Sdfr 30166633Sdfr br.ret.sptk.few rp 30266458Sdfr 30366486SdfrEND(fubyte) 30466458Sdfr 30566633SdfrENTRY(suibyte, 2) 30666633Sdfr mov ret0=-1 30766633Sdfr br.ret.sptk.few rp 30866633SdfrEND(suibyte) 30966458Sdfr 31066633SdfrENTRY(fusufault, 0) 31166633Sdfr st8 [r15]=r0 ;; // r15 points at onfault 31266633Sdfr mov ret0=r0 31366633Sdfr br.ret.sptk.few rp 31466486SdfrEND(fusufault) 31566458Sdfr 31666633SdfrENTRY(fswintrberr, 0) 31766633SdfrXENTRY(fuswintr) /* XXX what is a 'word'? */ 31866633SdfrXENTRY(suswintr) /* XXX what is a 'word'? */ 31966633Sdfr mov ret0=-1 32066633Sdfr br.ret.sptk.few rp 32166486SdfrEND(fswintrberr) 32266458Sdfr 32366458Sdfr/**************************************************************************/ 32466458Sdfr 32566458Sdfr/* 32666458Sdfr * Copy a null-terminated string within the kernel's address space. 32766458Sdfr * If lenp is not NULL, store the number of chars copied in *lenp 32866458Sdfr * 32966458Sdfr * int copystr(char *from, char *to, size_t len, size_t *lenp); 33066458Sdfr */ 33166633SdfrENTRY(copystr, 4) 33266486Sdfr mov r14=in2 // r14 = i = len 33366486Sdfr cmp.eq p6,p0=r0,in2 33466486Sdfr(p6) br.cond.spnt.few 2f // if (len == 0), bail out 33566458Sdfr 33666486Sdfr1: ld1 r15=[in0],1 // read one byte 33766486Sdfr ;; 33866486Sdfr st1 [in1]=r15,1 // write that byte 33966486Sdfr add in2=-1,in2 // len-- 34066486Sdfr ;; 34166486Sdfr cmp.eq p6,p0=r0,r15 34266486Sdfr cmp.ne p7,p0=r0,in2 34366486Sdfr ;; 34466486Sdfr(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 34566486Sdfr(p7) br.cond.sptk.few 1b // if (len != 0) copy more 34666458Sdfr 34766486Sdfr2: cmp.eq p6,p0=r0,in3 34866486Sdfr(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 34967020Sdfr sub r14=r14,in2 // *lenp = (i - len) 35066486Sdfr ;; 35166486Sdfr st8 [in3]=r14 35266486Sdfr 35366486Sdfr3: cmp.eq p6,p0=r0,r15 35466486Sdfr(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 35566458Sdfr 35666486Sdfr mov ret0=ENAMETOOLONG // *from != '\0'; error. 35766486Sdfr br.ret.sptk.few rp 35866458Sdfr 35966486Sdfr4: mov ret0=0 // return 0. 36066486Sdfr br.ret.sptk.few rp 36166486Sdfr 36266486SdfrEND(copystr) 36366458Sdfr 36466633SdfrENTRY(copyinstr, 4) 36585682Sdfr .prologue 36685682Sdfr .regstk 4, 3, 4, 0 36785682Sdfr .save ar.pfs,loc0 36866486Sdfr alloc loc0=ar.pfs,4,3,4,0 36985682Sdfr .save rp,loc1 37066486Sdfr mov loc1=rp 37185682Sdfr .body 37266458Sdfr 37366486Sdfr movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 37466486Sdfr ;; 37566633Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 37666486Sdfr ;; 37766486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 37866486Sdfr movl r14=copyerr // set up fault handler. 37983366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 38066486Sdfr ;; 38166486Sdfr ld8 r15=[r15] 38266486Sdfr ;; 38383366Sjulian add r15=TD_PCB,r15 // find pcb 38466486Sdfr ;; 38566486Sdfr ld8 r15=[r15] 38666486Sdfr ;; 38783366Sjulian add loc2=PCB_ONFAULT,r15 38866486Sdfr ;; 38966486Sdfr st8 [loc2]=r14 39066486Sdfr ;; 39166486Sdfr mov out0=in0 39266486Sdfr mov out1=in1 39366486Sdfr mov out2=in2 39466486Sdfr mov out3=in3 39566486Sdfr ;; 39666486Sdfr br.call.sptk.few rp=copystr // do the copy. 39766486Sdfr st8 [loc2]=r0 // kill the fault handler. 39867020Sdfr mov ar.pfs=loc0 // restore ar.pfs 39966486Sdfr mov rp=loc1 // restore ra. 40066486Sdfr br.ret.sptk.few rp // ret0 left over from copystr 40166458Sdfr 40266486SdfrEND(copyinstr) 40366458Sdfr 40466633SdfrENTRY(copyoutstr, 4) 40585682Sdfr .prologue 40685682Sdfr .regstk 4, 3, 4, 0 40785682Sdfr .save ar.pfs,loc0 40866486Sdfr alloc loc0=ar.pfs,4,3,4,0 40985682Sdfr .save rp,loc1 41066486Sdfr mov loc1=rp 41185682Sdfr .body 41266458Sdfr 41366486Sdfr movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 41466486Sdfr ;; 41566633Sdfr cmp.geu p6,p0=in1,loc2 // is in user space. 41666486Sdfr ;; 41766486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 41866486Sdfr movl r14=copyerr // set up fault handler. 41983366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 42066486Sdfr ;; 42166486Sdfr ld8 r15=[r15] 42266486Sdfr ;; 42383366Sjulian add r15=TD_PCB,r15 // find pcb 42466486Sdfr ;; 42566486Sdfr ld8 r15=[r15] 42666486Sdfr ;; 42783366Sjulian add loc2=PCB_ONFAULT,r15 42866486Sdfr ;; 42966486Sdfr st8 [loc2]=r14 43066486Sdfr ;; 43166486Sdfr mov out0=in0 43266486Sdfr mov out1=in1 43366486Sdfr mov out2=in2 43466486Sdfr mov out3=in3 43566486Sdfr ;; 43666486Sdfr br.call.sptk.few rp=copystr // do the copy. 43766486Sdfr st8 [loc2]=r0 // kill the fault handler. 43867020Sdfr mov ar.pfs=loc0 // restore ar.pfs 43966486Sdfr mov rp=loc1 // restore ra. 44066486Sdfr br.ret.sptk.few rp // ret0 left over from copystr 44166486Sdfr 44266486SdfrEND(copyoutstr) 44366486Sdfr 44466458Sdfr/* 44566486Sdfr * Not the fastest bcopy in the world. 44666458Sdfr */ 44766633SdfrENTRY(bcopy, 3) 44866633SdfrXENTRY(ovbcopy) 44966458Sdfr 45066486Sdfr mov ret0=r0 // return zero for copy{in,out} 45166486Sdfr ;; 45266486Sdfr cmp.le p6,p0=in2,r0 // bail if len <= 0 45366486Sdfr(p6) br.ret.spnt.few rp 45466458Sdfr 45566486Sdfr sub r14=in1,in0 ;; // check for overlap 45666486Sdfr cmp.ltu p6,p0=r14,in2 // dst-src < len 45766486Sdfr(p6) br.cond.spnt.few 5f 45866458Sdfr 45966486Sdfr extr.u r14=in0,0,3 // src & 7 46066486Sdfr extr.u r15=in1,0,3 ;; // dst & 7 46166486Sdfr cmp.eq p6,p0=r14,r15 // different alignment? 46266486Sdfr(p6) br.cond.spnt.few 2f // branch if same alignment 46366458Sdfr 46466486Sdfr1: ld1 r14=[in0],1 ;; // copy bytewise 46566486Sdfr st1 [in1]=r14,1 46666486Sdfr add in2=-1,in2 ;; // len-- 46766486Sdfr cmp.ne p6,p0=r0,in2 46866486Sdfr(p6) br.cond.dptk.few 1b // loop 46966486Sdfr br.ret.sptk.few rp // done 47066458Sdfr 47166486Sdfr2: cmp.eq p6,p0=r14,r0 // aligned? 47266486Sdfr(p6) br.cond.sptk.few 4f 47366458Sdfr 47466486Sdfr3: ld1 r14=[in0],1 ;; // copy bytewise 47566486Sdfr st1 [in1]=r14,1 47666486Sdfr extr.u r15=in0,0,3 // src & 7 47766486Sdfr add in2=-1,in2 ;; // len-- 47866486Sdfr cmp.eq p6,p0=r0,in2 // done? 47966486Sdfr cmp.eq p7,p0=r0,r15 ;; // aligned now? 48066486Sdfr(p6) br.ret.spnt.few rp // return if done 48166486Sdfr(p7) br.cond.spnt.few 4f // go to main copy 48266486Sdfr br.cond.sptk.few 3b // more bytes to copy 48366458Sdfr 48466486Sdfr // At this point, in2 is non-zero 48566458Sdfr 48666486Sdfr4: mov r14=8 ;; 48766486Sdfr cmp.ltu p6,p0=in2,r14 ;; // len < 8? 48866486Sdfr(p6) br.cond.spnt.few 1b // byte copy the end 48966486Sdfr ld8 r15=[in0],8 ;; // copy word 49066486Sdfr st8 [in1]=r15,8 49166486Sdfr add in2=-8,in2 ;; // len -= 8 49266486Sdfr cmp.ne p6,p0=r0,in2 // done? 49366486Sdfr(p6) br.cond.spnt.few 4b // again 49466458Sdfr 49566486Sdfr br.ret.sptk.few rp // return 49666458Sdfr 49766486Sdfr // Don't bother optimising overlap case 49866458Sdfr 49966486Sdfr5: add in0=in0,in2 50066486Sdfr add in1=in1,in2 ;; 50166486Sdfr add in0=-1,in0 50266486Sdfr add in1=-1,in1 ;; 50366458Sdfr 50466486Sdfr6: ld1 r14=[in0],-1 ;; 50566486Sdfr st1 [in1]=r14,-1 50666486Sdfr add in2=-1,in2 ;; 50766486Sdfr cmp.ne p6,p0=r0,in2 50866486Sdfr(p6) br.cond.spnt.few 6b 50966458Sdfr 51066486Sdfr br.ret.sptk.few rp 51166458Sdfr 51266486SdfrEND(bcopy) 51366458Sdfr 51466633SdfrENTRY(memcpy,3) 51566486Sdfr 51666486Sdfr mov r14=in0 ;; 51766486Sdfr mov in0=in1 ;; 51866486Sdfr mov in1=r14 51966486Sdfr br.cond.sptk.few bcopy 52066486Sdfr 52166486SdfrEND(memcpy) 52266486Sdfr 52366633SdfrENTRY(copyin, 3) 52466486Sdfr 52585682Sdfr .prologue 52685682Sdfr .regstk 4, 3, 4, 0 52785682Sdfr .save ar.pfs,loc0 52885682Sdfr alloc loc0=ar.pfs,4,3,4,0 52985682Sdfr .save rp,loc1 53066486Sdfr mov loc1=rp 53185682Sdfr .body 53266458Sdfr 53366486Sdfr movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 53466486Sdfr ;; 53567020Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 53666486Sdfr ;; 53766486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 53866486Sdfr movl r14=copyerr // set up fault handler. 53983366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 54066486Sdfr ;; 54166486Sdfr ld8 r15=[r15] 54266486Sdfr ;; 54383366Sjulian add r15=TD_PCB,r15 // find pcb 54466486Sdfr ;; 54566486Sdfr ld8 r15=[r15] 54666486Sdfr ;; 54783366Sjulian add loc2=PCB_ONFAULT,r15 54866486Sdfr ;; 54966486Sdfr st8 [loc2]=r14 55066486Sdfr ;; 55166486Sdfr mov out0=in0 55266486Sdfr mov out1=in1 55366486Sdfr mov out2=in2 55466486Sdfr ;; 55566486Sdfr br.call.sptk.few rp=bcopy // do the copy. 55666486Sdfr st8 [loc2]=r0 // kill the fault handler. 55767020Sdfr mov ar.pfs=loc0 // restore ar.pfs 55866486Sdfr mov rp=loc1 // restore ra. 55966486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 56066486Sdfr 56166486SdfrEND(copyin) 56266458Sdfr 56366633SdfrENTRY(copyout, 3) 56466486Sdfr 56585682Sdfr .prologue 56685682Sdfr .regstk 4, 3, 4, 0 56785682Sdfr .save ar.pfs,loc0 56885682Sdfr alloc loc0=ar.pfs,4,3,4,0 56985682Sdfr .save rp,loc1 57066486Sdfr mov loc1=rp 57185682Sdfr .body 57266458Sdfr 57366486Sdfr movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 57466486Sdfr ;; 57567020Sdfr cmp.geu p6,p0=in1,loc2 // is in user space. 57666486Sdfr ;; 57766486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 57866486Sdfr movl r14=copyerr // set up fault handler. 57983366Sjulian add r15=GD_CURTHREAD,r13 // find curthread 58066486Sdfr ;; 58166486Sdfr ld8 r15=[r15] 58266486Sdfr ;; 58383366Sjulian add r15=TD_PCB,r15 // find pcb 58466486Sdfr ;; 58566486Sdfr ld8 r15=[r15] 58666486Sdfr ;; 58783366Sjulian add loc2=PCB_ONFAULT,r15 58866486Sdfr ;; 58966486Sdfr st8 [loc2]=r14 59066486Sdfr ;; 59166486Sdfr mov out0=in0 59266486Sdfr mov out1=in1 59366486Sdfr mov out2=in2 59466486Sdfr ;; 59566486Sdfr br.call.sptk.few rp=bcopy // do the copy. 59666486Sdfr st8 [loc2]=r0 // kill the fault handler. 59767020Sdfr mov ar.pfs=loc0 // restore ar.pfs 59866486Sdfr mov rp=loc1 // restore ra. 59966486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 60066486Sdfr 60166486SdfrEND(copyout) 60266458Sdfr 60366633SdfrENTRY(copyerr, 0) 60466458Sdfr 60583366Sjulian add r14=GD_CURTHREAD,r13 ;; // find curthread 60666486Sdfr ld8 r14=[r14] ;; 60783366Sjulian add r14=TD_PCB,r14 ;; // curthread->td_addr 60866486Sdfr ld8 r14=[r14] ;; 60983366Sjulian add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 61066486Sdfr st8 [r14]=r0 // reset fault handler 61166458Sdfr 61266486Sdfr mov ret0=EFAULT // return EFAULT 61366486Sdfr br.ret.sptk.few rp 61466458Sdfr 61566486SdfrEND(copyerr) 616