Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /* NG2memcpy.S: Niagara-2 optimized memcpy.
0003  *
0004  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
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_PNF 0x82
0014 #define ASI_BLK_P 0xf0
0015 #define ASI_BLK_INIT_QUAD_LDD_P 0xe2
0016 #define FPRS_FEF  0x04
0017 #ifdef MEMCPY_DEBUG
0018 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
0019              clr %g1; clr %g2; clr %g3; clr %g5; subcc %g0, %g0, %g0;
0020 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0021 #else
0022 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
0023 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0024 #endif
0025 #define GLOBAL_SPARE    %g5
0026 #endif
0027 
0028 #ifndef STORE_ASI
0029 #ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA
0030 #define STORE_ASI   ASI_BLK_INIT_QUAD_LDD_P
0031 #else
0032 #define STORE_ASI   0x80        /* ASI_P */
0033 #endif
0034 #endif
0035 
0036 #ifndef EX_LD
0037 #define EX_LD(x,y)  x
0038 #endif
0039 #ifndef EX_LD_FP
0040 #define EX_LD_FP(x,y)   x
0041 #endif
0042 
0043 #ifndef EX_ST
0044 #define EX_ST(x,y)  x
0045 #endif
0046 #ifndef EX_ST_FP
0047 #define EX_ST_FP(x,y)   x
0048 #endif
0049 
0050 #ifndef LOAD
0051 #define LOAD(type,addr,dest)    type [addr], dest
0052 #endif
0053 
0054 #ifndef LOAD_BLK
0055 #define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_P, dest
0056 #endif
0057 
0058 #ifndef STORE
0059 #ifndef MEMCPY_DEBUG
0060 #define STORE(type,src,addr)    type src, [addr]
0061 #else
0062 #define STORE(type,src,addr)    type##a src, [addr] 0x80
0063 #endif
0064 #endif
0065 
0066 #ifndef STORE_BLK
0067 #define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P
0068 #endif
0069 
0070 #ifndef STORE_INIT
0071 #define STORE_INIT(src,addr)    stxa src, [addr] STORE_ASI
0072 #endif
0073 
0074 #ifndef FUNC_NAME
0075 #define FUNC_NAME   NG2memcpy
0076 #endif
0077 
0078 #ifndef PREAMBLE
0079 #define PREAMBLE
0080 #endif
0081 
0082 #ifndef XCC
0083 #define XCC xcc
0084 #endif
0085 
0086 #define FREG_FROB(x0, x1, x2, x3, x4, x5, x6, x7, x8) \
0087     faligndata  %x0, %x1, %f0; \
0088     faligndata  %x1, %x2, %f2; \
0089     faligndata  %x2, %x3, %f4; \
0090     faligndata  %x3, %x4, %f6; \
0091     faligndata  %x4, %x5, %f8; \
0092     faligndata  %x5, %x6, %f10; \
0093     faligndata  %x6, %x7, %f12; \
0094     faligndata  %x7, %x8, %f14;
0095 
0096 #define FREG_MOVE_1(x0) \
0097     fsrc2       %x0, %f0;
0098 #define FREG_MOVE_2(x0, x1) \
0099     fsrc2       %x0, %f0; \
0100     fsrc2       %x1, %f2;
0101 #define FREG_MOVE_3(x0, x1, x2) \
0102     fsrc2       %x0, %f0; \
0103     fsrc2       %x1, %f2; \
0104     fsrc2       %x2, %f4;
0105 #define FREG_MOVE_4(x0, x1, x2, x3) \
0106     fsrc2       %x0, %f0; \
0107     fsrc2       %x1, %f2; \
0108     fsrc2       %x2, %f4; \
0109     fsrc2       %x3, %f6;
0110 #define FREG_MOVE_5(x0, x1, x2, x3, x4) \
0111     fsrc2       %x0, %f0; \
0112     fsrc2       %x1, %f2; \
0113     fsrc2       %x2, %f4; \
0114     fsrc2       %x3, %f6; \
0115     fsrc2       %x4, %f8;
0116 #define FREG_MOVE_6(x0, x1, x2, x3, x4, x5) \
0117     fsrc2       %x0, %f0; \
0118     fsrc2       %x1, %f2; \
0119     fsrc2       %x2, %f4; \
0120     fsrc2       %x3, %f6; \
0121     fsrc2       %x4, %f8; \
0122     fsrc2       %x5, %f10;
0123 #define FREG_MOVE_7(x0, x1, x2, x3, x4, x5, x6) \
0124     fsrc2       %x0, %f0; \
0125     fsrc2       %x1, %f2; \
0126     fsrc2       %x2, %f4; \
0127     fsrc2       %x3, %f6; \
0128     fsrc2       %x4, %f8; \
0129     fsrc2       %x5, %f10; \
0130     fsrc2       %x6, %f12;
0131 #define FREG_MOVE_8(x0, x1, x2, x3, x4, x5, x6, x7) \
0132     fsrc2       %x0, %f0; \
0133     fsrc2       %x1, %f2; \
0134     fsrc2       %x2, %f4; \
0135     fsrc2       %x3, %f6; \
0136     fsrc2       %x4, %f8; \
0137     fsrc2       %x5, %f10; \
0138     fsrc2       %x6, %f12; \
0139     fsrc2       %x7, %f14;
0140 #define FREG_LOAD_1(base, x0) \
0141     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1)
0142 #define FREG_LOAD_2(base, x0, x1) \
0143     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0144     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1);
0145 #define FREG_LOAD_3(base, x0, x1, x2) \
0146     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0147     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
0148     EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1);
0149 #define FREG_LOAD_4(base, x0, x1, x2, x3) \
0150     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0151     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
0152     EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
0153     EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1);
0154 #define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
0155     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0156     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
0157     EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
0158     EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
0159     EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1);
0160 #define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
0161     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0162     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
0163     EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
0164     EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
0165     EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
0166     EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1);
0167 #define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
0168     EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
0169     EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
0170     EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
0171     EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
0172     EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
0173     EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1); \
0174     EX_LD_FP(LOAD(ldd, base + 0x30, %x6), NG2_retl_o2_plus_g1);
0175 
0176     .register   %g2,#scratch
0177     .register   %g3,#scratch
0178 
0179     .text
0180 #ifndef EX_RETVAL
0181 #define EX_RETVAL(x)    x
0182 __restore_fp:
0183     VISExitHalf
0184 __restore_asi:
0185     retl
0186      wr %g0, ASI_AIUS, %asi
0187 ENTRY(NG2_retl_o2)
0188     ba,pt   %xcc, __restore_asi
0189      mov    %o2, %o0
0190 ENDPROC(NG2_retl_o2)
0191 ENTRY(NG2_retl_o2_plus_1)
0192     ba,pt   %xcc, __restore_asi
0193      add    %o2, 1, %o0
0194 ENDPROC(NG2_retl_o2_plus_1)
0195 ENTRY(NG2_retl_o2_plus_4)
0196     ba,pt   %xcc, __restore_asi
0197      add    %o2, 4, %o0
0198 ENDPROC(NG2_retl_o2_plus_4)
0199 ENTRY(NG2_retl_o2_plus_8)
0200     ba,pt   %xcc, __restore_asi
0201      add    %o2, 8, %o0
0202 ENDPROC(NG2_retl_o2_plus_8)
0203 ENTRY(NG2_retl_o2_plus_o4_plus_1)
0204     add %o4, 1, %o4
0205     ba,pt   %xcc, __restore_asi
0206      add    %o2, %o4, %o0
0207 ENDPROC(NG2_retl_o2_plus_o4_plus_1)
0208 ENTRY(NG2_retl_o2_plus_o4_plus_8)
0209     add %o4, 8, %o4
0210     ba,pt   %xcc, __restore_asi
0211      add    %o2, %o4, %o0
0212 ENDPROC(NG2_retl_o2_plus_o4_plus_8)
0213 ENTRY(NG2_retl_o2_plus_o4_plus_16)
0214     add %o4, 16, %o4
0215     ba,pt   %xcc, __restore_asi
0216      add    %o2, %o4, %o0
0217 ENDPROC(NG2_retl_o2_plus_o4_plus_16)
0218 ENTRY(NG2_retl_o2_plus_g1_fp)
0219     ba,pt   %xcc, __restore_fp
0220      add    %o2, %g1, %o0
0221 ENDPROC(NG2_retl_o2_plus_g1_fp)
0222 ENTRY(NG2_retl_o2_plus_g1_plus_64_fp)
0223     add %g1, 64, %g1
0224     ba,pt   %xcc, __restore_fp
0225      add    %o2, %g1, %o0
0226 ENDPROC(NG2_retl_o2_plus_g1_plus_64_fp)
0227 ENTRY(NG2_retl_o2_plus_g1_plus_1)
0228     add %g1, 1, %g1
0229     ba,pt   %xcc, __restore_asi
0230      add    %o2, %g1, %o0
0231 ENDPROC(NG2_retl_o2_plus_g1_plus_1)
0232 ENTRY(NG2_retl_o2_and_7_plus_o4)
0233     and %o2, 7, %o2
0234     ba,pt   %xcc, __restore_asi
0235      add    %o2, %o4, %o0
0236 ENDPROC(NG2_retl_o2_and_7_plus_o4)
0237 ENTRY(NG2_retl_o2_and_7_plus_o4_plus_8)
0238     and %o2, 7, %o2
0239     add %o4, 8, %o4
0240     ba,pt   %xcc, __restore_asi
0241      add    %o2, %o4, %o0
0242 ENDPROC(NG2_retl_o2_and_7_plus_o4_plus_8)
0243 #endif
0244 
0245     .align      64
0246 
0247     .globl  FUNC_NAME
0248     .type   FUNC_NAME,#function
0249 FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
0250     srlx        %o2, 31, %g2
0251     cmp     %g2, 0
0252     tne     %xcc, 5
0253     PREAMBLE
0254     mov     %o0, %o3
0255     cmp     %o2, 0
0256     be,pn       %XCC, 85f
0257      or     %o0, %o1, GLOBAL_SPARE
0258     cmp     %o2, 16
0259     blu,a,pn    %XCC, 80f
0260      or     GLOBAL_SPARE, %o2, GLOBAL_SPARE
0261 
0262     /* 2 blocks (128 bytes) is the minimum we can do the block
0263      * copy with.  We need to ensure that we'll iterate at least
0264      * once in the block copy loop.  At worst we'll need to align
0265      * the destination to a 64-byte boundary which can chew up
0266      * to (64 - 1) bytes from the length before we perform the
0267      * block copy loop.
0268      *
0269      * However, the cut-off point, performance wise, is around
0270      * 4 64-byte blocks.
0271      */
0272     cmp     %o2, (4 * 64)
0273     blu,pt      %XCC, 75f
0274      andcc      GLOBAL_SPARE, 0x7, %g0
0275 
0276     /* %o0: dst
0277      * %o1: src
0278      * %o2: len  (known to be >= 128)
0279      *
0280      * The block copy loops can use %o4, %g2, %g3 as
0281      * temporaries while copying the data.  %o5 must
0282      * be preserved between VISEntryHalf and VISExitHalf
0283      */
0284 
0285     LOAD(prefetch, %o1 + 0x000, #one_read)
0286     LOAD(prefetch, %o1 + 0x040, #one_read)
0287     LOAD(prefetch, %o1 + 0x080, #one_read)
0288 
0289     /* Align destination on 64-byte boundary.  */
0290     andcc       %o0, (64 - 1), %o4
0291     be,pt       %XCC, 2f
0292      sub        %o4, 64, %o4
0293     sub     %g0, %o4, %o4   ! bytes to align dst
0294     sub     %o2, %o4, %o2
0295 1:  subcc       %o4, 1, %o4
0296     EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_o4_plus_1)
0297     EX_ST(STORE(stb, %g1, %o0), NG2_retl_o2_plus_o4_plus_1)
0298     add     %o1, 1, %o1
0299     bne,pt      %XCC, 1b
0300     add     %o0, 1, %o0
0301 
0302 2:
0303     /* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
0304      * o5 from here until we hit VISExitHalf.
0305      */
0306     VISEntryHalf
0307 
0308     membar      #Sync
0309     alignaddr   %o1, %g0, %g0
0310 
0311     add     %o1, (64 - 1), %o4
0312     andn        %o4, (64 - 1), %o4
0313     andn        %o2, (64 - 1), %g1
0314     sub     %o2, %g1, %o2
0315 
0316     and     %o1, (64 - 1), %g2
0317     add     %o1, %g1, %o1
0318     sub     %o0, %o4, %g3
0319     brz,pt      %g2, 190f
0320      cmp        %g2, 32
0321     blu,a       5f
0322      cmp        %g2, 16
0323     cmp     %g2, 48
0324     blu,a       4f
0325      cmp        %g2, 40
0326     cmp     %g2, 56
0327     blu     170f
0328      nop
0329     ba,a,pt     %xcc, 180f
0330      nop
0331 
0332 4:  /* 32 <= low bits < 48 */
0333     blu     150f
0334      nop
0335     ba,a,pt     %xcc, 160f
0336      nop
0337 5:  /* 0 < low bits < 32 */
0338     blu,a       6f
0339      cmp        %g2, 8
0340     cmp     %g2, 24
0341     blu     130f
0342      nop
0343     ba,a,pt     %xcc, 140f
0344      nop
0345 6:  /* 0 < low bits < 16 */
0346     bgeu        120f
0347      nop
0348     /* fall through for 0 < low bits < 8 */
0349 110:    sub     %o4, 64, %g2
0350     EX_LD_FP(LOAD_BLK(%g2, %f0), NG2_retl_o2_plus_g1)
0351 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0352     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0353     FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
0354     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0355     FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
0356     subcc       %g1, 64, %g1
0357     add     %o4, 64, %o4
0358     bne,pt      %xcc, 1b
0359      LOAD(prefetch, %o4 + 64, #one_read)
0360     ba,pt       %xcc, 195f
0361      nop
0362 
0363 120:    sub     %o4, 56, %g2
0364     FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
0365 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0366     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0367     FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
0368     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0369     FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
0370     subcc       %g1, 64, %g1
0371     add     %o4, 64, %o4
0372     bne,pt      %xcc, 1b
0373      LOAD(prefetch, %o4 + 64, #one_read)
0374     ba,pt       %xcc, 195f
0375      nop
0376 
0377 130:    sub     %o4, 48, %g2
0378     FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
0379 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0380     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0381     FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
0382     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0383     FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
0384     subcc       %g1, 64, %g1
0385     add     %o4, 64, %o4
0386     bne,pt      %xcc, 1b
0387      LOAD(prefetch, %o4 + 64, #one_read)
0388     ba,pt       %xcc, 195f
0389      nop
0390 
0391 140:    sub     %o4, 40, %g2
0392     FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
0393 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0394     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0395     FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
0396     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0397     FREG_MOVE_5(f22, f24, f26, f28, f30)
0398     subcc       %g1, 64, %g1
0399     add     %o4, 64, %o4
0400     bne,pt      %xcc, 1b
0401      LOAD(prefetch, %o4 + 64, #one_read)
0402     ba,pt       %xcc, 195f
0403      nop
0404 
0405 150:    sub     %o4, 32, %g2
0406     FREG_LOAD_4(%g2, f0, f2, f4, f6)
0407 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0408     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0409     FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
0410     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0411     FREG_MOVE_4(f24, f26, f28, f30)
0412     subcc       %g1, 64, %g1
0413     add     %o4, 64, %o4
0414     bne,pt      %xcc, 1b
0415      LOAD(prefetch, %o4 + 64, #one_read)
0416     ba,pt       %xcc, 195f
0417      nop
0418 
0419 160:    sub     %o4, 24, %g2
0420     FREG_LOAD_3(%g2, f0, f2, f4)
0421 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0422     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0423     FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
0424     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0425     FREG_MOVE_3(f26, f28, f30)
0426     subcc       %g1, 64, %g1
0427     add     %o4, 64, %o4
0428     bne,pt      %xcc, 1b
0429      LOAD(prefetch, %o4 + 64, #one_read)
0430     ba,pt       %xcc, 195f
0431      nop
0432 
0433 170:    sub     %o4, 16, %g2
0434     FREG_LOAD_2(%g2, f0, f2)
0435 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0436     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0437     FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
0438     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0439     FREG_MOVE_2(f28, f30)
0440     subcc       %g1, 64, %g1
0441     add     %o4, 64, %o4
0442     bne,pt      %xcc, 1b
0443      LOAD(prefetch, %o4 + 64, #one_read)
0444     ba,pt       %xcc, 195f
0445      nop
0446 
0447 180:    sub     %o4, 8, %g2
0448     FREG_LOAD_1(%g2, f0)
0449 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0450     EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
0451     FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
0452     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
0453     FREG_MOVE_1(f30)
0454     subcc       %g1, 64, %g1
0455     add     %o4, 64, %o4
0456     bne,pt      %xcc, 1b
0457      LOAD(prefetch, %o4 + 64, #one_read)
0458     ba,pt       %xcc, 195f
0459      nop
0460 
0461 190:
0462 1:  EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
0463     subcc       %g1, 64, %g1
0464     EX_LD_FP(LOAD_BLK(%o4, %f0), NG2_retl_o2_plus_g1_plus_64)
0465     EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1_plus_64)
0466     add     %o4, 64, %o4
0467     bne,pt      %xcc, 1b
0468      LOAD(prefetch, %o4 + 64, #one_read)
0469 
0470 195:
0471     add     %o4, %g3, %o0
0472     membar      #Sync
0473 
0474     VISExitHalf
0475 
0476     /* %o2 contains any final bytes still needed to be copied
0477      * over. If anything is left, we copy it one byte at a time.
0478      */
0479     brz,pt      %o2, 85f
0480      sub        %o0, %o1, GLOBAL_SPARE
0481     ba,a,pt     %XCC, 90f
0482      nop
0483 
0484     .align      64
0485 75: /* 16 < len <= 64 */
0486     bne,pn      %XCC, 75f
0487      sub        %o0, %o1, GLOBAL_SPARE
0488 
0489 72:
0490     andn        %o2, 0xf, %o4
0491     and     %o2, 0xf, %o2
0492 1:  subcc       %o4, 0x10, %o4
0493     EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_o4_plus_16)
0494     add     %o1, 0x08, %o1
0495     EX_LD(LOAD(ldx, %o1, %g1), NG2_retl_o2_plus_o4_plus_16)
0496     sub     %o1, 0x08, %o1
0497     EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_16)
0498     add     %o1, 0x8, %o1
0499     EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_8)
0500     bgu,pt      %XCC, 1b
0501      add        %o1, 0x8, %o1
0502 73: andcc       %o2, 0x8, %g0
0503     be,pt       %XCC, 1f
0504      nop
0505     sub     %o2, 0x8, %o2
0506     EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_8)
0507     EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_8)
0508     add     %o1, 0x8, %o1
0509 1:  andcc       %o2, 0x4, %g0
0510     be,pt       %XCC, 1f
0511      nop
0512     sub     %o2, 0x4, %o2
0513     EX_LD(LOAD(lduw, %o1, %o5), NG2_retl_o2_plus_4)
0514     EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
0515     add     %o1, 0x4, %o1
0516 1:  cmp     %o2, 0
0517     be,pt       %XCC, 85f
0518      nop
0519     ba,pt       %xcc, 90f
0520      nop
0521 
0522 75:
0523     andcc       %o0, 0x7, %g1
0524     sub     %g1, 0x8, %g1
0525     be,pn       %icc, 2f
0526      sub        %g0, %g1, %g1
0527     sub     %o2, %g1, %o2
0528 
0529 1:  subcc       %g1, 1, %g1
0530     EX_LD(LOAD(ldub, %o1, %o5), NG2_retl_o2_plus_g1_plus_1)
0531     EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_g1_plus_1)
0532     bgu,pt      %icc, 1b
0533      add        %o1, 1, %o1
0534 
0535 2:  add     %o1, GLOBAL_SPARE, %o0
0536     andcc       %o1, 0x7, %g1
0537     bne,pt      %icc, 8f
0538      sll        %g1, 3, %g1
0539 
0540     cmp     %o2, 16
0541     bgeu,pt     %icc, 72b
0542      nop
0543     ba,a,pt     %xcc, 73b
0544 
0545 8:  mov     64, GLOBAL_SPARE
0546     andn        %o1, 0x7, %o1
0547     EX_LD(LOAD(ldx, %o1, %g2), NG2_retl_o2)
0548     sub     GLOBAL_SPARE, %g1, GLOBAL_SPARE
0549     andn        %o2, 0x7, %o4
0550     sllx        %g2, %g1, %g2
0551 1:  add     %o1, 0x8, %o1
0552     EX_LD(LOAD(ldx, %o1, %g3), NG2_retl_o2_and_7_plus_o4)
0553     subcc       %o4, 0x8, %o4
0554     srlx        %g3, GLOBAL_SPARE, %o5
0555     or      %o5, %g2, %o5
0556     EX_ST(STORE(stx, %o5, %o0), NG2_retl_o2_and_7_plus_o4_plus_8)
0557     add     %o0, 0x8, %o0
0558     bgu,pt      %icc, 1b
0559      sllx       %g3, %g1, %g2
0560 
0561     srl     %g1, 3, %g1
0562     andcc       %o2, 0x7, %o2
0563     be,pn       %icc, 85f
0564      add        %o1, %g1, %o1
0565     ba,pt       %xcc, 90f
0566      sub        %o0, %o1, GLOBAL_SPARE
0567 
0568     .align      64
0569 80: /* 0 < len <= 16 */
0570     andcc       GLOBAL_SPARE, 0x3, %g0
0571     bne,pn      %XCC, 90f
0572      sub        %o0, %o1, GLOBAL_SPARE
0573 
0574 1:
0575     subcc       %o2, 4, %o2
0576     EX_LD(LOAD(lduw, %o1, %g1), NG2_retl_o2_plus_4)
0577     EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
0578     bgu,pt      %XCC, 1b
0579      add        %o1, 4, %o1
0580 
0581 85: retl
0582      mov        EX_RETVAL(%o3), %o0
0583 
0584     .align      32
0585 90:
0586     subcc       %o2, 1, %o2
0587     EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_1)
0588     EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_1)
0589     bgu,pt      %XCC, 90b
0590      add        %o1, 1, %o1
0591     retl
0592      mov        EX_RETVAL(%o3), %o0
0593 
0594     .size       FUNC_NAME, .-FUNC_NAME