freebsd-dev/sys/ia64/ia64/support.s
Peter Wemm 7022a21abd Update an 'XXX what is this?' type comment about suswintr and fuswintr.
These are 16 bit short values used only by the profiling code.
2002-06-20 07:40:53 +00:00

668 lines
14 KiB
ArmAsm

/*-
* Copyright (c) 1998 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <machine/asm.h>
#include <machine/ia64_cpu.h>
#include <assym.s>
.text
/*
* ia64_change_mode: change mode to/from physical mode
*
* Arguments:
* r14 psr for desired mode
*
* Modifies:
* r15-r19 scratch
* ar.bsp tranlated to new mode
*/
ENTRY(ia64_change_mode, 0)
rsm psr.i | psr.ic
mov r19=ar.rsc // save rsc while we change mode
tbit.nz p6,p7=r14,17 // physical or virtual ?
;;
mov ar.rsc=0 // turn off RSE
(p6) mov r15=7 // RR base for virtual addresses
(p7) mov r15=0 // RR base for physical addresses
flushrs // no dirty registers please
srlz.i
;;
mov r16=ar.bsp
mov r17=rp
mov r18=ar.rnat
;;
dep r16=r15,r16,61,3 // new address of ar.bsp
dep r17=r15,r17,61,3 // new address of rp
dep sp=r15,sp,61,3 // new address of sp
;;
mov ar.bspstore=r16
mov rp=r17
;;
1: mov r16=ip
mov ar.rnat=r18
mov cr.ipsr=r14 // psr for new mode
;;
add r16=2f-1b,r16 // address to rfi to
;;
dep r16=r15,r16,61,3 // new mode address for rfi
;;
mov cr.iip=r16 // setup for rfi
mov cr.ifs=r0
;;
rfi
2: mov ar.rsc=r19 // restore ar.rsc
br.ret.sptk.few rp // now in new mode
END(ia64_change_mode)
/*
* ia64_physical_mode: change mode to physical mode
*
* Return:
* ret0 psr to restore
*
* Modifies:
* r15-r18 scratch
* ar.bsp tranlated to physical mode
* psr.i cleared
*/
ENTRY(ia64_physical_mode, 0)
mov r14=psr
mov ret0=psr
movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH)
movl r16=IA64_PSR_BN
;;
andcm r14=r14,r15 // clear various xT bits
;;
or r14=r14,r16 // make sure BN=1
or ret0=ret0,r16 // make sure BN=1
br.cond.sptk.many ia64_change_mode
END(ia64_physical_mode)
/*
* ia64_call_efi_physical: call an EFI procedure in physical mode
*
* Arguments:
* in0 Address of EFI procedure descriptor
* in1-in5 Arguments to EFI procedure
*
* Return:
* ret0-ret3 return values from EFI
*
*/
ENTRY(ia64_call_efi_physical, 6)
.prologue
.regstk 6,4,5,0
.save ar.pfs,loc0
alloc loc0=ar.pfs,6,4,5,0
;;
.save rp,loc1
mov loc1=rp
;;
.body
br.call.sptk.many rp=ia64_physical_mode
;;
mov loc2=r8 // psr to restore mode
mov loc3=gp // save kernel gp
ld8 r14=[in0],8 // function address
;;
mov out0=in1
mov out1=in2
mov out2=in3
mov out3=in4
mov out4=in5
ld8 gp=[in0] // function gp value
;;
mov b6=r14
;;
br.call.sptk.many rp=b6 // call EFI procedure
mov gp=loc3 // restore kernel gp
;;
mov r14=loc2 // psr to restore mode
br.call.sptk.many rp=ia64_change_mode
;;
mov rp=loc1
mov ar.pfs=loc0
;;
br.ret.sptk.many rp
END(ia64_call_efi_physical)
/**************************************************************************/
/*
* fu{byte,word} : fetch a byte (word) from user memory
*/
ENTRY(suword64, 2)
XENTRY(suword)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
st8.rel [in0]=in1 // try the store
;;
st8 [r15]=r0 // clean up
mov ret0=r0
br.ret.sptk.few rp
END(suword64)
ENTRY(suword32, 2)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
st4.rel [in0]=in1 // try the store
;;
st8 [r15]=r0 // clean up
mov ret0=r0
br.ret.sptk.few rp
END(suword32)
ENTRY(subyte, 2)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
st1.rel [in0]=in1 // try the store
;;
st8 [r15]=r0 // clean up
mov ret0=r0
br.ret.sptk.few rp
END(subyte)
ENTRY(fuword64, 1)
XENTRY(fuword)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
ld8.acq ret0=[in0] // try the fetch
;;
st8 [r15]=r0 // clean up
br.ret.sptk.few rp
END(fuword64)
ENTRY(fuword32, 1)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
ld4.acq ret0=[in0] // try the fetch
;;
st8 [r15]=r0 // clean up
br.ret.sptk.few rp
END(fuword32)
ENTRY(fubyte, 1)
movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok
cmp.geu p6,p0=in0,r14
(p6) br.dpnt.few fusufault
movl r14=fusufault // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add r15=PCB_ONFAULT,r15
;;
st8 [r15]=r14
;;
ld1.acq ret0=[in0] // try the fetch
;;
st8 [r15]=r0 // clean up
br.ret.sptk.few rp
END(fubyte)
ENTRY(fusufault, 0)
st8 [r15]=r0 ;; // r15 points at onfault
mov ret0=r0
br.ret.sptk.few rp
END(fusufault)
ENTRY(fswintrberr, 0)
XENTRY(fuswintr) /* XXX 16 bit short for profiling */
XENTRY(suswintr) /* XXX 16 bit short for profiling */
mov ret0=-1
br.ret.sptk.few rp
END(fswintrberr)
/**************************************************************************/
/*
* Copy a null-terminated string within the kernel's address space.
* If lenp is not NULL, store the number of chars copied in *lenp
*
* int copystr(char *from, char *to, size_t len, size_t *lenp);
*/
ENTRY(copystr, 4)
mov r14=in2 // r14 = i = len
cmp.eq p6,p0=r0,in2
(p6) br.cond.spnt.few 2f // if (len == 0), bail out
1: ld1 r15=[in0],1 // read one byte
;;
st1 [in1]=r15,1 // write that byte
add in2=-1,in2 // len--
;;
cmp.eq p6,p0=r0,r15
cmp.ne p7,p0=r0,in2
;;
(p6) br.cond.spnt.few 2f // if (*from == 0), bail out
(p7) br.cond.sptk.few 1b // if (len != 0) copy more
2: cmp.eq p6,p0=r0,in3
(p6) br.cond.dpnt.few 3f // if (lenp != NULL)
sub r14=r14,in2 // *lenp = (i - len)
;;
st8 [in3]=r14
3: cmp.eq p6,p0=r0,r15
(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
mov ret0=ENAMETOOLONG // *from != '\0'; error.
br.ret.sptk.few rp
4: mov ret0=0 // return 0.
br.ret.sptk.few rp
END(copystr)
ENTRY(copyinstr, 4)
.prologue
.regstk 4, 3, 4, 0
.save ar.pfs,loc0
alloc loc0=ar.pfs,4,3,4,0
.save rp,loc1
mov loc1=rp
.body
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.geu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov ar.pfs=loc0 // restore ar.pfs
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyinstr)
ENTRY(copyoutstr, 4)
.prologue
.regstk 4, 3, 4, 0
.save ar.pfs,loc0
alloc loc0=ar.pfs,4,3,4,0
.save rp,loc1
mov loc1=rp
.body
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.geu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov ar.pfs=loc0 // restore ar.pfs
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyoutstr)
/*
* Not the fastest bcopy in the world.
*/
ENTRY(bcopy, 3)
XENTRY(ovbcopy)
mov ret0=r0 // return zero for copy{in,out}
;;
cmp.le p6,p0=in2,r0 // bail if len <= 0
(p6) br.ret.spnt.few rp
sub r14=in1,in0 ;; // check for overlap
cmp.ltu p6,p0=r14,in2 // dst-src < len
(p6) br.cond.spnt.few 5f
extr.u r14=in0,0,3 // src & 7
extr.u r15=in1,0,3 ;; // dst & 7
cmp.eq p6,p0=r14,r15 // different alignment?
(p6) br.cond.spnt.few 2f // branch if same alignment
1: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
add in2=-1,in2 ;; // len--
cmp.ne p6,p0=r0,in2
(p6) br.cond.dptk.few 1b // loop
br.ret.sptk.few rp // done
2: cmp.eq p6,p0=r14,r0 // aligned?
(p6) br.cond.sptk.few 4f
3: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
extr.u r15=in0,0,3 // src & 7
add in2=-1,in2 ;; // len--
cmp.eq p6,p0=r0,in2 // done?
cmp.eq p7,p0=r0,r15 ;; // aligned now?
(p6) br.ret.spnt.few rp // return if done
(p7) br.cond.spnt.few 4f // go to main copy
br.cond.sptk.few 3b // more bytes to copy
// At this point, in2 is non-zero
4: mov r14=8 ;;
cmp.ltu p6,p0=in2,r14 ;; // len < 8?
(p6) br.cond.spnt.few 1b // byte copy the end
ld8 r15=[in0],8 ;; // copy word
st8 [in1]=r15,8
add in2=-8,in2 ;; // len -= 8
cmp.ne p6,p0=r0,in2 // done?
(p6) br.cond.spnt.few 4b // again
br.ret.sptk.few rp // return
// Don't bother optimising overlap case
5: add in0=in0,in2
add in1=in1,in2 ;;
add in0=-1,in0
add in1=-1,in1 ;;
6: ld1 r14=[in0],-1 ;;
st1 [in1]=r14,-1
add in2=-1,in2 ;;
cmp.ne p6,p0=r0,in2
(p6) br.cond.spnt.few 6b
br.ret.sptk.few rp
END(bcopy)
ENTRY(memcpy,3)
mov r14=in0 ;;
mov in0=in1 ;;
mov in1=r14
br.cond.sptk.few bcopy
END(memcpy)
ENTRY(copyin, 3)
.prologue
.regstk 4, 3, 4, 0
.save ar.pfs,loc0
alloc loc0=ar.pfs,4,3,4,0
.save rp,loc1
mov loc1=rp
.body
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.geu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov ar.pfs=loc0 // restore ar.pfs
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyin)
ENTRY(copyout, 3)
.prologue
.regstk 4, 3, 4, 0
.save ar.pfs,loc0
alloc loc0=ar.pfs,4,3,4,0
.save rp,loc1
mov loc1=rp
.body
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.geu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=PC_CURTHREAD,r13 // find curthread
;;
ld8 r15=[r15]
;;
add r15=TD_PCB,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov ar.pfs=loc0 // restore ar.pfs
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyout)
ENTRY(copyerr, 0)
add r14=PC_CURTHREAD,r13 ;; // find curthread
ld8 r14=[r14] ;;
add r14=TD_PCB,r14 ;; // curthread->td_addr
ld8 r14=[r14] ;;
add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault
st8 [r14]=r0 // reset fault handler
mov ret0=EFAULT // return EFAULT
br.ret.sptk.few rp
END(copyerr)