Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /* U3memcpy.S: UltraSparc-III optimized memcpy.
0003  *
0004  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
0005  */
0006 
0007 #ifdef __KERNEL__
0008 #include <linux/linkage.h>
0009 #include <asm/visasm.h>
0010 #include <asm/asi.h>
0011 #define GLOBAL_SPARE    %g7
0012 #else
0013 #define ASI_BLK_P 0xf0
0014 #define FPRS_FEF  0x04
0015 #ifdef MEMCPY_DEBUG
0016 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
0017              clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
0018 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0019 #else
0020 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
0021 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0022 #endif
0023 #define GLOBAL_SPARE    %g5
0024 #endif
0025 
0026 #ifndef EX_LD
0027 #define EX_LD(x,y)  x
0028 #endif
0029 #ifndef EX_LD_FP
0030 #define EX_LD_FP(x,y)   x
0031 #endif
0032 
0033 #ifndef EX_ST
0034 #define EX_ST(x,y)  x
0035 #endif
0036 #ifndef EX_ST_FP
0037 #define EX_ST_FP(x,y)   x
0038 #endif
0039 
0040 #ifndef LOAD
0041 #define LOAD(type,addr,dest)    type [addr], dest
0042 #endif
0043 
0044 #ifndef STORE
0045 #define STORE(type,src,addr)    type src, [addr]
0046 #endif
0047 
0048 #ifndef STORE_BLK
0049 #define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P
0050 #endif
0051 
0052 #ifndef FUNC_NAME
0053 #define FUNC_NAME   U3memcpy
0054 #endif
0055 
0056 #ifndef PREAMBLE
0057 #define PREAMBLE
0058 #endif
0059 
0060 #ifndef XCC
0061 #define XCC xcc
0062 #endif
0063 
0064     .register   %g2,#scratch
0065     .register   %g3,#scratch
0066 
0067     /* Special/non-trivial issues of this code:
0068      *
0069      * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
0070      * 2) Only low 32 FPU registers are used so that only the
0071      *    lower half of the FPU register set is dirtied by this
0072      *    code.  This is especially important in the kernel.
0073      * 3) This code never prefetches cachelines past the end
0074      *    of the source buffer.
0075      */
0076 
0077     .text
0078 #ifndef EX_RETVAL
0079 #define EX_RETVAL(x)    x
0080 __restore_fp:
0081     VISExitHalf
0082     retl
0083      nop
0084 ENTRY(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
0085     add %g1, 1, %g1
0086     add %g2, %g1, %g2
0087     ba,pt   %xcc, __restore_fp
0088      add    %o2, %g2, %o0
0089 ENDPROC(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
0090 ENTRY(U3_retl_o2_plus_g2_fp)
0091     ba,pt   %xcc, __restore_fp
0092      add    %o2, %g2, %o0
0093 ENDPROC(U3_retl_o2_plus_g2_fp)
0094 ENTRY(U3_retl_o2_plus_g2_plus_8_fp)
0095     add %g2, 8, %g2
0096     ba,pt   %xcc, __restore_fp
0097      add    %o2, %g2, %o0
0098 ENDPROC(U3_retl_o2_plus_g2_plus_8_fp)
0099 ENTRY(U3_retl_o2)
0100     retl
0101      mov    %o2, %o0
0102 ENDPROC(U3_retl_o2)
0103 ENTRY(U3_retl_o2_plus_1)
0104     retl
0105      add    %o2, 1, %o0
0106 ENDPROC(U3_retl_o2_plus_1)
0107 ENTRY(U3_retl_o2_plus_4)
0108     retl
0109      add    %o2, 4, %o0
0110 ENDPROC(U3_retl_o2_plus_4)
0111 ENTRY(U3_retl_o2_plus_8)
0112     retl
0113      add    %o2, 8, %o0
0114 ENDPROC(U3_retl_o2_plus_8)
0115 ENTRY(U3_retl_o2_plus_g1_plus_1)
0116     add %g1, 1, %g1
0117     retl
0118      add    %o2, %g1, %o0
0119 ENDPROC(U3_retl_o2_plus_g1_plus_1)
0120 ENTRY(U3_retl_o2_fp)
0121     ba,pt   %xcc, __restore_fp
0122      mov    %o2, %o0
0123 ENDPROC(U3_retl_o2_fp)
0124 ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
0125     sll %o3, 6, %o3
0126     add %o3, 0x80, %o3
0127     ba,pt   %xcc, __restore_fp
0128      add    %o2, %o3, %o0
0129 ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
0130 ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
0131     sll %o3, 6, %o3
0132     add %o3, 0x40, %o3
0133     ba,pt   %xcc, __restore_fp
0134      add    %o2, %o3, %o0
0135 ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
0136 ENTRY(U3_retl_o2_plus_GS_plus_0x10)
0137     add GLOBAL_SPARE, 0x10, GLOBAL_SPARE
0138     retl
0139      add    %o2, GLOBAL_SPARE, %o0
0140 ENDPROC(U3_retl_o2_plus_GS_plus_0x10)
0141 ENTRY(U3_retl_o2_plus_GS_plus_0x08)
0142     add GLOBAL_SPARE, 0x08, GLOBAL_SPARE
0143     retl
0144      add    %o2, GLOBAL_SPARE, %o0
0145 ENDPROC(U3_retl_o2_plus_GS_plus_0x08)
0146 ENTRY(U3_retl_o2_and_7_plus_GS)
0147     and %o2, 7, %o2
0148     retl
0149      add    %o2, GLOBAL_SPARE, %o0
0150 ENDPROC(U3_retl_o2_and_7_plus_GS)
0151 ENTRY(U3_retl_o2_and_7_plus_GS_plus_8)
0152     add GLOBAL_SPARE, 8, GLOBAL_SPARE
0153     and %o2, 7, %o2
0154     retl
0155      add    %o2, GLOBAL_SPARE, %o0
0156 ENDPROC(U3_retl_o2_and_7_plus_GS_plus_8)
0157 #endif
0158 
0159     .align      64
0160 
0161     /* The cheetah's flexible spine, oversized liver, enlarged heart,
0162      * slender muscular body, and claws make it the swiftest hunter
0163      * in Africa and the fastest animal on land.  Can reach speeds
0164      * of up to 2.4GB per second.
0165      */
0166 
0167     .globl  FUNC_NAME
0168     .type   FUNC_NAME,#function
0169 FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
0170     srlx        %o2, 31, %g2
0171     cmp     %g2, 0
0172 
0173     /* software trap 5 "Range Check" if dst >= 0x80000000 */
0174     tne     %xcc, 5
0175     PREAMBLE
0176     mov     %o0, %o4
0177 
0178     /* if len == 0 */
0179     cmp     %o2, 0
0180     be,pn       %XCC, end_return
0181      or     %o0, %o1, %o3
0182 
0183     /* if len < 16 */
0184     cmp     %o2, 16
0185     blu,a,pn    %XCC, less_than_16
0186      or     %o3, %o2, %o3
0187 
0188     /* if len < 192 */
0189     cmp     %o2, (3 * 64)
0190     blu,pt      %XCC, less_than_192
0191      andcc      %o3, 0x7, %g0
0192 
0193     /* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
0194      * o5 from here until we hit VISExitHalf.
0195      */
0196     VISEntryHalf
0197 
0198     /* Is 'dst' already aligned on an 64-byte boundary? */
0199     andcc       %o0, 0x3f, %g2
0200     be,pt       %XCC, 2f
0201 
0202     /* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
0203      * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
0204      * subtract this from 'len'.
0205      */
0206      sub        %o0, %o1, GLOBAL_SPARE
0207     sub     %g2, 0x40, %g2
0208     sub     %g0, %g2, %g2
0209     sub     %o2, %g2, %o2
0210     andcc       %g2, 0x7, %g1
0211     be,pt       %icc, 2f
0212      and        %g2, 0x38, %g2
0213 
0214 1:  subcc       %g1, 0x1, %g1
0215     EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U3_retl_o2_plus_g2_plus_g1_plus_1)
0216     EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE), U3_retl_o2_plus_g2_plus_g1_plus_1)
0217     bgu,pt      %XCC, 1b
0218      add        %o1, 0x1, %o1
0219 
0220     add     %o1, GLOBAL_SPARE, %o0
0221 
0222 2:  cmp     %g2, 0x0
0223     and     %o1, 0x7, %g1
0224     be,pt       %icc, 3f
0225      alignaddr  %o1, %g0, %o1
0226 
0227     EX_LD_FP(LOAD(ldd, %o1, %f4), U3_retl_o2_plus_g2)
0228 1:  EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U3_retl_o2_plus_g2)
0229     add     %o1, 0x8, %o1
0230     subcc       %g2, 0x8, %g2
0231     faligndata  %f4, %f6, %f0
0232     EX_ST_FP(STORE(std, %f0, %o0), U3_retl_o2_plus_g2_plus_8)
0233     be,pn       %icc, 3f
0234      add        %o0, 0x8, %o0
0235 
0236     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U3_retl_o2_plus_g2)
0237     add     %o1, 0x8, %o1
0238     subcc       %g2, 0x8, %g2
0239     faligndata  %f6, %f4, %f2
0240     EX_ST_FP(STORE(std, %f2, %o0), U3_retl_o2_plus_g2_plus_8)
0241     bne,pt      %icc, 1b
0242      add        %o0, 0x8, %o0
0243 
0244 3:  LOAD(prefetch, %o1 + 0x000, #one_read)
0245     LOAD(prefetch, %o1 + 0x040, #one_read)
0246     andn        %o2, (0x40 - 1), GLOBAL_SPARE
0247     LOAD(prefetch, %o1 + 0x080, #one_read)
0248     LOAD(prefetch, %o1 + 0x0c0, #one_read)
0249     LOAD(prefetch, %o1 + 0x100, #one_read)
0250     EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0), U3_retl_o2)
0251     LOAD(prefetch, %o1 + 0x140, #one_read)
0252     EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2)
0253     LOAD(prefetch, %o1 + 0x180, #one_read)
0254     EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2)
0255     LOAD(prefetch, %o1 + 0x1c0, #one_read)
0256     faligndata  %f0, %f2, %f16
0257     EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2)
0258     faligndata  %f2, %f4, %f18
0259     EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2)
0260     faligndata  %f4, %f6, %f20
0261     EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2)
0262     faligndata  %f6, %f8, %f22
0263 
0264     EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2)
0265     faligndata  %f8, %f10, %f24
0266     EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2)
0267     faligndata  %f10, %f12, %f26
0268     EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2)
0269 
0270     subcc       GLOBAL_SPARE, 0x80, GLOBAL_SPARE
0271     add     %o1, 0x40, %o1
0272     bgu,pt      %XCC, 1f
0273      srl        GLOBAL_SPARE, 6, %o3
0274     ba,pt       %xcc, 2f
0275      nop
0276 
0277     .align      64
0278 1:
0279     EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0280     faligndata  %f12, %f14, %f28
0281     EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0282     faligndata  %f14, %f0, %f30
0283     EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0284     EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0285     faligndata  %f0, %f2, %f16
0286     add     %o0, 0x40, %o0
0287 
0288     EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0289     faligndata  %f2, %f4, %f18
0290     EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0291     faligndata  %f4, %f6, %f20
0292     EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0293     subcc       %o3, 0x01, %o3
0294     faligndata  %f6, %f8, %f22
0295     EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0296 
0297     faligndata  %f8, %f10, %f24
0298     EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0299     LOAD(prefetch, %o1 + 0x1c0, #one_read)
0300     faligndata  %f10, %f12, %f26
0301     bg,pt       %XCC, 1b
0302      add        %o1, 0x40, %o1
0303 
0304     /* Finally we copy the last full 64-byte block. */
0305 2:
0306     EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0307     faligndata  %f12, %f14, %f28
0308     EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0309     faligndata  %f14, %f0, %f30
0310     EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
0311     EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0312     faligndata  %f0, %f2, %f16
0313     EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0314     faligndata  %f2, %f4, %f18
0315     EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0316     faligndata  %f4, %f6, %f20
0317     EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0318     faligndata  %f6, %f8, %f22
0319     EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0320     faligndata  %f8, %f10, %f24
0321     cmp     %g1, 0
0322     be,pt       %XCC, 1f
0323      add        %o0, 0x40, %o0
0324     EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0325 1:  faligndata  %f10, %f12, %f26
0326     faligndata  %f12, %f14, %f28
0327     faligndata  %f14, %f0, %f30
0328     EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
0329     add     %o0, 0x40, %o0
0330     add     %o1, 0x40, %o1
0331     membar      #Sync
0332 
0333     /* Now we copy the (len modulo 64) bytes at the end.
0334      * Note how we borrow the %f0 loaded above.
0335      *
0336      * Also notice how this code is careful not to perform a
0337      * load past the end of the src buffer.
0338      */
0339     and     %o2, 0x3f, %o2
0340     andcc       %o2, 0x38, %g2
0341     be,pn       %XCC, 2f
0342      subcc      %g2, 0x8, %g2
0343     be,pn       %XCC, 2f
0344      cmp        %g1, 0
0345 
0346     sub     %o2, %g2, %o2
0347     be,a,pt     %XCC, 1f
0348      EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0), U3_retl_o2_plus_g2)
0349 
0350 1:  EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2), U3_retl_o2_plus_g2)
0351     add     %o1, 0x8, %o1
0352     subcc       %g2, 0x8, %g2
0353     faligndata  %f0, %f2, %f8
0354     EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
0355     be,pn       %XCC, 2f
0356      add        %o0, 0x8, %o0
0357     EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0), U3_retl_o2_plus_g2)
0358     add     %o1, 0x8, %o1
0359     subcc       %g2, 0x8, %g2
0360     faligndata  %f2, %f0, %f8
0361     EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
0362     bne,pn      %XCC, 1b
0363      add        %o0, 0x8, %o0
0364 
0365     /* If anything is left, we copy it one byte at a time.
0366      * Note that %g1 is (src & 0x3) saved above before the
0367      * alignaddr was performed.
0368      */
0369 2:
0370     cmp     %o2, 0
0371     add     %o1, %g1, %o1
0372     VISExitHalf
0373     be,pn       %XCC, end_return
0374      sub        %o0, %o1, %o3
0375 
0376     andcc       %g1, 0x7, %g0
0377     bne,pn      %icc, 90f
0378      andcc      %o2, 0x8, %g0
0379     be,pt       %icc, 1f
0380      nop
0381     EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2)
0382     EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2)
0383     add     %o1, 0x8, %o1
0384     sub     %o2, 8, %o2
0385 
0386 1:  andcc       %o2, 0x4, %g0
0387     be,pt       %icc, 1f
0388      nop
0389     EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2)
0390     EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2)
0391     add     %o1, 0x4, %o1
0392     sub     %o2, 4, %o2
0393 
0394 1:  andcc       %o2, 0x2, %g0
0395     be,pt       %icc, 1f
0396      nop
0397     EX_LD(LOAD(lduh, %o1, %o5), U3_retl_o2)
0398     EX_ST(STORE(sth, %o5, %o1 + %o3), U3_retl_o2)
0399     add     %o1, 0x2, %o1
0400     sub     %o2, 2, %o2
0401 
0402 1:  andcc       %o2, 0x1, %g0
0403     be,pt       %icc, end_return
0404      nop
0405     EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2)
0406     ba,pt       %xcc, end_return
0407      EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2)
0408 
0409     .align      64
0410     /* 16 <= len < 192 */
0411 less_than_192:
0412     bne,pn      %XCC, 75f
0413      sub        %o0, %o1, %o3
0414 
0415 72:
0416     andn        %o2, 0xf, GLOBAL_SPARE
0417     and     %o2, 0xf, %o2
0418 1:  subcc       GLOBAL_SPARE, 0x10, GLOBAL_SPARE
0419     EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U3_retl_o2_plus_GS_plus_0x10)
0420     EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U3_retl_o2_plus_GS_plus_0x10)
0421     EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x10)
0422     add     %o1, 0x8, %o1
0423     EX_ST(STORE(stx, %g1, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x08)
0424     bgu,pt      %XCC, 1b
0425      add        %o1, 0x8, %o1
0426 73: andcc       %o2, 0x8, %g0
0427     be,pt       %XCC, 1f
0428      nop
0429     sub     %o2, 0x8, %o2
0430     EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2_plus_8)
0431     EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_8)
0432     add     %o1, 0x8, %o1
0433 1:  andcc       %o2, 0x4, %g0
0434     be,pt       %XCC, 1f
0435      nop
0436     sub     %o2, 0x4, %o2
0437     EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2_plus_4)
0438     EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2_plus_4)
0439     add     %o1, 0x4, %o1
0440 1:  cmp     %o2, 0
0441     be,pt       %XCC, end_return
0442      nop
0443     ba,pt       %xcc, 90f
0444      nop
0445 
0446 75:
0447     andcc       %o0, 0x7, %g1
0448     sub     %g1, 0x8, %g1
0449     be,pn       %icc, 2f
0450      sub        %g0, %g1, %g1
0451     sub     %o2, %g1, %o2
0452 
0453 1:  subcc       %g1, 1, %g1
0454     EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2_plus_g1_plus_1)
0455     EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2_plus_g1_plus_1)
0456     bgu,pt      %icc, 1b
0457      add        %o1, 1, %o1
0458 
0459 2:  add     %o1, %o3, %o0
0460     andcc       %o1, 0x7, %g1
0461     bne,pt      %icc, 8f
0462      sll        %g1, 3, %g1
0463 
0464     cmp     %o2, 16
0465     bgeu,pt     %icc, 72b
0466      nop
0467     ba,a,pt     %xcc, 73b
0468 
0469 8:  mov     64, %o3
0470     andn        %o1, 0x7, %o1
0471     EX_LD(LOAD(ldx, %o1, %g2), U3_retl_o2)
0472     sub     %o3, %g1, %o3
0473     andn        %o2, 0x7, GLOBAL_SPARE
0474     sllx        %g2, %g1, %g2
0475 1:  EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U3_retl_o2_and_7_plus_GS)
0476     subcc       GLOBAL_SPARE, 0x8, GLOBAL_SPARE
0477     add     %o1, 0x8, %o1
0478     srlx        %g3, %o3, %o5
0479     or      %o5, %g2, %o5
0480     EX_ST(STORE(stx, %o5, %o0), U3_retl_o2_and_7_plus_GS_plus_8)
0481     add     %o0, 0x8, %o0
0482     bgu,pt      %icc, 1b
0483      sllx       %g3, %g1, %g2
0484 
0485     srl     %g1, 3, %g1
0486     andcc       %o2, 0x7, %o2
0487     be,pn       %icc, end_return
0488      add        %o1, %g1, %o1
0489     ba,pt       %xcc, 90f
0490      sub        %o0, %o1, %o3
0491 
0492     .align      64
0493     /* 0 < len < 16 */
0494 less_than_16:
0495     andcc       %o3, 0x3, %g0
0496     bne,pn      %XCC, 90f
0497      sub        %o0, %o1, %o3
0498 
0499 1:
0500     subcc       %o2, 4, %o2
0501     EX_LD(LOAD(lduw, %o1, %g1), U3_retl_o2_plus_4)
0502     EX_ST(STORE(stw, %g1, %o1 + %o3), U3_retl_o2_plus_4)
0503     bgu,pt      %XCC, 1b
0504      add        %o1, 4, %o1
0505 
0506 end_return:
0507     retl
0508      mov        EX_RETVAL(%o4), %o0
0509 
0510     .align      32
0511 90:
0512     subcc       %o2, 1, %o2
0513     EX_LD(LOAD(ldub, %o1, %g1), U3_retl_o2_plus_1)
0514     EX_ST(STORE(stb, %g1, %o1 + %o3), U3_retl_o2_plus_1)
0515     bgu,pt      %XCC, 90b
0516      add        %o1, 1, %o1
0517     retl
0518      mov        EX_RETVAL(%o4), %o0
0519 
0520     .size       FUNC_NAME, .-FUNC_NAME