#include <sys/param.h>
#include <sys/errno.h>
#include <sys/asm_linkage.h>
#include <sys/vtrace.h>
#include <sys/machthread.h>
#include <sys/clock.h>
#include <sys/asi.h>
#include <sys/fsr.h>
#include <sys/privregs.h>
#include "assym.h"
#define VIS_COPY_THRESHOLD 900
#define SMALL_LIMIT 7
#define FPUSED_FLAG 1
#define BCOPY_FLAG 2
#define COPY_FLAGS (FPUSED_FLAG | BCOPY_FLAG)
#define KPREEMPT_FLAG 4
#define HWCOPYFRAMESIZE ((64 * 5) + (2 * 4))
#define SAVED_FPREGS_OFFSET (64 * 5)
#define SAVED_FPRS_OFFSET (SAVED_FPREGS_OFFSET + 4)
#define SAVED_GSR_OFFSET (SAVED_FPRS_OFFSET + 4)
#define FZERO \
fzero %f0 ;\
fzero %f2 ;\
faddd %f0, %f2, %f4 ;\
fmuld %f0, %f2, %f6 ;\
faddd %f0, %f2, %f8 ;\
fmuld %f0, %f2, %f10 ;\
faddd %f0, %f2, %f12 ;\
fmuld %f0, %f2, %f14 ;\
faddd %f0, %f2, %f16 ;\
fmuld %f0, %f2, %f18 ;\
faddd %f0, %f2, %f20 ;\
fmuld %f0, %f2, %f22 ;\
faddd %f0, %f2, %f24 ;\
fmuld %f0, %f2, %f26 ;\
faddd %f0, %f2, %f28 ;\
fmuld %f0, %f2, %f30 ;\
faddd %f0, %f2, %f32 ;\
fmuld %f0, %f2, %f34 ;\
faddd %f0, %f2, %f36 ;\
fmuld %f0, %f2, %f38 ;\
faddd %f0, %f2, %f40 ;\
fmuld %f0, %f2, %f42 ;\
faddd %f0, %f2, %f44 ;\
fmuld %f0, %f2, %f46 ;\
faddd %f0, %f2, %f48 ;\
fmuld %f0, %f2, %f50 ;\
faddd %f0, %f2, %f52 ;\
fmuld %f0, %f2, %f54 ;\
faddd %f0, %f2, %f56 ;\
fmuld %f0, %f2, %f58 ;\
faddd %f0, %f2, %f60 ;\
fmuld %f0, %f2, %f62
#define FALIGN_D0 \
faligndata %d0, %d2, %d48 ;\
faligndata %d2, %d4, %d50 ;\
faligndata %d4, %d6, %d52 ;\
faligndata %d6, %d8, %d54 ;\
faligndata %d8, %d10, %d56 ;\
faligndata %d10, %d12, %d58 ;\
faligndata %d12, %d14, %d60 ;\
faligndata %d14, %d16, %d62
#define FALIGN_D16 \
faligndata %d16, %d18, %d48 ;\
faligndata %d18, %d20, %d50 ;\
faligndata %d20, %d22, %d52 ;\
faligndata %d22, %d24, %d54 ;\
faligndata %d24, %d26, %d56 ;\
faligndata %d26, %d28, %d58 ;\
faligndata %d28, %d30, %d60 ;\
faligndata %d30, %d32, %d62
#define FALIGN_D32 \
faligndata %d32, %d34, %d48 ;\
faligndata %d34, %d36, %d50 ;\
faligndata %d36, %d38, %d52 ;\
faligndata %d38, %d40, %d54 ;\
faligndata %d40, %d42, %d56 ;\
faligndata %d42, %d44, %d58 ;\
faligndata %d44, %d46, %d60 ;\
faligndata %d46, %d0, %d62
#define FALIGN_D2 \
faligndata %d2, %d4, %d48 ;\
faligndata %d4, %d6, %d50 ;\
faligndata %d6, %d8, %d52 ;\
faligndata %d8, %d10, %d54 ;\
faligndata %d10, %d12, %d56 ;\
faligndata %d12, %d14, %d58 ;\
faligndata %d14, %d16, %d60 ;\
faligndata %d16, %d18, %d62
#define FALIGN_D18 \
faligndata %d18, %d20, %d48 ;\
faligndata %d20, %d22, %d50 ;\
faligndata %d22, %d24, %d52 ;\
faligndata %d24, %d26, %d54 ;\
faligndata %d26, %d28, %d56 ;\
faligndata %d28, %d30, %d58 ;\
faligndata %d30, %d32, %d60 ;\
faligndata %d32, %d34, %d62
#define FALIGN_D34 \
faligndata %d34, %d36, %d48 ;\
faligndata %d36, %d38, %d50 ;\
faligndata %d38, %d40, %d52 ;\
faligndata %d40, %d42, %d54 ;\
faligndata %d42, %d44, %d56 ;\
faligndata %d44, %d46, %d58 ;\
faligndata %d46, %d0, %d60 ;\
faligndata %d0, %d2, %d62
#define FALIGN_D4 \
faligndata %d4, %d6, %d48 ;\
faligndata %d6, %d8, %d50 ;\
faligndata %d8, %d10, %d52 ;\
faligndata %d10, %d12, %d54 ;\
faligndata %d12, %d14, %d56 ;\
faligndata %d14, %d16, %d58 ;\
faligndata %d16, %d18, %d60 ;\
faligndata %d18, %d20, %d62
#define FALIGN_D20 \
faligndata %d20, %d22, %d48 ;\
faligndata %d22, %d24, %d50 ;\
faligndata %d24, %d26, %d52 ;\
faligndata %d26, %d28, %d54 ;\
faligndata %d28, %d30, %d56 ;\
faligndata %d30, %d32, %d58 ;\
faligndata %d32, %d34, %d60 ;\
faligndata %d34, %d36, %d62
#define FALIGN_D36 \
faligndata %d36, %d38, %d48 ;\
faligndata %d38, %d40, %d50 ;\
faligndata %d40, %d42, %d52 ;\
faligndata %d42, %d44, %d54 ;\
faligndata %d44, %d46, %d56 ;\
faligndata %d46, %d0, %d58 ;\
faligndata %d0, %d2, %d60 ;\
faligndata %d2, %d4, %d62
#define FALIGN_D6 \
faligndata %d6, %d8, %d48 ;\
faligndata %d8, %d10, %d50 ;\
faligndata %d10, %d12, %d52 ;\
faligndata %d12, %d14, %d54 ;\
faligndata %d14, %d16, %d56 ;\
faligndata %d16, %d18, %d58 ;\
faligndata %d18, %d20, %d60 ;\
faligndata %d20, %d22, %d62
#define FALIGN_D22 \
faligndata %d22, %d24, %d48 ;\
faligndata %d24, %d26, %d50 ;\
faligndata %d26, %d28, %d52 ;\
faligndata %d28, %d30, %d54 ;\
faligndata %d30, %d32, %d56 ;\
faligndata %d32, %d34, %d58 ;\
faligndata %d34, %d36, %d60 ;\
faligndata %d36, %d38, %d62
#define FALIGN_D38 \
faligndata %d38, %d40, %d48 ;\
faligndata %d40, %d42, %d50 ;\
faligndata %d42, %d44, %d52 ;\
faligndata %d44, %d46, %d54 ;\
faligndata %d46, %d0, %d56 ;\
faligndata %d0, %d2, %d58 ;\
faligndata %d2, %d4, %d60 ;\
faligndata %d4, %d6, %d62
#define FALIGN_D8 \
faligndata %d8, %d10, %d48 ;\
faligndata %d10, %d12, %d50 ;\
faligndata %d12, %d14, %d52 ;\
faligndata %d14, %d16, %d54 ;\
faligndata %d16, %d18, %d56 ;\
faligndata %d18, %d20, %d58 ;\
faligndata %d20, %d22, %d60 ;\
faligndata %d22, %d24, %d62
#define FALIGN_D24 \
faligndata %d24, %d26, %d48 ;\
faligndata %d26, %d28, %d50 ;\
faligndata %d28, %d30, %d52 ;\
faligndata %d30, %d32, %d54 ;\
faligndata %d32, %d34, %d56 ;\
faligndata %d34, %d36, %d58 ;\
faligndata %d36, %d38, %d60 ;\
faligndata %d38, %d40, %d62
#define FALIGN_D40 \
faligndata %d40, %d42, %d48 ;\
faligndata %d42, %d44, %d50 ;\
faligndata %d44, %d46, %d52 ;\
faligndata %d46, %d0, %d54 ;\
faligndata %d0, %d2, %d56 ;\
faligndata %d2, %d4, %d58 ;\
faligndata %d4, %d6, %d60 ;\
faligndata %d6, %d8, %d62
#define FALIGN_D10 \
faligndata %d10, %d12, %d48 ;\
faligndata %d12, %d14, %d50 ;\
faligndata %d14, %d16, %d52 ;\
faligndata %d16, %d18, %d54 ;\
faligndata %d18, %d20, %d56 ;\
faligndata %d20, %d22, %d58 ;\
faligndata %d22, %d24, %d60 ;\
faligndata %d24, %d26, %d62
#define FALIGN_D26 \
faligndata %d26, %d28, %d48 ;\
faligndata %d28, %d30, %d50 ;\
faligndata %d30, %d32, %d52 ;\
faligndata %d32, %d34, %d54 ;\
faligndata %d34, %d36, %d56 ;\
faligndata %d36, %d38, %d58 ;\
faligndata %d38, %d40, %d60 ;\
faligndata %d40, %d42, %d62
#define FALIGN_D42 \
faligndata %d42, %d44, %d48 ;\
faligndata %d44, %d46, %d50 ;\
faligndata %d46, %d0, %d52 ;\
faligndata %d0, %d2, %d54 ;\
faligndata %d2, %d4, %d56 ;\
faligndata %d4, %d6, %d58 ;\
faligndata %d6, %d8, %d60 ;\
faligndata %d8, %d10, %d62
#define FALIGN_D12 \
faligndata %d12, %d14, %d48 ;\
faligndata %d14, %d16, %d50 ;\
faligndata %d16, %d18, %d52 ;\
faligndata %d18, %d20, %d54 ;\
faligndata %d20, %d22, %d56 ;\
faligndata %d22, %d24, %d58 ;\
faligndata %d24, %d26, %d60 ;\
faligndata %d26, %d28, %d62
#define FALIGN_D28 \
faligndata %d28, %d30, %d48 ;\
faligndata %d30, %d32, %d50 ;\
faligndata %d32, %d34, %d52 ;\
faligndata %d34, %d36, %d54 ;\
faligndata %d36, %d38, %d56 ;\
faligndata %d38, %d40, %d58 ;\
faligndata %d40, %d42, %d60 ;\
faligndata %d42, %d44, %d62
#define FALIGN_D44 \
faligndata %d44, %d46, %d48 ;\
faligndata %d46, %d0, %d50 ;\
faligndata %d0, %d2, %d52 ;\
faligndata %d2, %d4, %d54 ;\
faligndata %d4, %d6, %d56 ;\
faligndata %d6, %d8, %d58 ;\
faligndata %d8, %d10, %d60 ;\
faligndata %d10, %d12, %d62
#define FALIGN_D14 \
faligndata %d14, %d16, %d48 ;\
faligndata %d16, %d18, %d50 ;\
faligndata %d18, %d20, %d52 ;\
faligndata %d20, %d22, %d54 ;\
faligndata %d22, %d24, %d56 ;\
faligndata %d24, %d26, %d58 ;\
faligndata %d26, %d28, %d60 ;\
faligndata %d28, %d30, %d62
#define FALIGN_D30 \
faligndata %d30, %d32, %d48 ;\
faligndata %d32, %d34, %d50 ;\
faligndata %d34, %d36, %d52 ;\
faligndata %d36, %d38, %d54 ;\
faligndata %d38, %d40, %d56 ;\
faligndata %d40, %d42, %d58 ;\
faligndata %d42, %d44, %d60 ;\
faligndata %d44, %d46, %d62
#define FALIGN_D46 \
faligndata %d46, %d0, %d48 ;\
faligndata %d0, %d2, %d50 ;\
faligndata %d2, %d4, %d52 ;\
faligndata %d4, %d6, %d54 ;\
faligndata %d6, %d8, %d56 ;\
faligndata %d8, %d10, %d58 ;\
faligndata %d10, %d12, %d60 ;\
faligndata %d12, %d14, %d62
.seg ".text"
.align 4
ENTRY(kcopy)
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
set .copyerr, %l6 ! copyerr is lofault value
ldn [THREAD_REG + T_LOFAULT], %l7 ! save existing handler
membar #Sync ! sync error barrier (see copy.s)
stn %l6, [THREAD_REG + T_LOFAULT] ! set t_lofault
!
! Note that we carefully do *not* flag the setting of
! t_lofault.
!
ba,pt %ncc, .do_copy ! common code
mov %l7, %l6
.copyerr:
set .copyerr2, %l1
membar #Sync ! sync error barrier
stn %l1, [THREAD_REG + T_LOFAULT] ! set t_lofault
btst FPUSED_FLAG, %l6
bz %icc, 1f
and %l6, BCOPY_FLAG, %l1 ! copy flag to %l1
membar #Sync
ld [%fp + STACK_BIAS - SAVED_GSR_OFFSET], %o2 ! restore gsr
wr %o2, 0, %gsr
ld [%fp + STACK_BIAS - SAVED_FPRS_OFFSET], %o3
btst FPRS_FEF, %o3
bz %icc, 4f
nop
! restore fpregs from stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
ldda [%o2]ASI_BLK_P, %d0
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d16
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d32
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d48
membar #Sync
ba,pt %ncc, 2f
wr %o3, 0, %fprs ! restore fprs
4:
FZERO ! zero all of the fpregs
wr %o3, 0, %fprs ! restore fprs
2: ldn [THREAD_REG + T_LWP], %o2
tst %o2
bnz,pt %ncc, 1f
nop
ldsb [THREAD_REG + T_PREEMPT], %l0
deccc %l0
bnz,pn %ncc, 1f
stb %l0, [THREAD_REG + T_PREEMPT]
! Check for a kernel preemption request
ldn [THREAD_REG + T_CPU], %l0
ldub [%l0 + CPU_KPRUNRUN], %l0
tst %l0
bnz,a,pt %ncc, 1f ! Need to call kpreempt?
or %l1, KPREEMPT_FLAG, %l1 ! If so, set the flag
!
! Need to cater for the different expectations of kcopy
! and bcopy. kcopy will *always* set a t_lofault handler
! If it fires, we're expected to just return the error code
! and *not* to invoke any existing error handler. As far as
! bcopy is concerned, we only set t_lofault if there was an
! existing lofault handler. In that case we're expected to
! invoke the previously existing handler after restting the
! t_lofault value.
!
1:
andn %l6, COPY_FLAGS, %l6 ! remove flags from lofault address
membar #Sync ! sync error barrier
stn %l6, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
! call kpreempt if necessary
btst KPREEMPT_FLAG, %l1
bz,pt %icc, 2f
nop
call kpreempt
rdpr %pil, %o0 ! pass %pil
2:
btst BCOPY_FLAG, %l1
bnz,pn %ncc, 3f
nop
ret
restore %g1, 0, %o0
3:
!
! We're here via bcopy. There *must* have been an error handler
! in place otheerwise we would have died a nasty death already.
!
jmp %l6 ! goto real handler
restore %g0, 0, %o0 ! dispose of copy window
fp_panic_msg:
.asciz "Unable to restore fp state after copy operation"
.align 4
.copyerr2:
set fp_panic_msg, %o0
call panic
nop
SET_SIZE(kcopy)
ENTRY(bcopy)
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
ldn [THREAD_REG + T_LOFAULT], %l6 ! save t_lofault
tst %l6
!
! We've already captured whether t_lofault was zero on entry.
! We need to mark ourselves as being from bcopy since both
! kcopy and bcopy use the same code path. If BCOPY_FLAG is set
! and the saved lofault was zero, we won't reset lofault on
! returning.
!
or %l6, BCOPY_FLAG, %l6
bz,pt %ncc, .do_copy
sethi %hi(.copyerr), %o2
or %o2, %lo(.copyerr), %o2
membar #Sync ! sync error barrier
stn %o2, [THREAD_REG + T_LOFAULT] ! install new vector
.do_copy:
cmp %i2, 12 ! for small counts
blu %ncc, .bytecp ! just copy bytes
.empty
cmp %i2, VIS_COPY_THRESHOLD ! for large counts
blu,pt %ncc, .bcb_punt
.empty
!
! Check to see if VIS acceleration is enabled
!
sethi %hi(use_hw_bcopy), %o2
ld [%o2 + %lo(use_hw_bcopy)], %o2
tst %o2
bz,pn %icc, .bcb_punt
nop
subcc %i1, %i0, %i3
bneg,a,pn %ncc, 1f
neg %i3
1:
cmp %i3, 256
blu,pn %ncc, .bcb_punt
nop
ldn [THREAD_REG + T_LWP], %o3
tst %o3
bnz,pt %ncc, 1f
nop
! kpreempt_disable();
ldsb [THREAD_REG + T_PREEMPT], %o2
inc %o2
stb %o2, [THREAD_REG + T_PREEMPT]
1:
rd %fprs, %o2 ! check for unused fp
st %o2, [%fp + STACK_BIAS - SAVED_FPRS_OFFSET] ! save orig %fprs
btst FPRS_FEF, %o2
bz,a %icc, .do_blockcopy
wr %g0, FPRS_FEF, %fprs
.bcb_fpregs_inuse:
cmp %i2, VIS_COPY_THRESHOLD+(64*4) ! for large counts (larger
bgeu %ncc, 1f ! if we have to save the fpregs)
nop
tst %o3
bnz,pt %ncc, .bcb_punt
nop
ldsb [THREAD_REG + T_PREEMPT], %l0
deccc %l0
bnz,pn %icc, .bcb_punt
stb %l0, [THREAD_REG + T_PREEMPT]
! Check for a kernel preemption request
ldn [THREAD_REG + T_CPU], %l0
ldub [%l0 + CPU_KPRUNRUN], %l0
tst %l0
bz,pt %icc, .bcb_punt
nop
! Attempt to preempt
call kpreempt
rdpr %pil, %o0 ! pass %pil
ba,pt %ncc, .bcb_punt
nop
1:
wr %g0, FPRS_FEF, %fprs
! save in-use fpregs on stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
stda %d0, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d16, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d32, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d48, [%o2]ASI_BLK_P
membar #Sync
.do_blockcopy:
membar #StoreStore|#StoreLoad|#LoadStore
rd %gsr, %o2
st %o2, [%fp + STACK_BIAS - SAVED_GSR_OFFSET] ! save gsr
! Set the lower bit in the saved t_lofault to indicate
! that we need to clear the %fprs register on the way
! out
or %l6, FPUSED_FLAG, %l6
! Swap src/dst since the code below is memcpy code
! and memcpy/bcopy have different calling sequences
mov %i1, %i5
mov %i0, %i1
mov %i5, %i0
!!! This code is nearly identical to the version in the sun4u
!!! libc_psr. Most bugfixes made to that file should be
!!! merged into this routine.
andcc %i0, 7, %o3
bz,pt %ncc, blkcpy
sub %o3, 8, %o3
neg %o3
sub %i2, %o3, %i2
! Align Destination on double-word boundary
2: ldub [%i1], %o4
inc %i1
inc %i0
deccc %o3
bgu %ncc, 2b
stb %o4, [%i0 - 1]
blkcpy:
andcc %i0, 63, %i3
bz,pn %ncc, blalign ! now block aligned
sub %i3, 64, %i3
neg %i3 ! bytes till block aligned
sub %i2, %i3, %i2 ! update %i2 with new count
! Copy %i3 bytes till dst is block (64 byte) aligned. use
! double word copies.
alignaddr %i1, %g0, %g1
ldd [%g1], %d0
add %g1, 8, %g1
6:
ldd [%g1], %d2
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d0, %d2, %d8
std %d8, [%i0]
add %i1, 8, %i1
bz,pn %ncc, blalign
add %i0, 8, %i0
ldd [%g1], %d0
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d2, %d0, %d8
std %d8, [%i0]
add %i1, 8, %i1
bgu,pn %ncc, 6b
add %i0, 8, %i0
blalign:
membar #StoreLoad
! %i2 = total length
! %i3 = blocks (length - 64) / 64
! %i4 = doubles remaining (length - blocks)
sub %i2, 64, %i3
andn %i3, 63, %i3
sub %i2, %i3, %i4
andn %i4, 7, %i4
sub %i4, 16, %i4
sub %i2, %i4, %i2
sub %i2, %i3, %i2
andn %i1, 0x3f, %l7 ! blk aligned address
alignaddr %i1, %g0, %g0 ! gen %gsr
srl %i1, 3, %l5 ! bits 3,4,5 are now least sig in %l5
andcc %l5, 7, %i5 ! mask everything except bits 1,2 3
add %i1, %i4, %i1
add %i1, %i3, %i1
ldda [%l7]ASI_BLK_P, %d0
add %l7, 64, %l7
ldda [%l7]ASI_BLK_P, %d16
add %l7, 64, %l7
ldda [%l7]ASI_BLK_P, %d32
add %l7, 64, %l7
sub %i3, 128, %i3
! switch statement to get us to the right 8 byte blk within a
! 64 byte block
cmp %i5, 4
bgeu,a hlf
cmp %i5, 6
cmp %i5, 2
bgeu,a sqtr
nop
cmp %i5, 1
be,a seg1
nop
ba,pt %ncc, seg0
nop
sqtr:
be,a seg2
nop
ba,pt %ncc, seg3
nop
hlf:
bgeu,a fqtr
nop
cmp %i5, 5
be,a seg5
nop
ba,pt %ncc, seg4
nop
fqtr:
be,a seg6
nop
ba,pt %ncc, seg7
nop
seg0:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D0
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D16
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D32
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg0
0:
FALIGN_D16
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D32
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd0
add %i0, 64, %i0
1:
FALIGN_D32
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D0
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd16
add %i0, 64, %i0
2:
FALIGN_D0
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D16
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd32
add %i0, 64, %i0
seg1:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D2
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D18
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D34
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg1
0:
FALIGN_D18
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D34
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd2
add %i0, 64, %i0
1:
FALIGN_D34
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D2
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd18
add %i0, 64, %i0
2:
FALIGN_D2
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D18
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd34
add %i0, 64, %i0
seg2:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D4
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D20
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D36
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg2
0:
FALIGN_D20
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D36
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd4
add %i0, 64, %i0
1:
FALIGN_D36
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D4
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd20
add %i0, 64, %i0
2:
FALIGN_D4
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D20
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd36
add %i0, 64, %i0
seg3:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D6
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D22
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D38
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg3
0:
FALIGN_D22
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D38
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd6
add %i0, 64, %i0
1:
FALIGN_D38
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D6
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd22
add %i0, 64, %i0
2:
FALIGN_D6
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D22
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd38
add %i0, 64, %i0
seg4:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D8
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D24
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D40
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg4
0:
FALIGN_D24
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D40
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd8
add %i0, 64, %i0
1:
FALIGN_D40
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D8
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd24
add %i0, 64, %i0
2:
FALIGN_D8
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D24
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd40
add %i0, 64, %i0
seg5:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D10
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D26
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D42
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg5
0:
FALIGN_D26
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D42
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd10
add %i0, 64, %i0
1:
FALIGN_D42
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D10
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd26
add %i0, 64, %i0
2:
FALIGN_D10
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D26
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd42
add %i0, 64, %i0
seg6:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D12
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D28
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D44
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg6
0:
FALIGN_D28
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D44
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd12
add %i0, 64, %i0
1:
FALIGN_D44
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D12
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd28
add %i0, 64, %i0
2:
FALIGN_D12
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D28
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd44
add %i0, 64, %i0
seg7:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D14
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D30
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D46
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, seg7
0:
FALIGN_D30
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D46
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd14
add %i0, 64, %i0
1:
FALIGN_D46
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D14
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd30
add %i0, 64, %i0
2:
FALIGN_D14
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D30
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, blkd46
add %i0, 64, %i0
!
! dribble out the last partial block
!
blkd0:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d0, %d2, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd2:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d2, %d4, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd4:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d4, %d6, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd6:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d6, %d8, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd8:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d8, %d10, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd10:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d10, %d12, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd12:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d12, %d14, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd14:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
fsrc1 %d14, %d0
ba,a,pt %ncc, blkleft
blkd16:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d16, %d18, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd18:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d18, %d20, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd20:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d20, %d22, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd22:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d22, %d24, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd24:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d24, %d26, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd26:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d26, %d28, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd28:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d28, %d30, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd30:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
fsrc1 %d30, %d0
ba,a,pt %ncc, blkleft
blkd32:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d32, %d34, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd34:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d34, %d36, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd36:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d36, %d38, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd38:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d38, %d40, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd40:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d40, %d42, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd42:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d42, %d44, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd44:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
faligndata %d44, %d46, %d48
std %d48, [%i0]
add %i0, 8, %i0
blkd46:
subcc %i4, 8, %i4
blu,pn %ncc, blkdone
fsrc1 %d46, %d0
blkleft:
1:
ldd [%l7], %d2
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d0, %d2, %d8
std %d8, [%i0]
blu,pn %ncc, blkdone
add %i0, 8, %i0
ldd [%l7], %d0
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d2, %d0, %d8
std %d8, [%i0]
bgeu,pt %ncc, 1b
add %i0, 8, %i0
blkdone:
tst %i2
bz,pt %ncc, .bcb_exit
and %l3, 0x4, %l3 ! fprs.du = fprs.dl = 0
7: ldub [%i1], %i4
inc %i1
inc %i0
deccc %i2
bgu,pt %ncc, 7b
stb %i4, [%i0 - 1]
.bcb_exit:
membar #StoreLoad|#StoreStore
btst FPUSED_FLAG, %l6
bz %icc, 1f
and %l6, COPY_FLAGS, %l1 ! Store flags in %l1
! We can't clear the flags from %l6 yet.
! If there's an error, .copyerr will
! need them
ld [%fp + STACK_BIAS - SAVED_GSR_OFFSET], %o2 ! restore gsr
wr %o2, 0, %gsr
ld [%fp + STACK_BIAS - SAVED_FPRS_OFFSET], %o3
btst FPRS_FEF, %o3
bz %icc, 4f
nop
! restore fpregs from stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
ldda [%o2]ASI_BLK_P, %d0
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d16
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d32
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d48
membar #Sync
ba,pt %ncc, 2f
wr %o3, 0, %fprs ! restore fprs
4:
FZERO ! zero all of the fpregs
wr %o3, 0, %fprs ! restore fprs
2: ldn [THREAD_REG + T_LWP], %o2
tst %o2
bnz,pt %ncc, 1f
nop
ldsb [THREAD_REG + T_PREEMPT], %l0
deccc %l0
bnz,pn %ncc, 1f
stb %l0, [THREAD_REG + T_PREEMPT]
! Check for a kernel preemption request
ldn [THREAD_REG + T_CPU], %l0
ldub [%l0 + CPU_KPRUNRUN], %l0
tst %l0
bnz,a,pt %ncc, 1f ! Need to call kpreempt?
or %l1, KPREEMPT_FLAG, %l1 ! If so, set the flag
1:
btst BCOPY_FLAG, %l1
bz,pn %icc, 3f
andncc %l6, COPY_FLAGS, %l6
!
! Here via bcopy. Check to see if the handler was NULL.
! If so, just return quietly. Otherwise, reset the
! handler and go home.
!
bnz,pn %ncc, 3f
nop
!
! Null handler. Check for kpreempt flag, call if necessary,
! then return.
!
btst KPREEMPT_FLAG, %l1
bz,pt %icc, 2f
nop
call kpreempt
rdpr %pil, %o0 ! pass %pil
2:
ret
restore %g0, 0, %o0
!
! Here via kcopy or bcopy with a handler.Reset the
! fault handler.
!
3:
membar #Sync
stn %l6, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
! call kpreempt if necessary
btst KPREEMPT_FLAG, %l1
bz,pt %icc, 4f
nop
call kpreempt
rdpr %pil, %o0
4:
ret
restore %g0, 0, %o0
.bcb_punt:
!
! use aligned transfers where possible
!
xor %i0, %i1, %o4 ! xor from and to address
btst 7, %o4 ! if lower three bits zero
bz %icc, .aldoubcp ! can align on double boundary
.empty ! assembler complaints about label
xor %i0, %i1, %o4 ! xor from and to address
btst 3, %o4 ! if lower two bits zero
bz %icc, .alwordcp ! can align on word boundary
btst 3, %i0 ! delay slot, from address unaligned?
!
! use aligned reads and writes where possible
! this differs from wordcp in that it copes
! with odd alignment between source and destnation
! using word reads and writes with the proper shifts
! in between to align transfers to and from memory
! i0 - src address, i1 - dest address, i2 - count
! i3, i4 - tmps for used generating complete word
! i5 (word to write)
! l0 size in bits of upper part of source word (US)
! l1 size in bits of lower part of source word (LS = 32 - US)
! l2 size in bits of upper part of destination word (UD)
! l3 size in bits of lower part of destination word (LD = 32 - UD)
! l4 number of bytes leftover after aligned transfers complete
! l5 the number 32
!
mov 32, %l5 ! load an oft-needed constant
bz .align_dst_only
btst 3, %i1 ! is destnation address aligned?
clr %i4 ! clear registers used in either case
bz %icc, .align_src_only
clr %l0
!
! both source and destination addresses are unaligned
!
1: ! align source
ldub [%i0], %i3 ! read a byte from source address
add %i0, 1, %i0 ! increment source address
or %i4, %i3, %i4 ! or in with previous bytes (if any)
btst 3, %i0 ! is source aligned?
add %l0, 8, %l0 ! increment size of upper source (US)
bnz,a 1b
sll %i4, 8, %i4 ! make room for next byte
sub %l5, %l0, %l1 ! generate shift left count (LS)
sll %i4, %l1, %i4 ! prepare to get rest
ld [%i0], %i3 ! read a word
add %i0, 4, %i0 ! increment source address
srl %i3, %l0, %i5 ! upper src bits into lower dst bits
or %i4, %i5, %i5 ! merge
mov 24, %l3 ! align destination
1:
srl %i5, %l3, %i4 ! prepare to write a single byte
stb %i4, [%i1] ! write a byte
add %i1, 1, %i1 ! increment destination address
sub %i2, 1, %i2 ! decrement count
btst 3, %i1 ! is destination aligned?
bnz,a 1b
sub %l3, 8, %l3 ! delay slot, decrement shift count (LD)
sub %l5, %l3, %l2 ! generate shift left count (UD)
sll %i5, %l2, %i5 ! move leftover into upper bytes
cmp %l2, %l0 ! cmp # reqd to fill dst w old src left
bgu %ncc, .more_needed ! need more to fill than we have
nop
sll %i3, %l1, %i3 ! clear upper used byte(s)
srl %i3, %l1, %i3
! get the odd bytes between alignments
sub %l0, %l2, %l0 ! regenerate shift count
sub %l5, %l0, %l1 ! generate new shift left count (LS)
and %i2, 3, %l4 ! must do remaining bytes if count%4 > 0
andn %i2, 3, %i2 ! # of aligned bytes that can be moved
srl %i3, %l0, %i4
or %i5, %i4, %i5
st %i5, [%i1] ! write a word
subcc %i2, 4, %i2 ! decrement count
bz %ncc, .unalign_out
add %i1, 4, %i1 ! increment destination address
b 2f
sll %i3, %l1, %i5 ! get leftover into upper bits
.more_needed:
sll %i3, %l0, %i3 ! save remaining byte(s)
srl %i3, %l0, %i3
sub %l2, %l0, %l1 ! regenerate shift count
sub %l5, %l1, %l0 ! generate new shift left count
sll %i3, %l1, %i4 ! move to fill empty space
b 3f
or %i5, %i4, %i5 ! merge to complete word
!
! the source address is aligned and destination is not
!
.align_dst_only:
ld [%i0], %i4 ! read a word
add %i0, 4, %i0 ! increment source address
mov 24, %l0 ! initial shift alignment count
1:
srl %i4, %l0, %i3 ! prepare to write a single byte
stb %i3, [%i1] ! write a byte
add %i1, 1, %i1 ! increment destination address
sub %i2, 1, %i2 ! decrement count
btst 3, %i1 ! is destination aligned?
bnz,a 1b
sub %l0, 8, %l0 ! delay slot, decrement shift count
.xfer:
sub %l5, %l0, %l1 ! generate shift left count
sll %i4, %l1, %i5 ! get leftover
3:
and %i2, 3, %l4 ! must do remaining bytes if count%4 > 0
andn %i2, 3, %i2 ! # of aligned bytes that can be moved
2:
ld [%i0], %i3 ! read a source word
add %i0, 4, %i0 ! increment source address
srl %i3, %l0, %i4 ! upper src bits into lower dst bits
or %i5, %i4, %i5 ! merge with upper dest bits (leftover)
st %i5, [%i1] ! write a destination word
subcc %i2, 4, %i2 ! decrement count
bz %ncc, .unalign_out ! check if done
add %i1, 4, %i1 ! increment destination address
b 2b ! loop
sll %i3, %l1, %i5 ! get leftover
.unalign_out:
tst %l4 ! any bytes leftover?
bz %ncc, .cpdone
.empty ! allow next instruction in delay slot
1:
sub %l0, 8, %l0 ! decrement shift
srl %i3, %l0, %i4 ! upper src byte into lower dst byte
stb %i4, [%i1] ! write a byte
subcc %l4, 1, %l4 ! decrement count
bz %ncc, .cpdone ! done?
add %i1, 1, %i1 ! increment destination
tst %l0 ! any more previously read bytes
bnz %ncc, 1b ! we have leftover bytes
mov %l4, %i2 ! delay slot, mv cnt where dbytecp wants
b .dbytecp ! let dbytecp do the rest
sub %i0, %i1, %i0 ! i0 gets the difference of src and dst
!
! the destination address is aligned and the source is not
!
.align_src_only:
ldub [%i0], %i3 ! read a byte from source address
add %i0, 1, %i0 ! increment source address
or %i4, %i3, %i4 ! or in with previous bytes (if any)
btst 3, %i0 ! is source aligned?
add %l0, 8, %l0 ! increment shift count (US)
bnz,a .align_src_only
sll %i4, 8, %i4 ! make room for next byte
b,a .xfer
!
! if from address unaligned for double-word moves,
! move bytes till it is, if count is < 56 it could take
! longer to align the thing than to do the transfer
! in word size chunks right away
!
.aldoubcp:
cmp %i2, 56 ! if count < 56, use wordcp, it takes
blu,a %ncc, .alwordcp ! longer to align doubles than words
mov 3, %o0 ! mask for word alignment
call .alignit ! copy bytes until aligned
mov 7, %o0 ! mask for double alignment
!
! source and destination are now double-word aligned
! i3 has aligned count returned by alignit
!
and %i2, 7, %i2 ! unaligned leftover count
sub %i0, %i1, %i0 ! i0 gets the difference of src and dst
5:
ldx [%i0+%i1], %o4 ! read from address
stx %o4, [%i1] ! write at destination address
subcc %i3, 8, %i3 ! dec count
bgu %ncc, 5b
add %i1, 8, %i1 ! delay slot, inc to address
cmp %i2, 4 ! see if we can copy a word
blu %ncc, .dbytecp ! if 3 or less bytes use bytecp
.empty
!
! for leftover bytes we fall into wordcp, if needed
!
.wordcp:
and %i2, 3, %i2 ! unaligned leftover count
5:
ld [%i0+%i1], %o4 ! read from address
st %o4, [%i1] ! write at destination address
subcc %i3, 4, %i3 ! dec count
bgu %ncc, 5b
add %i1, 4, %i1 ! delay slot, inc to address
b,a .dbytecp
! we come here to align copies on word boundaries
.alwordcp:
call .alignit ! go word-align it
mov 3, %o0 ! bits that must be zero to be aligned
b .wordcp
sub %i0, %i1, %i0 ! i0 gets the difference of src and dst
!
! byte copy, works with any alignment
!
.bytecp:
b .dbytecp
sub %i0, %i1, %i0 ! i0 gets difference of src and dst
!
! differenced byte copy, works with any alignment
! assumes dest in %i1 and (source - dest) in %i0
!
1:
stb %o4, [%i1] ! write to address
inc %i1 ! inc to address
.dbytecp:
deccc %i2 ! dec count
bgeu,a %ncc, 1b ! loop till done
ldub [%i0+%i1], %o4 ! read from address
!
! FPUSED_FLAG will not have been set in any path leading to
! this point. No need to deal with it.
!
.cpdone:
btst BCOPY_FLAG, %l6
bz,pn %icc, 2f
andncc %l6, BCOPY_FLAG, %l6
!
! Here via bcopy. Check to see if the handler was NULL.
! If so, just return quietly. Otherwise, reset the
! handler and go home.
!
bnz,pn %ncc, 2f
nop
!
! Null handler.
!
ret
restore %g0, 0, %o0
!
! Here via kcopy or bcopy with a handler.Reset the
! fault handler.
!
2:
membar #Sync
stn %l6, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
ret
restore %g0, 0, %o0 ! return (0)
1:
inc %i0 ! inc from
stb %o4, [%i1] ! write a byte
inc %i1 ! inc to
dec %i2 ! dec count
.alignit:
btst %o0, %i0 ! %o0 is bit mask to check for alignment
bnz,a 1b
ldub [%i0], %o4 ! read next byte
retl
andn %i2, %o0, %i3 ! return size of aligned bytes
SET_SIZE(bcopy)
ENTRY(ovbcopy)
tst %o2 ! check count
bgu,a %ncc, 1f ! nothing to do or bad arguments
subcc %o0, %o1, %o3 ! difference of from and to address
retl ! return
nop
1:
bneg,a %ncc, 2f
neg %o3 ! if < 0, make it positive
2: cmp %o2, %o3 ! cmp size and abs(from - to)
bleu %ncc, bcopy ! if size <= abs(diff): use bcopy,
.empty ! no overlap
cmp %o0, %o1 ! compare from and to addresses
blu %ncc, .ov_bkwd ! if from < to, copy backwards
nop
!
! Copy forwards.
!
.ov_fwd:
ldub [%o0], %o3 ! read from address
inc %o0 ! inc from address
stb %o3, [%o1] ! write to address
deccc %o2 ! dec count
bgu %ncc, .ov_fwd ! loop till done
inc %o1 ! inc to address
retl ! return
nop
!
! Copy backwards.
!
.ov_bkwd:
deccc %o2 ! dec count
ldub [%o0 + %o2], %o3 ! get byte at end of src
bgu %ncc, .ov_bkwd ! loop till done
stb %o3, [%o1 + %o2] ! delay slot, store at end of dst
retl ! return
nop
SET_SIZE(ovbcopy)
ENTRY(hwblkpagecopy)
! get another window w/space for three aligned blocks of saved fpregs
save %sp, -SA(MINFRAME + 4*64), %sp
! %i0 - source address (arg)
! %i1 - destination address (arg)
! %i2 - length of region (not arg)
! %l0 - saved fprs
! %l1 - pointer to saved fpregs
rd %fprs, %l0 ! check for unused fp
btst FPRS_FEF, %l0
bz 1f
membar #Sync
! save in-use fpregs on stack
add %fp, STACK_BIAS - 193, %l1
and %l1, -64, %l1
stda %d0, [%l1]ASI_BLK_P
add %l1, 64, %l3
stda %d16, [%l3]ASI_BLK_P
add %l3, 64, %l3
stda %d32, [%l3]ASI_BLK_P
membar #Sync
1: wr %g0, FPRS_FEF, %fprs
ldda [%i0]ASI_BLK_P, %d0
add %i0, 64, %i0
set PAGESIZE - 64, %i2
2: ldda [%i0]ASI_BLK_P, %d16
fsrc1 %d0, %d32
fsrc1 %d2, %d34
fsrc1 %d4, %d36
fsrc1 %d6, %d38
fsrc1 %d8, %d40
fsrc1 %d10, %d42
fsrc1 %d12, %d44
fsrc1 %d14, %d46
stda %d32, [%i1]ASI_BLK_P
add %i0, 64, %i0
subcc %i2, 64, %i2
bz,pn %ncc, 3f
add %i1, 64, %i1
ldda [%i0]ASI_BLK_P, %d0
fsrc1 %d16, %d32
fsrc1 %d18, %d34
fsrc1 %d20, %d36
fsrc1 %d22, %d38
fsrc1 %d24, %d40
fsrc1 %d26, %d42
fsrc1 %d28, %d44
fsrc1 %d30, %d46
stda %d32, [%i1]ASI_BLK_P
add %i0, 64, %i0
sub %i2, 64, %i2
ba,pt %ncc, 2b
add %i1, 64, %i1
3: membar #Sync
btst FPRS_FEF, %l0
bz 4f
stda %d16, [%i1]ASI_BLK_P
! restore fpregs from stack
membar #Sync
ldda [%l1]ASI_BLK_P, %d0
add %l1, 64, %l3
ldda [%l3]ASI_BLK_P, %d16
add %l3, 64, %l3
ldda [%l3]ASI_BLK_P, %d32
4: wr %l0, 0, %fprs ! restore fprs
membar #Sync
ret
restore %g0, 0, %o0
SET_SIZE(hwblkpagecopy)
#define SAVE_SRC %g2
#define SAVE_DST %g3
#define SAVE_COUNT %g4
#define REAL_LOFAULT %g5
#define SAVED_LOFAULT %g6
ENTRY(copyio_fault)
btst FPUSED_FLAG, SAVED_LOFAULT
bz 1f
andn SAVED_LOFAULT, FPUSED_FLAG, SAVED_LOFAULT
membar #Sync
ld [%fp + STACK_BIAS - SAVED_GSR_OFFSET], %o2
wr %o2, 0, %gsr ! restore gsr
ld [%fp + STACK_BIAS - SAVED_FPRS_OFFSET], %o3
btst FPRS_FEF, %o3
bz 4f
nop
! restore fpregs from stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
ldda [%o2]ASI_BLK_P, %d0
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d16
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d32
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d48
membar #Sync
ba,pt %ncc, 1f
wr %o3, 0, %fprs ! restore fprs
4:
FZERO ! zero all of the fpregs
wr %o3, 0, %fprs ! restore fprs
1:
restore
mov SAVE_SRC, %o0
mov SAVE_DST, %o1
jmp REAL_LOFAULT
mov SAVE_COUNT, %o2
SET_SIZE(copyio_fault)
ENTRY(copyio_fault_nowindow)
membar #Sync
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
mov SAVE_SRC, %o0
mov SAVE_DST, %o1
jmp REAL_LOFAULT
mov SAVE_COUNT, %o2
SET_SIZE(copyio_fault_nowindow)
ENTRY(copyout)
sethi %hi(.copyout_err), REAL_LOFAULT
or REAL_LOFAULT, %lo(.copyout_err), REAL_LOFAULT
.do_copyout:
!
! Check the length and bail if zero.
!
tst %o2
bnz,pt %ncc, 1f
nop
retl
clr %o0
1:
sethi %hi(copyio_fault), %o4
or %o4, %lo(copyio_fault), %o4
sethi %hi(copyio_fault_nowindow), %o3
ldn [THREAD_REG + T_LOFAULT], SAVED_LOFAULT
or %o3, %lo(copyio_fault_nowindow), %o3
membar #Sync
stn %o3, [THREAD_REG + T_LOFAULT]
mov %o0, SAVE_SRC
mov %o1, SAVE_DST
mov %o2, SAVE_COUNT
!
! Check to see if we're more than SMALL_LIMIT (7 bytes).
! Run in leaf mode, using the %o regs as our input regs.
!
subcc %o2, SMALL_LIMIT, %o3
bgu,a,pt %ncc, .dco_ns
or %o0, %o1, %o3
!
! What was previously ".small_copyout"
! Do full differenced copy.
!
.dcobcp:
sub %g0, %o2, %o3 ! negate count
add %o0, %o2, %o0 ! make %o0 point at the end
add %o1, %o2, %o1 ! make %o1 point at the end
ba,pt %ncc, .dcocl
ldub [%o0 + %o3], %o4 ! load first byte
!
! %o0 and %o2 point at the end and remain pointing at the end
! of their buffers. We pull things out by adding %o3 (which is
! the negation of the length) to the buffer end which gives us
! the curent location in the buffers. By incrementing %o3 we walk
! through both buffers without having to bump each buffer's
! pointer. A very fast 4 instruction loop.
!
.align 16
.dcocl:
stba %o4, [%o1 + %o3]ASI_USER
inccc %o3
bl,a,pt %ncc, .dcocl
ldub [%o0 + %o3], %o4
!
! We're done. Go home.
!
membar #Sync
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]
retl
clr %o0
!
! Try aligned copies from here.
!
.dco_ns:
! %o0 = kernel addr (to be copied from)
! %o1 = user addr (to be copied to)
! %o2 = length
! %o3 = %o1 | %o2 (used for alignment checking)
! %o4 is alternate lo_fault
! %o5 is original lo_fault
!
! See if we're single byte aligned. If we are, check the
! limit for single byte copies. If we're smaller or equal,
! bounce to the byte for byte copy loop. Otherwise do it in
! HW (if enabled).
!
btst 1, %o3
bz,pt %icc, .dcoh8
btst 7, %o3
!
! Single byte aligned. Do we do it via HW or via
! byte for byte? Do a quick no memory reference
! check to pick up small copies.
!
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcobcp
sethi %hi(hw_copy_limit_1), %o3
!
! Big enough that we need to check the HW limit for
! this size copy.
!
ld [%o3 + %lo(hw_copy_limit_1)], %o3
!
! Is HW copy on? If not, do everything byte for byte.
!
tst %o3
bz,pn %icc, .dcobcp
subcc %o3, %o2, %o3
!
! If we're less than or equal to the single byte copy limit,
! bop to the copy loop.
!
bge,pt %ncc, .dcobcp
nop
!
! We're big enough and copy is on. Do it with HW.
!
ba,pt %ncc, .big_copyout
nop
.dcoh8:
!
! 8 byte aligned?
!
bnz,a %ncc, .dcoh4
btst 3, %o3
!
! See if we're in the "small range".
! If so, go off and do the copy.
! If not, load the hard limit. %o3 is
! available for reuse.
!
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcos8
sethi %hi(hw_copy_limit_8), %o3
ld [%o3 + %lo(hw_copy_limit_8)], %o3
!
! If it's zero, there's no HW bcopy.
! Bop off to the aligned copy.
!
tst %o3
bz,pn %icc, .dcos8
subcc %o3, %o2, %o3
!
! We're negative if our size is larger than hw_copy_limit_8.
!
bge,pt %ncc, .dcos8
nop
!
! HW assist is on and we're large enough. Do it.
!
ba,pt %ncc, .big_copyout
nop
.dcos8:
!
! Housekeeping for copy loops. Uses same idea as in the byte for
! byte copy loop above.
!
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .dodebc
srl %o2, 3, %o2 ! Number of 8 byte chunks to copy
!
! 4 byte aligned?
!
.dcoh4:
bnz,pn %ncc, .dcoh2
!
! See if we're in the "small range".
! If so, go off an do the copy.
! If not, load the hard limit. %o3 is
! available for reuse.
!
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcos4
sethi %hi(hw_copy_limit_4), %o3
ld [%o3 + %lo(hw_copy_limit_4)], %o3
!
! If it's zero, there's no HW bcopy.
! Bop off to the aligned copy.
!
tst %o3
bz,pn %icc, .dcos4
subcc %o3, %o2, %o3
!
! We're negative if our size is larger than hw_copy_limit_4.
!
bge,pt %ncc, .dcos4
nop
!
! HW assist is on and we're large enough. Do it.
!
ba,pt %ncc, .big_copyout
nop
.dcos4:
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .dodfbc
srl %o2, 2, %o2 ! Number of 4 byte chunks to copy
!
! We must be 2 byte aligned. Off we go.
! The check for small copies was done in the
! delay at .dcoh4
!
.dcoh2:
ble %ncc, .dcos2
sethi %hi(hw_copy_limit_2), %o3
ld [%o3 + %lo(hw_copy_limit_2)], %o3
tst %o3
bz,pn %icc, .dcos2
subcc %o3, %o2, %o3
bge,pt %ncc, .dcos2
nop
!
! HW is on and we're big enough. Do it.
!
ba,pt %ncc, .big_copyout
nop
.dcos2:
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .dodtbc
srl %o2, 1, %o2 ! Number of 2 byte chunks to copy
.small_copyout:
!
! Why are we doing this AGAIN? There are certain conditions in
! big_copyout that will cause us to forego the HW assisted copies
! and bounce back to a non-HW assisted copy. This dispatches those
! copies. Note that we branch around this in the main line code.
!
! We make no check for limits or HW enablement here. We've
! already been told that we're a poster child so just go off
! and do it.
!
or %o0, %o1, %o3
btst 1, %o3
bnz %icc, .dcobcp ! Most likely
btst 7, %o3
bz %icc, .dcos8
btst 3, %o3
bz %icc, .dcos4
nop
ba,pt %ncc, .dcos2
nop
.align 32
.dodebc:
ldx [%o0 + %o3], %o4
deccc %o2
stxa %o4, [%o1 + %o3]ASI_USER
bg,pt %ncc, .dodebc
addcc %o3, 8, %o3
!
! End of copy loop. Check to see if we're done. Most
! eight byte aligned copies end here.
!
bz,pt %ncc, .dcofh
nop
!
! Something is left - do it byte for byte.
!
ba,pt %ncc, .dcocl
ldub [%o0 + %o3], %o4 ! load next byte
!
! Four byte copy loop. %o2 is the number of 4 byte chunks to copy.
!
.align 32
.dodfbc:
lduw [%o0 + %o3], %o4
deccc %o2
sta %o4, [%o1 + %o3]ASI_USER
bg,pt %ncc, .dodfbc
addcc %o3, 4, %o3
!
! End of copy loop. Check to see if we're done. Most
! four byte aligned copies end here.
!
bz,pt %ncc, .dcofh
nop
!
! Something is left. Do it byte for byte.
!
ba,pt %ncc, .dcocl
ldub [%o0 + %o3], %o4 ! load next byte
!
! two byte aligned copy loop. %o2 is the number of 2 byte chunks to
! copy.
!
.align 32
.dodtbc:
lduh [%o0 + %o3], %o4
deccc %o2
stha %o4, [%o1 + %o3]ASI_USER
bg,pt %ncc, .dodtbc
addcc %o3, 2, %o3
!
! End of copy loop. Anything left?
!
bz,pt %ncc, .dcofh
nop
!
! Deal with the last byte
!
ldub [%o0 + %o3], %o4
stba %o4, [%o1 + %o3]ASI_USER
.dcofh:
membar #Sync
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
retl
clr %o0
.big_copyout:
!
! Are we using the FP registers?
!
rd %fprs, %o3 ! check for unused fp
btst FPRS_FEF, %o3
bnz %icc, .copyout_fpregs_inuse
nop
!
! We're going to go off and do a block copy.
! Switch fault hendlers and grab a window. We
! don't do a membar #Sync since we've done only
! kernel data to this point.
!
stn %o4, [THREAD_REG + T_LOFAULT]
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
!
! %o3 is now %i3. Save original %fprs.
!
st %i3, [%fp + STACK_BIAS - SAVED_FPRS_OFFSET]
ba,pt %ncc, .do_block_copyout ! Not in use. Go off and do it.
wr %g0, FPRS_FEF, %fprs ! clear %fprs
!
.copyout_fpregs_inuse:
!
! We're here if the FP regs are in use. Need to see if the request
! exceeds our suddenly larger minimum.
!
cmp %i2, VIS_COPY_THRESHOLD+(64*4) ! for large counts (larger
bl %ncc, .small_copyout
nop
!
! We're going to go off and do a block copy.
! Change to the heavy duty fault handler and grab a window first.
!
stn %o4, [THREAD_REG + T_LOFAULT]
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
st %i3, [%fp + STACK_BIAS - SAVED_FPRS_OFFSET]
!
! save in-use fpregs on stack
!
wr %g0, FPRS_FEF, %fprs
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
stda %d0, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d16, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d32, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d48, [%o2]ASI_BLK_P
membar #Sync
.do_block_copyout:
membar #StoreStore|#StoreLoad|#LoadStore
rd %gsr, %o2
st %o2, [%fp + STACK_BIAS - SAVED_GSR_OFFSET] ! save gsr
! Set the lower bit in the saved t_lofault to indicate
! that we need to clear the %fprs register on the way
! out
or SAVED_LOFAULT, FPUSED_FLAG, SAVED_LOFAULT
! Swap src/dst since the code below is memcpy code
! and memcpy/bcopy have different calling sequences
mov %i1, %i5
mov %i0, %i1
mov %i5, %i0
!!! This code is nearly identical to the version in the sun4u
!!! libc_psr. Most bugfixes made to that file should be
!!! merged into this routine.
andcc %i0, 7, %o3
bz %ncc, copyout_blkcpy
sub %o3, 8, %o3
neg %o3
sub %i2, %o3, %i2
! Align Destination on double-word boundary
2: ldub [%i1], %o4
inc %i1
stba %o4, [%i0]ASI_USER
deccc %o3
bgu %ncc, 2b
inc %i0
copyout_blkcpy:
andcc %i0, 63, %i3
bz,pn %ncc, copyout_blalign ! now block aligned
sub %i3, 64, %i3
neg %i3 ! bytes till block aligned
sub %i2, %i3, %i2 ! update %i2 with new count
! Copy %i3 bytes till dst is block (64 byte) aligned. use
! double word copies.
alignaddr %i1, %g0, %g1
ldd [%g1], %d0
add %g1, 8, %g1
6:
ldd [%g1], %d2
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d0, %d2, %d8
stda %d8, [%i0]ASI_USER
add %i1, 8, %i1
bz,pn %ncc, copyout_blalign
add %i0, 8, %i0
ldd [%g1], %d0
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d2, %d0, %d8
stda %d8, [%i0]ASI_USER
add %i1, 8, %i1
bgu,pn %ncc, 6b
add %i0, 8, %i0
copyout_blalign:
membar #StoreLoad
! %i2 = total length
! %i3 = blocks (length - 64) / 64
! %i4 = doubles remaining (length - blocks)
sub %i2, 64, %i3
andn %i3, 63, %i3
sub %i2, %i3, %i4
andn %i4, 7, %i4
sub %i4, 16, %i4
sub %i2, %i4, %i2
sub %i2, %i3, %i2
andn %i1, 0x3f, %l7 ! blk aligned address
alignaddr %i1, %g0, %g0 ! gen %gsr
srl %i1, 3, %l5 ! bits 3,4,5 are now least sig in %l5
andcc %l5, 7, %i5 ! mask everything except bits 1,2 3
add %i1, %i4, %i1
add %i1, %i3, %i1
ldda [%l7]ASI_BLK_P, %d0
add %l7, 64, %l7
ldda [%l7]ASI_BLK_P, %d16
add %l7, 64, %l7
ldda [%l7]ASI_BLK_P, %d32
add %l7, 64, %l7
sub %i3, 128, %i3
! switch statement to get us to the right 8 byte blk within a
! 64 byte block
cmp %i5, 4
bgeu,a copyout_hlf
cmp %i5, 6
cmp %i5, 2
bgeu,a copyout_sqtr
nop
cmp %i5, 1
be,a copyout_seg1
nop
ba,pt %ncc, copyout_seg0
nop
copyout_sqtr:
be,a copyout_seg2
nop
ba,pt %ncc, copyout_seg3
nop
copyout_hlf:
bgeu,a copyout_fqtr
nop
cmp %i5, 5
be,a copyout_seg5
nop
ba,pt %ncc, copyout_seg4
nop
copyout_fqtr:
be,a copyout_seg6
nop
ba,pt %ncc, copyout_seg7
nop
copyout_seg0:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D0
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D16
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D32
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg0
0:
FALIGN_D16
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D32
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd0
add %i0, 64, %i0
1:
FALIGN_D32
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D0
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd16
add %i0, 64, %i0
2:
FALIGN_D0
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D16
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd32
add %i0, 64, %i0
copyout_seg1:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D2
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D18
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D34
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg1
0:
FALIGN_D18
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D34
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd2
add %i0, 64, %i0
1:
FALIGN_D34
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D2
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd18
add %i0, 64, %i0
2:
FALIGN_D2
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D18
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd34
add %i0, 64, %i0
copyout_seg2:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D4
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D20
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D36
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg2
0:
FALIGN_D20
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D36
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd4
add %i0, 64, %i0
1:
FALIGN_D36
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D4
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd20
add %i0, 64, %i0
2:
FALIGN_D4
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D20
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd36
add %i0, 64, %i0
copyout_seg3:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D6
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D22
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D38
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg3
0:
FALIGN_D22
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D38
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd6
add %i0, 64, %i0
1:
FALIGN_D38
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D6
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd22
add %i0, 64, %i0
2:
FALIGN_D6
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D22
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd38
add %i0, 64, %i0
copyout_seg4:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D8
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D24
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D40
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg4
0:
FALIGN_D24
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D40
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd8
add %i0, 64, %i0
1:
FALIGN_D40
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D8
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd24
add %i0, 64, %i0
2:
FALIGN_D8
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D24
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd40
add %i0, 64, %i0
copyout_seg5:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D10
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D26
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D42
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg5
0:
FALIGN_D26
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D42
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd10
add %i0, 64, %i0
1:
FALIGN_D42
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D10
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd26
add %i0, 64, %i0
2:
FALIGN_D10
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D26
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd42
add %i0, 64, %i0
copyout_seg6:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D12
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D28
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D44
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg6
0:
FALIGN_D28
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D44
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd12
add %i0, 64, %i0
1:
FALIGN_D44
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D12
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd28
add %i0, 64, %i0
2:
FALIGN_D12
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D28
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd44
add %i0, 64, %i0
copyout_seg7:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D14
ldda [%l7]ASI_BLK_P, %d0
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D30
ldda [%l7]ASI_BLK_P, %d16
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D46
ldda [%l7]ASI_BLK_P, %d32
stda %d48, [%i0]ASI_BLK_AIUS
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyout_seg7
0:
FALIGN_D30
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D46
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd14
add %i0, 64, %i0
1:
FALIGN_D46
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D14
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd30
add %i0, 64, %i0
2:
FALIGN_D14
stda %d48, [%i0]ASI_BLK_AIUS
add %i0, 64, %i0
membar #Sync
FALIGN_D30
stda %d48, [%i0]ASI_BLK_AIUS
ba,pt %ncc, copyout_blkd46
add %i0, 64, %i0
!
! dribble out the last partial block
!
copyout_blkd0:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d0, %d2, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd2:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d2, %d4, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd4:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d4, %d6, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd6:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d6, %d8, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd8:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d8, %d10, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd10:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d10, %d12, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd12:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d12, %d14, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd14:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
fsrc1 %d14, %d0
ba,a,pt %ncc, copyout_blkleft
copyout_blkd16:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d16, %d18, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd18:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d18, %d20, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd20:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d20, %d22, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd22:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d22, %d24, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd24:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d24, %d26, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd26:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d26, %d28, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd28:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d28, %d30, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd30:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
fsrc1 %d30, %d0
ba,a,pt %ncc, copyout_blkleft
copyout_blkd32:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d32, %d34, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd34:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d34, %d36, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd36:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d36, %d38, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd38:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d38, %d40, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd40:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d40, %d42, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd42:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d42, %d44, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd44:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
faligndata %d44, %d46, %d48
stda %d48, [%i0]ASI_USER
add %i0, 8, %i0
copyout_blkd46:
subcc %i4, 8, %i4
blu,pn %ncc, copyout_blkdone
fsrc1 %d46, %d0
copyout_blkleft:
1:
ldd [%l7], %d2
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d0, %d2, %d8
stda %d8, [%i0]ASI_USER
blu,pn %ncc, copyout_blkdone
add %i0, 8, %i0
ldd [%l7], %d0
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d2, %d0, %d8
stda %d8, [%i0]ASI_USER
bgeu,pt %ncc, 1b
add %i0, 8, %i0
copyout_blkdone:
tst %i2
bz,pt %ncc, .copyout_exit
and %l3, 0x4, %l3 ! fprs.du = fprs.dl = 0
7: ldub [%i1], %i4
inc %i1
stba %i4, [%i0]ASI_USER
inc %i0
deccc %i2
bgu %ncc, 7b
nop
.copyout_exit:
membar #StoreLoad|#StoreStore
btst FPUSED_FLAG, SAVED_LOFAULT
bz 1f
nop
ld [%fp + STACK_BIAS - SAVED_GSR_OFFSET], %o2
wr %o2, 0, %gsr ! restore gsr
ld [%fp + STACK_BIAS - SAVED_FPRS_OFFSET], %o3
btst FPRS_FEF, %o3
bz 4f
nop
! restore fpregs from stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
ldda [%o2]ASI_BLK_P, %d0
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d16
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d32
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d48
membar #Sync
ba,pt %ncc, 1f
wr %o3, 0, %fprs ! restore fprs
4:
FZERO ! zero all of the fpregs
wr %o3, 0, %fprs ! restore fprs
1:
andn SAVED_LOFAULT, FPUSED_FLAG, SAVED_LOFAULT
membar #Sync ! sync error barrier
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
ret
restore %g0, 0, %o0
.copyout_err:
ldn [THREAD_REG + T_COPYOPS], %o4
brz %o4, 2f
nop
ldn [%o4 + CP_COPYOUT], %g2
jmp %g2
nop
2:
retl
mov -1, %o0
SET_SIZE(copyout)
ENTRY(xcopyout)
sethi %hi(.xcopyout_err), REAL_LOFAULT
b .do_copyout
or REAL_LOFAULT, %lo(.xcopyout_err), REAL_LOFAULT
.xcopyout_err:
ldn [THREAD_REG + T_COPYOPS], %o4
brz %o4, 2f
nop
ldn [%o4 + CP_XCOPYOUT], %g2
jmp %g2
nop
2:
retl
mov %g1, %o0
SET_SIZE(xcopyout)
ENTRY(xcopyout_little)
sethi %hi(.little_err), %o4
ldn [THREAD_REG + T_LOFAULT], %o5
or %o4, %lo(.little_err), %o4
membar #Sync ! sync error barrier
stn %o4, [THREAD_REG + T_LOFAULT]
subcc %g0, %o2, %o3
add %o0, %o2, %o0
bz,pn %ncc, 2f ! check for zero bytes
sub %o2, 1, %o4
add %o0, %o4, %o0 ! start w/last byte
add %o1, %o2, %o1
ldub [%o0+%o3], %o4
1: stba %o4, [%o1+%o3]ASI_AIUSL
inccc %o3
sub %o0, 2, %o0 ! get next byte
bcc,a,pt %ncc, 1b
ldub [%o0+%o3], %o4
2: membar #Sync ! sync error barrier
stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
retl
mov %g0, %o0 ! return (0)
SET_SIZE(xcopyout_little)
ENTRY(copyin)
sethi %hi(.copyin_err), REAL_LOFAULT
or REAL_LOFAULT, %lo(.copyin_err), REAL_LOFAULT
.do_copyin:
!
! Check the length and bail if zero.
!
tst %o2
bnz,pt %ncc, 1f
nop
retl
clr %o0
1:
sethi %hi(copyio_fault), %o4
or %o4, %lo(copyio_fault), %o4
sethi %hi(copyio_fault_nowindow), %o3
ldn [THREAD_REG + T_LOFAULT], SAVED_LOFAULT
or %o3, %lo(copyio_fault_nowindow), %o3
membar #Sync
stn %o3, [THREAD_REG + T_LOFAULT]
mov %o0, SAVE_SRC
mov %o1, SAVE_DST
mov %o2, SAVE_COUNT
!
! Check to see if we're more than SMALL_LIMIT.
!
subcc %o2, SMALL_LIMIT, %o3
bgu,a,pt %ncc, .dci_ns
or %o0, %o1, %o3
!
! What was previously ".small_copyin"
!
.dcibcp:
sub %g0, %o2, %o3 ! setup for copy loop
add %o0, %o2, %o0
add %o1, %o2, %o1
ba,pt %ncc, .dcicl
lduba [%o0 + %o3]ASI_USER, %o4
!
! %o0 and %o1 point at the end and remain pointing at the end
! of their buffers. We pull things out by adding %o3 (which is
! the negation of the length) to the buffer end which gives us
! the curent location in the buffers. By incrementing %o3 we walk
! through both buffers without having to bump each buffer's
! pointer. A very fast 4 instruction loop.
!
.align 16
.dcicl:
stb %o4, [%o1 + %o3]
inccc %o3
bl,a,pt %ncc, .dcicl
lduba [%o0 + %o3]ASI_USER, %o4
!
! We're done. Go home.
!
membar #Sync
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT]
retl
clr %o0
!
! Try aligned copies from here.
!
.dci_ns:
!
! See if we're single byte aligned. If we are, check the
! limit for single byte copies. If we're smaller, or equal,
! bounce to the byte for byte copy loop. Otherwise do it in
! HW (if enabled).
!
btst 1, %o3
bz,a,pt %icc, .dcih8
btst 7, %o3
!
! We're single byte aligned.
!
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcibcp
sethi %hi(hw_copy_limit_1), %o3
ld [%o3 + %lo(hw_copy_limit_1)], %o3
!
! Is HW copy on? If not do everything byte for byte.
!
tst %o3
bz,pn %icc, .dcibcp
subcc %o3, %o2, %o3
!
! Are we bigger than the HW limit? If not
! go to byte for byte.
!
bge,pt %ncc, .dcibcp
nop
!
! We're big enough and copy is on. Do it with HW.
!
ba,pt %ncc, .big_copyin
nop
.dcih8:
!
! 8 byte aligned?
!
bnz,a %ncc, .dcih4
btst 3, %o3
!
! We're eight byte aligned.
!
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcis8
sethi %hi(hw_copy_limit_8), %o3
ld [%o3 + %lo(hw_copy_limit_8)], %o3
!
! Is HW assist on? If not, do it with the aligned copy.
!
tst %o3
bz,pn %icc, .dcis8
subcc %o3, %o2, %o3
bge %ncc, .dcis8
nop
ba,pt %ncc, .big_copyin
nop
.dcis8:
!
! Housekeeping for copy loops. Uses same idea as in the byte for
! byte copy loop above.
!
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .didebc
srl %o2, 3, %o2 ! Number of 8 byte chunks to copy
!
! 4 byte aligned?
!
.dcih4:
bnz %ncc, .dcih2
subcc %o2, VIS_COPY_THRESHOLD, %o3
bleu,pt %ncc, .dcis4
sethi %hi(hw_copy_limit_4), %o3
ld [%o3 + %lo(hw_copy_limit_4)], %o3
!
! Is HW assist on? If not, do it with the aligned copy.
!
tst %o3
bz,pn %icc, .dcis4
subcc %o3, %o2, %o3
!
! We're negative if our size is less than or equal to hw_copy_limit_4.
!
bge %ncc, .dcis4
nop
ba,pt %ncc, .big_copyin
nop
.dcis4:
!
! Housekeeping for copy loops. Uses same idea as in the byte
! for byte copy loop above.
!
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .didfbc
srl %o2, 2, %o2 ! Number of 4 byte chunks to copy
.dcih2:
!
! We're two byte aligned. Check for "smallness"
! done in delay at .dcih4
!
bleu,pt %ncc, .dcis2
sethi %hi(hw_copy_limit_2), %o3
ld [%o3 + %lo(hw_copy_limit_2)], %o3
!
! Is HW assist on? If not, do it with the aligned copy.
!
tst %o3
bz,pn %icc, .dcis2
subcc %o3, %o2, %o3
!
! Are we larger than the HW limit?
!
bge %ncc, .dcis2
nop
!
! HW assist is on and we're large enough to use it.
!
ba,pt %ncc, .big_copyin
nop
!
! Housekeeping for copy loops. Uses same idea as in the byte
! for byte copy loop above.
!
.dcis2:
add %o0, %o2, %o0
add %o1, %o2, %o1
sub %g0, %o2, %o3
ba,pt %ncc, .didtbc
srl %o2, 1, %o2 ! Number of 2 byte chunks to copy
!
.small_copyin:
!
! Why are we doing this AGAIN? There are certain conditions in
! big copyin that will cause us to forgo the HW assisted copys
! and bounce back to a non-hw assisted copy. This dispatches
! those copies. Note that we branch around this in the main line
! code.
!
! We make no check for limits or HW enablement here. We've
! already been told that we're a poster child so just go off
! and do it.
!
or %o0, %o1, %o3
btst 1, %o3
bnz %icc, .dcibcp ! Most likely
btst 7, %o3
bz %icc, .dcis8
btst 3, %o3
bz %icc, .dcis4
nop
ba,pt %ncc, .dcis2
nop
!
! Eight byte aligned copies. A steal from the original .small_copyin
! with modifications. %o2 is number of 8 byte chunks to copy. When
! done, we examine %o3. If this is < 0, we have 1 - 7 bytes more
! to copy.
!
.align 32
.didebc:
ldxa [%o0 + %o3]ASI_USER, %o4
deccc %o2
stx %o4, [%o1 + %o3]
bg,pt %ncc, .didebc
addcc %o3, 8, %o3
!
! End of copy loop. Most 8 byte aligned copies end here.
!
bz,pt %ncc, .dcifh
nop
!
! Something is left. Do it byte for byte.
!
ba,pt %ncc, .dcicl
lduba [%o0 + %o3]ASI_USER, %o4
!
! 4 byte copy loop. %o2 is number of 4 byte chunks to copy.
!
.align 32
.didfbc:
lduwa [%o0 + %o3]ASI_USER, %o4
deccc %o2
st %o4, [%o1 + %o3]
bg,pt %ncc, .didfbc
addcc %o3, 4, %o3
!
! End of copy loop. Most 4 byte aligned copies end here.
!
bz,pt %ncc, .dcifh
nop
!
! Something is left. Do it byte for byte.
!
ba,pt %ncc, .dcicl
lduba [%o0 + %o3]ASI_USER, %o4
!
! 2 byte aligned copy loop. %o2 is number of 2 byte chunks to
! copy.
!
.align 32
.didtbc:
lduha [%o0 + %o3]ASI_USER, %o4
deccc %o2
sth %o4, [%o1 + %o3]
bg,pt %ncc, .didtbc
addcc %o3, 2, %o3
!
! End of copy loop. Most 2 byte aligned copies end here.
!
bz,pt %ncc, .dcifh
nop
!
! Deal with the last byte
!
lduba [%o0 + %o3]ASI_USER, %o4
stb %o4, [%o1 + %o3]
.dcifh:
membar #Sync
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
retl
clr %o0
.big_copyin:
!
! Are we using the FP registers?
!
rd %fprs, %o3 ! check for unused fp
btst FPRS_FEF, %o3
bnz %ncc, .copyin_fpregs_inuse
nop
!
! We're going off to do a block copy.
! Switch fault hendlers and grab a window. We
! don't do a membar #Sync since we've done only
! kernel data to this point.
!
stn %o4, [THREAD_REG + T_LOFAULT]
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
!
! %o3 is %i3 after the save...
!
st %i3, [%fp + STACK_BIAS - SAVED_FPRS_OFFSET]
ba,pt %ncc, .do_blockcopyin
wr %g0, FPRS_FEF, %fprs
.copyin_fpregs_inuse:
!
! We're here if the FP regs are in use. Need to see if the request
! exceeds our suddenly larger minimum.
!
cmp %i2, VIS_COPY_THRESHOLD+(64*4)
bl %ncc, .small_copyin
nop
!
! We're going off and do a block copy.
! Change to the heavy duty fault handler and grab a window first.
! New handler is passed in
!
stn %o4, [THREAD_REG + T_LOFAULT]
save %sp, -SA(MINFRAME + HWCOPYFRAMESIZE), %sp
!
! %o3 is now %i3
!
st %i3, [%fp + STACK_BIAS - SAVED_FPRS_OFFSET]
! save in-use fpregs on stack
wr %g0, FPRS_FEF, %fprs
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
stda %d0, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d16, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d32, [%o2]ASI_BLK_P
add %o2, 64, %o2
stda %d48, [%o2]ASI_BLK_P
membar #Sync
.do_blockcopyin:
membar #StoreStore|#StoreLoad|#LoadStore
rd %gsr, %o2
st %o2, [%fp + STACK_BIAS - SAVED_GSR_OFFSET] ! save gsr
! Set the lower bit in the saved t_lofault to indicate
! that we need to clear the %fprs register on the way
! out
or SAVED_LOFAULT, FPUSED_FLAG, SAVED_LOFAULT
! Swap src/dst since the code below is memcpy code
! and memcpy/bcopy have different calling sequences
mov %i1, %i5
mov %i0, %i1
mov %i5, %i0
!!! This code is nearly identical to the version in the sun4u
!!! libc_psr. Most bugfixes made to that file should be
!!! merged into this routine.
andcc %i0, 7, %o3
bz copyin_blkcpy
sub %o3, 8, %o3
neg %o3
sub %i2, %o3, %i2
! Align Destination on double-word boundary
2: lduba [%i1]ASI_USER, %o4
inc %i1
inc %i0
deccc %o3
bgu %ncc, 2b
stb %o4, [%i0-1]
copyin_blkcpy:
andcc %i0, 63, %i3
bz,pn %ncc, copyin_blalign ! now block aligned
sub %i3, 64, %i3
neg %i3 ! bytes till block aligned
sub %i2, %i3, %i2 ! update %i2 with new count
! Copy %i3 bytes till dst is block (64 byte) aligned. use
! double word copies.
alignaddr %i1, %g0, %g1
ldda [%g1]ASI_USER, %d0
add %g1, 8, %g1
6:
ldda [%g1]ASI_USER, %d2
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d0, %d2, %d8
std %d8, [%i0]
add %i1, 8, %i1
bz,pn %ncc, copyin_blalign
add %i0, 8, %i0
ldda [%g1]ASI_USER, %d0
add %g1, 8, %g1
subcc %i3, 8, %i3
faligndata %d2, %d0, %d8
std %d8, [%i0]
add %i1, 8, %i1
bgu,pn %ncc, 6b
add %i0, 8, %i0
copyin_blalign:
membar #StoreLoad
! %i2 = total length
! %i3 = blocks (length - 64) / 64
! %i4 = doubles remaining (length - blocks)
sub %i2, 64, %i3
andn %i3, 63, %i3
sub %i2, %i3, %i4
andn %i4, 7, %i4
sub %i4, 16, %i4
sub %i2, %i4, %i2
sub %i2, %i3, %i2
andn %i1, 0x3f, %l7 ! blk aligned address
alignaddr %i1, %g0, %g0 ! gen %gsr
srl %i1, 3, %l5 ! bits 3,4,5 are now least sig in %l5
andcc %l5, 7, %i5 ! mask everything except bits 1,2 3
add %i1, %i4, %i1
add %i1, %i3, %i1
ldda [%l7]ASI_BLK_AIUS, %d0
add %l7, 64, %l7
ldda [%l7]ASI_BLK_AIUS, %d16
add %l7, 64, %l7
ldda [%l7]ASI_BLK_AIUS, %d32
add %l7, 64, %l7
sub %i3, 128, %i3
! switch statement to get us to the right 8 byte blk within a
! 64 byte block
cmp %i5, 4
bgeu,a copyin_hlf
cmp %i5, 6
cmp %i5, 2
bgeu,a copyin_sqtr
nop
cmp %i5, 1
be,a copyin_seg1
nop
ba,pt %ncc, copyin_seg0
nop
copyin_sqtr:
be,a copyin_seg2
nop
ba,pt %ncc, copyin_seg3
nop
copyin_hlf:
bgeu,a copyin_fqtr
nop
cmp %i5, 5
be,a copyin_seg5
nop
ba,pt %ncc, copyin_seg4
nop
copyin_fqtr:
be,a copyin_seg6
nop
ba,pt %ncc, copyin_seg7
nop
copyin_seg0:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D0
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D16
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D32
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg0
0:
FALIGN_D16
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D32
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd0
add %i0, 64, %i0
1:
FALIGN_D32
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D0
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd16
add %i0, 64, %i0
2:
FALIGN_D0
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D16
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd32
add %i0, 64, %i0
copyin_seg1:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D2
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D18
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D34
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg1
0:
FALIGN_D18
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D34
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd2
add %i0, 64, %i0
1:
FALIGN_D34
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D2
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd18
add %i0, 64, %i0
2:
FALIGN_D2
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D18
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd34
add %i0, 64, %i0
copyin_seg2:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D4
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D20
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D36
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg2
0:
FALIGN_D20
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D36
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd4
add %i0, 64, %i0
1:
FALIGN_D36
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D4
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd20
add %i0, 64, %i0
2:
FALIGN_D4
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D20
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd36
add %i0, 64, %i0
copyin_seg3:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D6
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D22
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D38
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg3
0:
FALIGN_D22
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D38
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd6
add %i0, 64, %i0
1:
FALIGN_D38
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D6
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd22
add %i0, 64, %i0
2:
FALIGN_D6
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D22
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd38
add %i0, 64, %i0
copyin_seg4:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D8
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D24
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D40
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg4
0:
FALIGN_D24
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D40
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd8
add %i0, 64, %i0
1:
FALIGN_D40
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D8
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd24
add %i0, 64, %i0
2:
FALIGN_D8
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D24
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd40
add %i0, 64, %i0
copyin_seg5:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D10
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D26
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D42
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg5
0:
FALIGN_D26
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D42
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd10
add %i0, 64, %i0
1:
FALIGN_D42
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D10
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd26
add %i0, 64, %i0
2:
FALIGN_D10
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D26
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd42
add %i0, 64, %i0
copyin_seg6:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D12
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D28
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D44
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg6
0:
FALIGN_D28
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D44
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd12
add %i0, 64, %i0
1:
FALIGN_D44
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D12
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd28
add %i0, 64, %i0
2:
FALIGN_D12
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D28
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd44
add %i0, 64, %i0
copyin_seg7:
! 1st chunk - %d0 low, %d16 high, %d32 pre, %d48 dst
FALIGN_D14
ldda [%l7]ASI_BLK_AIUS, %d0
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 0f
add %i0, 64, %i0
! 2nd chunk - %d0 pre, %d16 low, %d32 high, %d48 dst
FALIGN_D30
ldda [%l7]ASI_BLK_AIUS, %d16
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 1f
add %i0, 64, %i0
! 3rd chunk - %d0 high, %d16 pre, %d32 low, %d48 dst
FALIGN_D46
ldda [%l7]ASI_BLK_AIUS, %d32
stda %d48, [%i0]ASI_BLK_P
add %l7, 64, %l7
subcc %i3, 64, %i3
bz,pn %ncc, 2f
add %i0, 64, %i0
ba,a,pt %ncc, copyin_seg7
0:
FALIGN_D30
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D46
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd14
add %i0, 64, %i0
1:
FALIGN_D46
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D14
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd30
add %i0, 64, %i0
2:
FALIGN_D14
stda %d48, [%i0]ASI_BLK_P
add %i0, 64, %i0
membar #Sync
FALIGN_D30
stda %d48, [%i0]ASI_BLK_P
ba,pt %ncc, copyin_blkd46
add %i0, 64, %i0
!
! dribble out the last partial block
!
copyin_blkd0:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d0, %d2, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd2:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d2, %d4, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd4:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d4, %d6, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd6:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d6, %d8, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd8:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d8, %d10, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd10:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d10, %d12, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd12:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d12, %d14, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd14:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
fsrc1 %d14, %d0
ba,a,pt %ncc, copyin_blkleft
copyin_blkd16:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d16, %d18, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd18:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d18, %d20, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd20:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d20, %d22, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd22:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d22, %d24, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd24:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d24, %d26, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd26:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d26, %d28, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd28:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d28, %d30, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd30:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
fsrc1 %d30, %d0
ba,a,pt %ncc, copyin_blkleft
copyin_blkd32:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d32, %d34, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd34:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d34, %d36, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd36:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d36, %d38, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd38:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d38, %d40, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd40:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d40, %d42, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd42:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d42, %d44, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd44:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
faligndata %d44, %d46, %d48
std %d48, [%i0]
add %i0, 8, %i0
copyin_blkd46:
subcc %i4, 8, %i4
blu,pn %ncc, copyin_blkdone
fsrc1 %d46, %d0
copyin_blkleft:
1:
ldda [%l7]ASI_USER, %d2
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d0, %d2, %d8
std %d8, [%i0]
blu,pn %ncc, copyin_blkdone
add %i0, 8, %i0
ldda [%l7]ASI_USER, %d0
add %l7, 8, %l7
subcc %i4, 8, %i4
faligndata %d2, %d0, %d8
std %d8, [%i0]
bgeu,pt %ncc, 1b
add %i0, 8, %i0
copyin_blkdone:
tst %i2
bz,pt %ncc, .copyin_exit
and %l3, 0x4, %l3 ! fprs.du = fprs.dl = 0
7: lduba [%i1]ASI_USER, %i4
inc %i1
inc %i0
deccc %i2
bgu %ncc, 7b
stb %i4, [%i0 - 1]
.copyin_exit:
membar #StoreLoad|#StoreStore
btst FPUSED_FLAG, SAVED_LOFAULT
bz %icc, 1f
nop
ld [%fp + STACK_BIAS - SAVED_GSR_OFFSET], %o2 ! restore gsr
wr %o2, 0, %gsr
ld [%fp + STACK_BIAS - SAVED_FPRS_OFFSET], %o3
btst FPRS_FEF, %o3
bz %icc, 4f
nop
! restore fpregs from stack
membar #Sync
add %fp, STACK_BIAS - 257, %o2
and %o2, -64, %o2
ldda [%o2]ASI_BLK_P, %d0
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d16
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d32
add %o2, 64, %o2
ldda [%o2]ASI_BLK_P, %d48
membar #Sync
ba,pt %ncc, 1f
wr %o3, 0, %fprs ! restore fprs
4:
FZERO ! zero all of the fpregs
wr %o3, 0, %fprs ! restore fprs
1:
andn SAVED_LOFAULT, FPUSED_FLAG, SAVED_LOFAULT
membar #Sync ! sync error barrier
stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
ret
restore %g0, 0, %o0
.copyin_err:
ldn [THREAD_REG + T_COPYOPS], %o4
brz %o4, 2f
nop
ldn [%o4 + CP_COPYIN], %g2
jmp %g2
nop
2:
retl
mov -1, %o0
SET_SIZE(copyin)
ENTRY(xcopyin)
sethi %hi(.xcopyin_err), REAL_LOFAULT
b .do_copyin
or REAL_LOFAULT, %lo(.xcopyin_err), REAL_LOFAULT
.xcopyin_err:
ldn [THREAD_REG + T_COPYOPS], %o4
brz %o4, 2f
nop
ldn [%o4 + CP_XCOPYIN], %g2
jmp %g2
nop
2:
retl
mov %g1, %o0
SET_SIZE(xcopyin)
ENTRY(xcopyin_little)
sethi %hi(.little_err), %o4
ldn [THREAD_REG + T_LOFAULT], %o5
or %o4, %lo(.little_err), %o4
membar #Sync ! sync error barrier
stn %o4, [THREAD_REG + T_LOFAULT]
subcc %g0, %o2, %o3
add %o0, %o2, %o0
bz,pn %ncc, 2f ! check for zero bytes
sub %o2, 1, %o4
add %o0, %o4, %o0 ! start w/last byte
add %o1, %o2, %o1
lduba [%o0+%o3]ASI_AIUSL, %o4
1: stb %o4, [%o1+%o3]
inccc %o3
sub %o0, 2, %o0 ! get next byte
bcc,a,pt %ncc, 1b
lduba [%o0+%o3]ASI_AIUSL, %o4
2: membar #Sync ! sync error barrier
stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
retl
mov %g0, %o0 ! return (0)
.little_err:
membar #Sync ! sync error barrier
stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault
retl
mov %g1, %o0
SET_SIZE(xcopyin_little)
ENTRY(copyin_noerr)
sethi %hi(.copyio_noerr), REAL_LOFAULT
b .do_copyin
or REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT
.copyio_noerr:
jmp SAVED_LOFAULT
nop
SET_SIZE(copyin_noerr)
ENTRY(copyout_noerr)
sethi %hi(.copyio_noerr), REAL_LOFAULT
b .do_copyout
or REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT
SET_SIZE(copyout_noerr)
.align 4
DGDEF(use_hw_bcopy)
.word 1
DGDEF(use_hw_copyio)
.word 1
DGDEF(use_hw_bzero)
.word 1
DGDEF(hw_copy_limit_1)
.word 0
DGDEF(hw_copy_limit_2)
.word 0
DGDEF(hw_copy_limit_4)
.word 0
DGDEF(hw_copy_limit_8)
.word 0
.align 64
.section ".text"
! %i0 - start address
! %i1 - length of region (multiple of 64)
! %l0 - saved fprs
! %l1 - pointer to saved %d0 block
! %l2 - saved curthread->t_lwp
ENTRY(hwblkclr)
! get another window w/space for one aligned block of saved fpregs
save %sp, -SA(MINFRAME + 2*64), %sp
! Must be block-aligned
andcc %i0, (64-1), %g0
bnz,pn %ncc, 1f
nop
! ... and must be 256 bytes or more
cmp %i1, 256
blu,pn %ncc, 1f
nop
! ... and length must be a multiple of 64
andcc %i1, (64-1), %g0
bz,pn %ncc, 2f
nop
1: ! punt, call bzero but notify the caller that bzero was used
mov %i0, %o0
call bzero
mov %i1, %o1
ret
restore %g0, 1, %o0 ! return (1) - did not use block operations
2: rd %fprs, %l0 ! check for unused fp
btst FPRS_FEF, %l0
bz 1f
nop
! save in-use fpregs on stack
membar #Sync
add %fp, STACK_BIAS - 65, %l1
and %l1, -64, %l1
stda %d0, [%l1]ASI_BLK_P
1: membar #StoreStore|#StoreLoad|#LoadStore
wr %g0, FPRS_FEF, %fprs
wr %g0, ASI_BLK_P, %asi
! Clear block
fzero %d0
fzero %d2
fzero %d4
fzero %d6
fzero %d8
fzero %d10
fzero %d12
fzero %d14
mov 256, %i3
ba .pz_doblock
nop
.pz_blkstart:
! stda %d0, [%i0+192]%asi ! in dly slot of branch that got us here
stda %d0, [%i0+128]%asi
stda %d0, [%i0+64]%asi
stda %d0, [%i0]%asi
.pz_zinst:
add %i0, %i3, %i0
sub %i1, %i3, %i1
.pz_doblock:
cmp %i1, 256
bgeu,a %ncc, .pz_blkstart
stda %d0, [%i0+192]%asi
cmp %i1, 64
blu %ncc, .pz_finish
andn %i1, (64-1), %i3
srl %i3, 4, %i2 ! using blocks, 1 instr / 16 words
set .pz_zinst, %i4
sub %i4, %i2, %i4
jmp %i4
nop
.pz_finish:
membar #Sync
btst FPRS_FEF, %l0
bz,a .pz_finished
wr %l0, 0, %fprs ! restore fprs
! restore fpregs from stack
ldda [%l1]ASI_BLK_P, %d0
membar #Sync
wr %l0, 0, %fprs ! restore fprs
.pz_finished:
ret
restore %g0, 0, %o0 ! return (bzero or not)
SET_SIZE(hwblkclr)
ENTRY_NP(hw_pa_bcopy32)
rdpr %pstate, %g1
andn %g1, PSTATE_IE, %g2
wrpr %g0, %g2, %pstate
ldxa [%o0]ASI_MEM, %o2
add %o0, 8, %o0
ldxa [%o0]ASI_MEM, %o3
add %o0, 8, %o0
ldxa [%o0]ASI_MEM, %o4
add %o0, 8, %o0
ldxa [%o0]ASI_MEM, %o5
stxa %o2, [%o1]ASI_MEM
add %o1, 8, %o1
stxa %o3, [%o1]ASI_MEM
add %o1, 8, %o1
stxa %o4, [%o1]ASI_MEM
add %o1, 8, %o1
stxa %o5, [%o1]ASI_MEM
membar #Sync
retl
wrpr %g0, %g1, %pstate
SET_SIZE(hw_pa_bcopy32)