dtrace_asm.s revision 0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/dtrace_impl.h>
#else
#include <sys/asm_linkage.h>
#include <sys/privregs.h>
#endif
int
dtrace_getipl(void)
{ return (0); }
#else /* lint */
#endif /* lint */
dtrace_getotherwin(void)
{ return (0); }
#else /* lint */
#endif /* lint */
dtrace_getfprs(void)
{ return (0); }
#else /* lint */
#endif /* lint */
/*ARGSUSED*/
void
{}
#else /* lint */
1:
#endif /* lint */
dtrace_getfp(void)
{ return (0); }
#else /* lint */
#endif /* lint */
void
{}
#else
1:
2:
3:
#endif /* lint */
{
return (old);
}
void *
{
void *old;
return (old);
}
#else /* lint */
#endif /* lint */
#if defined(lint)
/*ARGSUSED*/
dtrace_caller(int aframes)
{
return (0);
}
#else /* lint */
!
!
0:
1:
!
!
#endif
#if defined(lint)
/*ARGSUSED*/
int
{
return (0);
}
#else /* lint */
ba 0f
0:
!
! contained in the register windows.
!
rdpr %canrestore, %g2
cmp %g2, %o0
bl %icc, 2f
rdpr %cwp, %g1
sub %g1, %o0, %g3
brgez,a,pt %g3, 0f
wrpr %g3, %cwp
!
! CWP minus the number of frames is negative; we must perform the
! arithmetic modulo MAXWIN.
!
add %g4, %g3, %g3
inc %g3
wrpr %g3, %cwp
0:
jmp %g5
ba 1f
1:
wrpr %g1, %cwp
stn %g4, [%o2]
retl
clr %o0 ! Success; return 0.
2:
!
!
#endif
#if defined(lint)
/*ARGSUSED*/
void
{}
#else
bz 1f
0:
bl,a 0b
1:
#endif
#if defined(lint)
/*ARGSUSED*/
void
{}
#else
bz 1f
0:
inc %g1 ! Increment offset
cmp %g1, %o2 ! Compare to limit
bl,a 0b ! If less, take another lap
lduba [%o0 + %g1]ASI_USER, %g2 ! delay: load user byte
1:
retl
nop
SET_SIZE(dtrace_copyinstr)
#endif
#if defined(lint)
/*ARGSUSED*/
void
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size)
{}
#else
ENTRY(dtrace_copyout)
tst %o2
bz 1f
clr %g1
ldub [%o0 + %g1], %g2
0:
stba %g2, [%o1 + %g1]ASI_USER
inc %g1
cmp %g1, %o2
bl,a 0b
ldub [%o0 + %g1], %g2
1:
retl
nop
SET_SIZE(dtrace_copyout)
#endif
#if defined(lint)
/*ARGSUSED*/
void
dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size)
{}
#else
ENTRY(dtrace_copyoutstr)
tst %o2
bz 1f
clr %g1
ldub [%o0 + %g1], %g2
0:
stba %g2, [%o1 + %g1]ASI_USER
cmp %g2, 0
be 1f
inc %g1
cmp %g1, %o2
bl,a 0b
ldub [%o0 + %g1], %g2
1:
retl
nop
SET_SIZE(dtrace_copyoutstr)
#endif
#if defined(lint)
/*ARGSUSED*/
uintptr_t
dtrace_fulword(void *addr)
{ return (0); }
#else
ENTRY(dtrace_fulword)
clr %o1
ldna [%o0]ASI_USER, %o1
retl
mov %o1, %o0
SET_SIZE(dtrace_fulword)
#endif
#if defined(lint)
/*ARGSUSED*/
uint8_t
dtrace_fuword8(void *addr)
{ return (0); }
#else
ENTRY(dtrace_fuword8)
clr %o1
lduba [%o0]ASI_USER, %o1
retl
mov %o1, %o0
SET_SIZE(dtrace_fuword8)
#endif
#if defined(lint)
/*ARGSUSED*/
uint16_t
dtrace_fuword16(void *addr)
{ return (0); }
#else
ENTRY(dtrace_fuword16)
clr %o1
lduha [%o0]ASI_USER, %o1
retl
mov %o1, %o0
SET_SIZE(dtrace_fuword16)
#endif
#if defined(lint)
/*ARGSUSED*/
uint32_t
dtrace_fuword32(void *addr)
{ return (0); }
#else
ENTRY(dtrace_fuword32)
clr %o1
lda [%o0]ASI_USER, %o1
retl
mov %o1, %o0
SET_SIZE(dtrace_fuword32)
#endif
#if defined(lint)
/*ARGSUSED*/
uint64_t
dtrace_fuword64(void *addr)
{ return (0); }
#else
ENTRY(dtrace_fuword64)
clr %o1
ldxa [%o0]ASI_USER, %o1
retl
mov %o1, %o0
SET_SIZE(dtrace_fuword64)
#endif
#if defined(lint)
/*ARGSUSED*/
int
dtrace_getupcstack_top(uint64_t *pcstack, int pcstack_limit, uintptr_t *sp)
{ return (0); }
#else
/*
* %g1 pcstack
* %g2 current window
* %g3 maxwin (nwindows - 1)
* %g4 saved %cwp (so we can get back to the original window)
* %g5 iteration count
* %g6 saved %fp
*
* %o0 pcstack / return value (iteration count)
* %o1 pcstack_limit
* %o2 last_fp
*/
ENTRY(dtrace_getupcstack_top)
mov %o0, %g1 ! we need the pcstack pointer while
ld [%g3 + %lo(nwin_minus_one)], %g3 ! it for our modular arithmetic
rdpr %cwp, %g4 ! remember our window so we can return
rdpr %canrestore, %g2 ! compute the first non-user window
subcc %g4, %g2, %g2 ! current = %cwp - %canrestore
bge,pt %xcc, 1f ! good to go if current is >= 0
mov %g5, %o0 ! we need to return the count
add %g2, %g3, %g2 ! normalize our current window if it's
1:
wrpr %g2, %cwp ! change windows
stx %i7, [%g1] ! stash the return address in pcstack
deccc %g5 ! decrement the count
bnz,pt %icc, 1b ! we iterate until the count reaches 0
add %g1, 8, %g1 ! increment the pcstack pointer
mov %i6, %g6 ! stash the last frame pointer we
! encounter so the caller can
! continue the stack walk in memory
wrpr %g4, %cwp ! change back to the original window
stn %g6, [%o2] ! return the last frame pointer
2:
retl
nop
SET_SIZE(dtrace_getupcstack_top)
#endif
#if defined(lint)
/*ARGSUSED*/
int
dtrace_getustackdepth_top(uintptr_t *sp)
{ return (0); }
#else
ENTRY(dtrace_getustackdepth_top)
mov %o0, %o2
rdpr %otherwin, %o0
brlez,a,pn %o0, 2f ! return 0 if there are no user wins
clr %o0
rdpr %cwp, %g4 ! remember our window so we can return
rdpr %canrestore, %g2 ! compute the first user window
sub %g4, %g2, %g2 ! current = %cwp - %canrestore -
subcc %g2, %o0, %g2 ! %otherwin
bge,pt %xcc, 1f ! normalize the window if necessary
sethi %hi(nwin_minus_one), %g3
ld [%g3 + %lo(nwin_minus_one)], %g3
add %g2, %g3, %g2
add %g2, 1, %g2
1:
wrpr %g2, %cwp ! change to the first user window
mov %i6, %g6 ! stash the frame pointer
wrpr %g4, %cwp ! change back to the original window
stn %g6, [%o2] ! return the frame pointer
2:
retl
nop
SET_SIZE(dtrace_getustackdepth_top)
#endif
#if defined(lint) || defined(__lint)
/* ARGSUSED */
ulong_t
dtrace_getreg_win(uint_t reg, uint_t depth)
{ return (0); }
#else /* lint */
ENTRY(dtrace_getreg_win)
sub %o0, 16, %o0
cmp %o0, 16 ! %o0 must begin in the range [16..32)
blu,pt %xcc, 1f
nop
retl
clr %o0
1:
set dtrace_getreg_win_table, %g3
sll %o0, 2, %o0
add %g3, %o0, %g3
rdpr %canrestore, %o3
rdpr %cwp, %g2
! Set %cwp to be (%cwp - %canrestore - %o1) mod NWINDOWS
sub %g2, %o3, %o2 ! %o2 is %cwp - %canrestore
subcc %o2, %o1, %o4
bge,a,pn %xcc, 2f
wrpr %o4, %cwp
sethi %hi(nwin_minus_one), %o3
ld [%o3 + %lo(nwin_minus_one)], %o3
add %o2, %o3, %o4
wrpr %o4, %cwp
2:
jmp %g3
ba 3f
3:
wrpr %g2, %cwp
retl
mov %g1, %o0
dtrace_getreg_win_table:
mov %l0, %g1
mov %l1, %g1
mov %l2, %g1
mov %l3, %g1
mov %l4, %g1
mov %l5, %g1
mov %l6, %g1
mov %l7, %g1
mov %i0, %g1
mov %i1, %g1
mov %i2, %g1
mov %i3, %g1
mov %i4, %g1
mov %i5, %g1
mov %i6, %g1
mov %i7, %g1
SET_SIZE(dtrace_getreg_win)
#endif /* lint */
#if defined(lint) || defined(__lint)
/* ARGSUSED */
void
dtrace_putreg_win(uint_t reg, ulong_t value)
{}
#else /* lint */
ENTRY(dtrace_putreg_win)
sub %o0, 16, %o0
cmp %o0, 16 ! %o0 must be in the range [16..32)
blu,pt %xcc, 1f
nop
retl
nop
1:
mov %o1, %g1 ! move the value into a global register
set dtrace_putreg_table, %g3
sll %o0, 2, %o0
add %g3, %o0, %g3
rdpr %canrestore, %o3
rdpr %cwp, %g2
! Set %cwp to be (%cwp - %canrestore - 1) mod NWINDOWS
sub %g2, %o3, %o2 ! %o2 is %cwp - %canrestore
subcc %o2, 1, %o4
bge,a,pn %xcc, 2f
wrpr %o4, %cwp
sethi %hi(nwin_minus_one), %o3
ld [%o3 + %lo(nwin_minus_one)], %o3
add %o2, %o3, %o4
wrpr %o4, %cwp
2:
jmp %g3
ba 3f
3:
wrpr %g2, %cwp
retl
nop
dtrace_putreg_table:
mov %g1, %l0
mov %g1, %l1
mov %g1, %l2
mov %g1, %l3
mov %g1, %l4
mov %g1, %l5
mov %g1, %l6
mov %g1, %l7
mov %g1, %i0
mov %g1, %i1
mov %g1, %i2
mov %g1, %i3
mov %g1, %i4
mov %g1, %i5
mov %g1, %i6
mov %g1, %i7
SET_SIZE(dtrace_putreg_win)
#endif /* lint */
#if defined(lint) || defined(__lint)
/*ARGSUSED*/
void
dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
int fault, int fltoffs, uintptr_t illval)
{}
#else /* lint */
ENTRY(dtrace_probe_error)
save %sp, -SA(MINFRAME), %sp
sethi %hi(dtrace_probeid_error), %l0
ld [%l0 + %lo(dtrace_probeid_error)], %o0
mov %i0, %o1
mov %i1, %o2
mov %i2, %o3
mov %i3, %o4
call dtrace_probe
mov %i4, %o5
ret
restore
SET_SIZE(dtrace_probe_error)
#endif