0001
0002
0003
0004
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_INIT_QUAD_LDD_P 0xe2
0014 #define FPRS_FEF 0x04
0015
0016
0017
0018
0019 #define FPU_ENTER \
0020 rd %fprs, %o5; \
0021 andcc %o5, FPRS_FEF, %g0; \
0022 be,a,pn %icc, 999f; \
0023 wr %g0, FPRS_FEF, %fprs; \
0024 999:
0025
0026 #ifdef MEMCPY_DEBUG
0027 #define VISEntryHalf FPU_ENTER; \
0028 clr %g1; clr %g2; clr %g3; clr %g5; subcc %g0, %g0, %g0;
0029 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0030 #else
0031 #define VISEntryHalf FPU_ENTER
0032 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
0033 #endif
0034
0035 #define GLOBAL_SPARE %g5
0036 #endif
0037
0038 #ifndef STORE_ASI
0039 #ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA
0040 #define STORE_ASI ASI_BLK_INIT_QUAD_LDD_P
0041 #else
0042 #define STORE_ASI 0x80
0043 #endif
0044 #endif
0045
0046 #if !defined(EX_LD) && !defined(EX_ST)
0047 #define NON_USER_COPY
0048 #endif
0049
0050 #ifndef EX_LD
0051 #define EX_LD(x,y) x
0052 #endif
0053 #ifndef EX_LD_FP
0054 #define EX_LD_FP(x,y) x
0055 #endif
0056
0057 #ifndef EX_ST
0058 #define EX_ST(x,y) x
0059 #endif
0060 #ifndef EX_ST_FP
0061 #define EX_ST_FP(x,y) x
0062 #endif
0063
0064
0065 #ifndef LOAD
0066 #define LOAD(type,addr,dest) type [addr], dest
0067 #endif
0068
0069 #ifndef STORE
0070 #ifndef MEMCPY_DEBUG
0071 #define STORE(type,src,addr) type src, [addr]
0072 #else
0073 #define STORE(type,src,addr) type##a src, [addr] %asi
0074 #endif
0075 #endif
0076
0077 #ifndef STORE_INIT
0078 #define STORE_INIT(src,addr) stxa src, [addr] STORE_ASI
0079 #endif
0080
0081 #ifndef FUNC_NAME
0082 #define FUNC_NAME NG4memcpy
0083 #endif
0084 #ifndef PREAMBLE
0085 #define PREAMBLE
0086 #endif
0087
0088 #ifndef XCC
0089 #define XCC xcc
0090 #endif
0091
0092 .register %g2,#scratch
0093 .register %g3,#scratch
0094
0095 .text
0096 #ifndef EX_RETVAL
0097 #define EX_RETVAL(x) x
0098 #endif
0099 .align 64
0100
0101 .globl FUNC_NAME
0102 .type FUNC_NAME,#function
0103 FUNC_NAME:
0104 #ifdef MEMCPY_DEBUG
0105 wr %g0, 0x80, %asi
0106 #endif
0107 srlx %o2, 31, %g2
0108 cmp %g2, 0
0109 tne %XCC, 5
0110 PREAMBLE
0111 mov %o0, %o3
0112 brz,pn %o2, .Lexit
0113 cmp %o2, 3
0114 ble,pn %icc, .Ltiny
0115 cmp %o2, 19
0116 ble,pn %icc, .Lsmall
0117 or %o0, %o1, %g2
0118 cmp %o2, 128
0119 bl,pn %icc, .Lmedium
0120 nop
0121
0122 .Llarge:
0123
0124 sub %g0, %o0, %g1
0125 and %g1, 0x7, %g1
0126 brz,pt %g1, 51f
0127 sub %o2, %g1, %o2
0128
0129
0130 1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2), memcpy_retl_o2_plus_g1)
0131 add %o1, 1, %o1
0132 subcc %g1, 1, %g1
0133 add %o0, 1, %o0
0134 bne,pt %icc, 1b
0135 EX_ST(STORE(stb, %g2, %o0 - 0x01), memcpy_retl_o2_plus_g1_plus_1)
0136
0137 51: LOAD(prefetch, %o1 + 0x040, #n_reads_strong)
0138 LOAD(prefetch, %o1 + 0x080, #n_reads_strong)
0139 LOAD(prefetch, %o1 + 0x0c0, #n_reads_strong)
0140 LOAD(prefetch, %o1 + 0x100, #n_reads_strong)
0141 LOAD(prefetch, %o1 + 0x140, #n_reads_strong)
0142 LOAD(prefetch, %o1 + 0x180, #n_reads_strong)
0143 LOAD(prefetch, %o1 + 0x1c0, #n_reads_strong)
0144 LOAD(prefetch, %o1 + 0x200, #n_reads_strong)
0145
0146
0147
0148
0149 andcc %o1, 0x7, %o5
0150 bne,pn %icc, .Llarge_src_unaligned
0151 sub %g0, %o0, %g1
0152
0153
0154
0155
0156 and %g1, 0x3f, %g1
0157 brz,pt %g1, .Llarge_aligned
0158 sub %o2, %g1, %o2
0159
0160 1: EX_LD(LOAD(ldx, %o1 + 0x00, %g2), memcpy_retl_o2_plus_g1)
0161 add %o1, 8, %o1
0162 subcc %g1, 8, %g1
0163 add %o0, 8, %o0
0164 bne,pt %icc, 1b
0165 EX_ST(STORE(stx, %g2, %o0 - 0x08), memcpy_retl_o2_plus_g1_plus_8)
0166
0167 .Llarge_aligned:
0168
0169 andn %o2, 0x3f, %o4
0170 sub %o2, %o4, %o2
0171
0172 1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), memcpy_retl_o2_plus_o4)
0173 add %o1, 0x40, %o1
0174 EX_LD(LOAD(ldx, %o1 - 0x38, %g2), memcpy_retl_o2_plus_o4)
0175 subcc %o4, 0x40, %o4
0176 EX_LD(LOAD(ldx, %o1 - 0x30, %g3), memcpy_retl_o2_plus_o4_plus_64)
0177 EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE), memcpy_retl_o2_plus_o4_plus_64)
0178 EX_LD(LOAD(ldx, %o1 - 0x20, %o5), memcpy_retl_o2_plus_o4_plus_64)
0179 EX_ST(STORE_INIT(%g1, %o0), memcpy_retl_o2_plus_o4_plus_64)
0180 add %o0, 0x08, %o0
0181 EX_ST(STORE_INIT(%g2, %o0), memcpy_retl_o2_plus_o4_plus_56)
0182 add %o0, 0x08, %o0
0183 EX_LD(LOAD(ldx, %o1 - 0x18, %g2), memcpy_retl_o2_plus_o4_plus_48)
0184 EX_ST(STORE_INIT(%g3, %o0), memcpy_retl_o2_plus_o4_plus_48)
0185 add %o0, 0x08, %o0
0186 EX_LD(LOAD(ldx, %o1 - 0x10, %g3), memcpy_retl_o2_plus_o4_plus_40)
0187 EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), memcpy_retl_o2_plus_o4_plus_40)
0188 add %o0, 0x08, %o0
0189 EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE), memcpy_retl_o2_plus_o4_plus_32)
0190 EX_ST(STORE_INIT(%o5, %o0), memcpy_retl_o2_plus_o4_plus_32)
0191 add %o0, 0x08, %o0
0192 EX_ST(STORE_INIT(%g2, %o0), memcpy_retl_o2_plus_o4_plus_24)
0193 add %o0, 0x08, %o0
0194 EX_ST(STORE_INIT(%g3, %o0), memcpy_retl_o2_plus_o4_plus_16)
0195 add %o0, 0x08, %o0
0196 EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), memcpy_retl_o2_plus_o4_plus_8)
0197 add %o0, 0x08, %o0
0198 bne,pt %icc, 1b
0199 LOAD(prefetch, %o1 + 0x200, #n_reads_strong)
0200
0201 membar #StoreLoad | #StoreStore
0202
0203 brz,pn %o2, .Lexit
0204 cmp %o2, 19
0205 ble,pn %icc, .Lsmall_unaligned
0206 nop
0207 ba,a,pt %icc, .Lmedium_noprefetch
0208
0209 .Lexit: retl
0210 mov EX_RETVAL(%o3), %o0
0211
0212 .Llarge_src_unaligned:
0213 #ifdef NON_USER_COPY
0214 VISEntryHalfFast(.Lmedium_vis_entry_fail)
0215 #else
0216 VISEntryHalf
0217 #endif
0218 andn %o2, 0x3f, %o4
0219 sub %o2, %o4, %o2
0220 alignaddr %o1, %g0, %g1
0221 add %o1, %o4, %o1
0222 EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0), memcpy_retl_o2_plus_o4)
0223 1: EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2), memcpy_retl_o2_plus_o4)
0224 subcc %o4, 0x40, %o4
0225 EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4), memcpy_retl_o2_plus_o4_plus_64)
0226 EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6), memcpy_retl_o2_plus_o4_plus_64)
0227 EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8), memcpy_retl_o2_plus_o4_plus_64)
0228 EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10), memcpy_retl_o2_plus_o4_plus_64)
0229 EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12), memcpy_retl_o2_plus_o4_plus_64)
0230 EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14), memcpy_retl_o2_plus_o4_plus_64)
0231 faligndata %f0, %f2, %f16
0232 EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0), memcpy_retl_o2_plus_o4_plus_64)
0233 faligndata %f2, %f4, %f18
0234 add %g1, 0x40, %g1
0235 faligndata %f4, %f6, %f20
0236 faligndata %f6, %f8, %f22
0237 faligndata %f8, %f10, %f24
0238 faligndata %f10, %f12, %f26
0239 faligndata %f12, %f14, %f28
0240 faligndata %f14, %f0, %f30
0241 EX_ST_FP(STORE(std, %f16, %o0 + 0x00), memcpy_retl_o2_plus_o4_plus_64)
0242 EX_ST_FP(STORE(std, %f18, %o0 + 0x08), memcpy_retl_o2_plus_o4_plus_56)
0243 EX_ST_FP(STORE(std, %f20, %o0 + 0x10), memcpy_retl_o2_plus_o4_plus_48)
0244 EX_ST_FP(STORE(std, %f22, %o0 + 0x18), memcpy_retl_o2_plus_o4_plus_40)
0245 EX_ST_FP(STORE(std, %f24, %o0 + 0x20), memcpy_retl_o2_plus_o4_plus_32)
0246 EX_ST_FP(STORE(std, %f26, %o0 + 0x28), memcpy_retl_o2_plus_o4_plus_24)
0247 EX_ST_FP(STORE(std, %f28, %o0 + 0x30), memcpy_retl_o2_plus_o4_plus_16)
0248 EX_ST_FP(STORE(std, %f30, %o0 + 0x38), memcpy_retl_o2_plus_o4_plus_8)
0249 add %o0, 0x40, %o0
0250 bne,pt %icc, 1b
0251 LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
0252 #ifdef NON_USER_COPY
0253 VISExitHalfFast
0254 #else
0255 VISExitHalf
0256 #endif
0257 brz,pn %o2, .Lexit
0258 cmp %o2, 19
0259 ble,pn %icc, .Lsmall_unaligned
0260 nop
0261 ba,a,pt %icc, .Lmedium_unaligned
0262
0263 #ifdef NON_USER_COPY
0264 .Lmedium_vis_entry_fail:
0265 or %o0, %o1, %g2
0266 #endif
0267 .Lmedium:
0268 LOAD(prefetch, %o1 + 0x40, #n_reads_strong)
0269 andcc %g2, 0x7, %g0
0270 bne,pn %icc, .Lmedium_unaligned
0271 nop
0272 .Lmedium_noprefetch:
0273 andncc %o2, 0x20 - 1, %o5
0274 be,pn %icc, 2f
0275 sub %o2, %o5, %o2
0276 1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), memcpy_retl_o2_plus_o5)
0277 EX_LD(LOAD(ldx, %o1 + 0x08, %g2), memcpy_retl_o2_plus_o5)
0278 EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE), memcpy_retl_o2_plus_o5)
0279 EX_LD(LOAD(ldx, %o1 + 0x18, %o4), memcpy_retl_o2_plus_o5)
0280 add %o1, 0x20, %o1
0281 subcc %o5, 0x20, %o5
0282 EX_ST(STORE(stx, %g1, %o0 + 0x00), memcpy_retl_o2_plus_o5_plus_32)
0283 EX_ST(STORE(stx, %g2, %o0 + 0x08), memcpy_retl_o2_plus_o5_plus_24)
0284 EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10), memcpy_retl_o2_plus_o5_plus_24)
0285 EX_ST(STORE(stx, %o4, %o0 + 0x18), memcpy_retl_o2_plus_o5_plus_8)
0286 bne,pt %icc, 1b
0287 add %o0, 0x20, %o0
0288 2: andcc %o2, 0x18, %o5
0289 be,pt %icc, 3f
0290 sub %o2, %o5, %o2
0291
0292 1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), memcpy_retl_o2_plus_o5)
0293 add %o1, 0x08, %o1
0294 add %o0, 0x08, %o0
0295 subcc %o5, 0x08, %o5
0296 bne,pt %icc, 1b
0297 EX_ST(STORE(stx, %g1, %o0 - 0x08), memcpy_retl_o2_plus_o5_plus_8)
0298 3: brz,pt %o2, .Lexit
0299 cmp %o2, 0x04
0300 bl,pn %icc, .Ltiny
0301 nop
0302 EX_LD(LOAD(lduw, %o1 + 0x00, %g1), memcpy_retl_o2)
0303 add %o1, 0x04, %o1
0304 add %o0, 0x04, %o0
0305 subcc %o2, 0x04, %o2
0306 bne,pn %icc, .Ltiny
0307 EX_ST(STORE(stw, %g1, %o0 - 0x04), memcpy_retl_o2_plus_4)
0308 ba,a,pt %icc, .Lexit
0309 .Lmedium_unaligned:
0310
0311 sub %g0, %o0, %g1
0312 and %g1, 0x7, %g1
0313 brz,pt %g1, 2f
0314 sub %o2, %g1, %o2
0315
0316 1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2), memcpy_retl_o2_plus_g1)
0317 add %o1, 1, %o1
0318 subcc %g1, 1, %g1
0319 add %o0, 1, %o0
0320 bne,pt %icc, 1b
0321 EX_ST(STORE(stb, %g2, %o0 - 0x01), memcpy_retl_o2_plus_g1_plus_1)
0322 2:
0323 and %o1, 0x7, %g1
0324 brz,pn %g1, .Lmedium_noprefetch
0325 sll %g1, 3, %g1
0326 mov 64, %g2
0327 sub %g2, %g1, %g2
0328 andn %o1, 0x7, %o1
0329 EX_LD(LOAD(ldx, %o1 + 0x00, %o4), memcpy_retl_o2)
0330 sllx %o4, %g1, %o4
0331 andn %o2, 0x08 - 1, %o5
0332 sub %o2, %o5, %o2
0333 1: EX_LD(LOAD(ldx, %o1 + 0x08, %g3), memcpy_retl_o2_plus_o5)
0334 add %o1, 0x08, %o1
0335 subcc %o5, 0x08, %o5
0336 srlx %g3, %g2, GLOBAL_SPARE
0337 or GLOBAL_SPARE, %o4, GLOBAL_SPARE
0338 EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00), memcpy_retl_o2_plus_o5_plus_8)
0339 add %o0, 0x08, %o0
0340 bne,pt %icc, 1b
0341 sllx %g3, %g1, %o4
0342 srl %g1, 3, %g1
0343 add %o1, %g1, %o1
0344 brz,pn %o2, .Lexit
0345 nop
0346 ba,pt %icc, .Lsmall_unaligned
0347
0348 .Ltiny:
0349 EX_LD(LOAD(ldub, %o1 + 0x00, %g1), memcpy_retl_o2)
0350 subcc %o2, 1, %o2
0351 be,pn %icc, .Lexit
0352 EX_ST(STORE(stb, %g1, %o0 + 0x00), memcpy_retl_o2_plus_1)
0353 EX_LD(LOAD(ldub, %o1 + 0x01, %g1), memcpy_retl_o2)
0354 subcc %o2, 1, %o2
0355 be,pn %icc, .Lexit
0356 EX_ST(STORE(stb, %g1, %o0 + 0x01), memcpy_retl_o2_plus_1)
0357 EX_LD(LOAD(ldub, %o1 + 0x02, %g1), memcpy_retl_o2)
0358 ba,pt %icc, .Lexit
0359 EX_ST(STORE(stb, %g1, %o0 + 0x02), memcpy_retl_o2)
0360
0361 .Lsmall:
0362 andcc %g2, 0x3, %g0
0363 bne,pn %icc, .Lsmall_unaligned
0364 andn %o2, 0x4 - 1, %o5
0365 sub %o2, %o5, %o2
0366 1:
0367 EX_LD(LOAD(lduw, %o1 + 0x00, %g1), memcpy_retl_o2_plus_o5)
0368 add %o1, 0x04, %o1
0369 subcc %o5, 0x04, %o5
0370 add %o0, 0x04, %o0
0371 bne,pt %icc, 1b
0372 EX_ST(STORE(stw, %g1, %o0 - 0x04), memcpy_retl_o2_plus_o5_plus_4)
0373 brz,pt %o2, .Lexit
0374 nop
0375 ba,a,pt %icc, .Ltiny
0376
0377 .Lsmall_unaligned:
0378 1: EX_LD(LOAD(ldub, %o1 + 0x00, %g1), memcpy_retl_o2)
0379 add %o1, 1, %o1
0380 add %o0, 1, %o0
0381 subcc %o2, 1, %o2
0382 bne,pt %icc, 1b
0383 EX_ST(STORE(stb, %g1, %o0 - 0x01), memcpy_retl_o2_plus_1)
0384 ba,a,pt %icc, .Lexit
0385 nop
0386 .size FUNC_NAME, .-FUNC_NAME