wordcopy for ppc32/power4.
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / powerpc32 / power4 / wordcopy.c
1 /* _memcopy.c -- subroutines for memory copy functions.
2    Copyright (C) 1991, 1996 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Torbjorn Granlund (tege@sics.se).
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
22
23 #include <stddef.h>
24 #include <memcopy.h>
25
26 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
27    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
28    Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
29
30 void
31 _wordcopy_fwd_aligned (dstp, srcp, len)
32      long int dstp;
33      long int srcp;
34      size_t len;
35 {
36   op_t a0, a1;
37
38   if (len & 1)
39   {
40     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
41     
42     if (len == 1)
43       return;
44     srcp += OPSIZ;
45     dstp += OPSIZ;
46     len -= 1;
47   }
48
49   do
50     {
51       a0 = ((op_t *) srcp)[0];
52       a1 = ((op_t *) srcp)[1];
53       ((op_t *) dstp)[0] = a0;
54       ((op_t *) dstp)[1] = a1;
55
56       srcp += 2 * OPSIZ;
57       dstp += 2 * OPSIZ;
58       len -= 2;
59     }
60   while (len != 0);
61 }
62
63 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
64    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
65    DSTP should be aligned for memory operations on `op_t's, but SRCP must
66    *not* be aligned.  */
67
68 void
69 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
70      long int dstp;
71      long int srcp;
72      size_t len;
73 {
74   op_t a0, a1, a2;
75   int sh_1, sh_2;
76
77   /* Calculate how to shift a word read at the memory operation
78      aligned srcp to make it aligned for copy.  */
79
80   sh_1 = 8 * (srcp % OPSIZ);
81   sh_2 = 8 * OPSIZ - sh_1;
82
83   /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
84      it points in the middle of.  */
85   srcp &= -OPSIZ;
86   a0 = ((op_t *) srcp)[0];
87
88   if (len & 1)
89   {
90     a1 = ((op_t *) srcp)[1];
91     ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
92     
93     if (len == 1)
94       return;
95     
96     a0 = a1;
97     srcp += OPSIZ;
98     dstp += OPSIZ;
99     len -= 1;
100   }
101
102   do
103     {
104       a1 = ((op_t *) srcp)[1];
105       a2 = ((op_t *) srcp)[2];
106       ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
107       ((op_t *) dstp)[1] = MERGE (a1, sh_1, a2, sh_2);
108       a0 = a2;
109
110       srcp += 2 * OPSIZ;
111       dstp += 2 * OPSIZ;
112       len -= 2;
113     }
114   while (len != 0);
115 }
116
117 /* _wordcopy_bwd_aligned -- Copy block finishing right before
118    SRCP to block finishing right before DSTP with LEN `op_t' words
119    (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
120    operations on `op_t's.  */
121
122 void
123 _wordcopy_bwd_aligned (dstp, srcp, len)
124      long int dstp;
125      long int srcp;
126      size_t len;
127 {
128   op_t a0, a1;
129
130   if (len & 1)
131   {
132     srcp -= OPSIZ;
133     dstp -= OPSIZ;
134     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
135     
136     if (len == 1)
137       return;
138     len -= 1;
139   }
140
141   do
142     {
143       srcp -= 2 * OPSIZ;
144       dstp -= 2 * OPSIZ;
145
146       a1 = ((op_t *) srcp)[1];
147       a0 = ((op_t *) srcp)[0];
148       ((op_t *) dstp)[1] = a1;
149       ((op_t *) dstp)[0] = a0;
150
151       len -= 2;
152     }
153   while (len != 0);
154 }
155
156 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
157    before SRCP to block finishing right before DSTP with LEN `op_t'
158    words (not LEN bytes!).  DSTP should be aligned for memory
159    operations on `op_t', but SRCP must *not* be aligned.  */
160
161 void
162 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
163      long int dstp;
164      long int srcp;
165      size_t len;
166 {
167   op_t a0, a1, a2;
168   int sh_1, sh_2;
169
170   /* Calculate how to shift a word read at the memory operation
171      aligned srcp to make it aligned for copy.  */
172
173   sh_1 = 8 * (srcp % OPSIZ);
174   sh_2 = 8 * OPSIZ - sh_1;
175
176   /* Make srcp aligned by rounding it down to the beginning of the op_t
177      it points in the middle of.  */
178   srcp &= -OPSIZ;
179   a2 = ((op_t *) srcp)[0];
180
181   if (len & 1)
182   {
183     srcp -= OPSIZ;
184     dstp -= OPSIZ;
185     a1 = ((op_t *) srcp)[0];
186     ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
187
188     if (len == 1)
189       return;
190
191     a2 = a1;
192     len -= 1;
193   }
194
195   do
196     {
197       srcp -= 2 * OPSIZ;
198       dstp -= 2 * OPSIZ;
199
200       a1 = ((op_t *) srcp)[1];
201       a0 = ((op_t *) srcp)[0];
202       ((op_t *) dstp)[1] = MERGE (a1, sh_1, a2, sh_2);
203       ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
204       a2 = a0;
205
206       len -= 2;
207     }
208   while (len != 0);
209 }