Update.
[glibc.git] / sysdeps / powerpc / powerpc64 / memcpy.S
blobc6d764595e2ca932a6fc67ccd31df21b2ffa2041
1 /* Optimized memcpy implementation for PowerPC64.
2    Copyright (C) 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
25    Returns 'dst'.
27    Memcpy handles short copies (< 32-bytes) using an unaligned
28    word lwz/stw loop.  The tail (remaining 1-3) bytes is handled with the
29    appropriate combination of byte and halfword load/stores. There is no
30    attempt to optimize the alignment of short moves.  The 64-bit
31    implementations of POWER3 and POWER4 do a reasonable job of handling
32    unligned load/stores that do not cross 32-byte boundries.
34    Longer moves (>= 32-bytes) justify the effort to get at least the
35    destination doubleword (8-byte) aligned.  Further optimization is
36    posible when both source and destination are doubleword aligned.
37    Each case has a optimized unrolled loop.   */
39 EALIGN (BP_SYM (memcpy), 5, 0)
40     cmpldi cr1,5,31
41     neg   0,3
42     std   30,-16(1)
43     std   31,-8(1)
44     rldicl. 0,0,0,61
45     mr    12,4
46     mr    31,5
47     mr    30,3
48     ble-  cr1,.L2
49     subf  31,0,5
51   /* Move 0-7 bytes as needed to get the destination doubleword alligned.  */
52     beq   0f
53     mtcrf 0x01,0
54 1:  bf    31,2f
55     lbz   6,0(12)
56     addi  12,12,1
57     stb   6,0(3)
58     addi  3,3,1
59 2:  bf    30,4f
60     lhz   6,0(12)
61     addi  12,12,2
62     sth   6,0(3)
63     addi  3,3,2
64 4:  bf    29,0f
65     lwz   6,0(12)
66     addi  12,12,4
67     stw   6,0(3)
68     addi  3,3,4
70   /* Copy doublewords from source to destination, assumpting the
71      destination is aligned on a doubleword boundary.
73      First verify that there is > 7 bytes to copy and check if the source
74      is also doubleword aligned.  If there are < 8 bytes to copy fall
75      through to the tail byte copy code.  Otherwise if the source and
76      destination are both doubleword aligned use an optimized doubleword
77      copy loop.  Otherwise the source has a different alignment and we use
78      a load, shift, store strategy.  */
79     rldicl. 0,12,0,61
80     cmpldi cr6,31,7
81     ble-  cr6,.L2  /* less than 8 bytes left.  */
82     bne-  0,.L6   /* Source is not DW aligned.  */
83     srdi. 9,31,3
84     mr    10,3
85     mr    11,12
87   /* Move doublewords where destination and source are aligned.
88      Use a unrolled loop to copy 4 doubleword (32-bytes) per iteration.
89      If the remainder is >0 and < 32 bytes copy 1-3 doublewords.  */
90     cmpldi      cr1,9,4
91     beq   0f
92     mtcrf 0x01,9
93     blt   cr1,2f
94     ld    6,0(11)
95     .align  4
97     ld    7,8(11)
98     addi  9,9,-4
99     std   6,0(10)
100     ld    6,16(11)
101     std   7,8(10)
102     ld    7,24(11)
103     addi  11,11,32
104     cmpldi      cr1,9,4
105     std   6,16(10)
106     blt   cr1,3f
107     ld    6,0(11)
108     std   7,24(10)
109     addi  10,10,32
110     b     4b
111 3:  std   7,24(10)
112     addi  10,10,32
113 2:  bf    30,1f
114     ld    6,0(11)
115     ld    7,8(11)
116     addi  11,11,16
117     std   6,0(10)
118     std   7,8(10)
119     addi  10,10,16
120 1:  bf    31,0f
121     ld    6,0(11)
122     addi  11,11,8
123     std   6,0(10)
124     addi  10,10,8
127 .L8:
128     rldicr 0,31,0,60
129     rldicl 31,31,0,61
130     add   3,3,0
131     add   12,12,0
133         /* Copy the tail for up to 31 bytes.  If this is the tail of a longer
134            copy then the destination will be aligned and the length will be
135            less than 8.  So it is normally not worth the set-up overhead to
136            get doubleword aligned and do doubleword load/store.  */
137 .L2:
138     mr.   10,31
139     cmpldi      cr1,31,4
140     beq   0f
141     mtcrf 0x01,31
142     blt   cr1,2f
143 4:  lwz   6,0(12)
144     addi  12,12,4
145     addi  10,10,-4
146     stw   6,0(3)
147     cmpldi      cr1,10,4
148     addi  3,3,4
149     bge   cr1,4b
150 2:  bf    30,1f
151     lhz   6,0(12)
152     addi  12,12,2
153     sth   6,0(3)
154     addi  3,3,2
155 1:  bf    31,0f
156     lbz   6,0(12)
157     addi  12,12,1
158     stb   6,0(3)
159     addi  3,3,1
161   /* Return original dst pointer.  */
162     ld 31,-8(1)
163     mr 3,30
164     ld 30,-16(1)
165     blr
167 .L6:
168     srdi 11,31,3
169     mr 4,3
170     mr 5,12
172   /* Copy doublewords where the destination is aligned but the source is
173      not.  Use aligned doubleword loads from the source, shifted to realign
174      the data, to allow aligned destination stores.  */
175     andi. 10,5,7
176     andi. 0,11,1
177     subf  5,10,5
178     ld    6,0(5)
179     sldi  10,10,3
180     ld    7,8(5)
181     subfic  9,10,64
182     beq   2f
183     sld   0,6,10
184     addi  11,11,-1
185     mr    6,7
186     addi  4,4,-8
187     cmpldi  11,0
188     b     1f
189 2:  addi  5,5,8
190     .align  4
191 0:  sld   0,6,10
192     srd   8,7,9
193     addi  11,11,-2
194     ld    6,8(5)
195     or    0,0,8
196     cmpldi  11,0
197     std   0,0(4)
198     sld   0,7,10
199 1:  srd   8,6,9
200     or    0,0,8
201     beq   8f
202     ld    7,16(5)
203     std   0,8(4)
204     addi  5,5,16
205     addi  4,4,16
206     b     0b
208     std   0,8(4)
209     b .L8
210 END_GEN_TB (BP_SYM (memcpy),TB_TOCLESS)
211 libc_hidden_builtin_def (memcpy)