Back to index

glibc  2.9
wordcopy.c
Go to the documentation of this file.
00001 /* _memcopy.c -- subroutines for memory copy functions.
00002    Copyright (C) 1991, 1996, 2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Torbjorn Granlund (tege@sics.se).
00005    Updated for POWER6 by Steven Munroe (sjmunroe@us.ibm.com).
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
00023 
00024 #include <stddef.h>
00025 #include <memcopy.h>
00026 
00027 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
00028    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
00029    Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
00030 
00031 void
00032 _wordcopy_fwd_aligned (dstp, srcp, len)
00033      long int dstp;
00034      long int srcp;
00035      size_t len;
00036 {
00037   op_t a0, a1;
00038 
00039   if (len & 1)
00040   {
00041     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
00042     
00043     if (len == 1)
00044       return;
00045     srcp += OPSIZ;
00046     dstp += OPSIZ;
00047     len -= 1;
00048   }
00049 
00050   do
00051     {
00052       a0 = ((op_t *) srcp)[0];
00053       a1 = ((op_t *) srcp)[1];
00054       ((op_t *) dstp)[0] = a0;
00055       ((op_t *) dstp)[1] = a1;
00056 
00057       srcp += 2 * OPSIZ;
00058       dstp += 2 * OPSIZ;
00059       len -= 2;
00060     }
00061   while (len != 0);
00062 }
00063 
00064 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
00065    block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
00066    DSTP should be aligned for memory operations on `op_t's, but SRCP must
00067    *not* be aligned.  */
00068 
00069 void
00070 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
00071      long int dstp;
00072      long int srcp;
00073      size_t len;
00074 {
00075   op_t a0, a1, a2;
00076   int sh_1, sh_2;
00077   int align;
00078 
00079   /* Calculate how to shift a word read at the memory operation
00080      aligned srcp to make it aligned for copy.  */
00081 
00082   align = srcp % OPSIZ;
00083   sh_1 = 8 * (srcp % OPSIZ);
00084   sh_2 = 8 * OPSIZ - sh_1;
00085 
00086   /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
00087      it points in the middle of.  */
00088   srcp &= -OPSIZ;
00089   a0 = ((op_t *) srcp)[0];
00090 
00091   if (len & 1)
00092   {
00093     a1 = ((op_t *) srcp)[1];
00094     ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
00095     
00096     if (len == 1)
00097       return;
00098     
00099     a0 = a1;
00100     srcp += OPSIZ;
00101     dstp += OPSIZ;
00102     len -= 1;
00103   }
00104 
00105   switch (align)
00106     {
00107     case 1:
00108       do
00109         {
00110           a1 = ((op_t *) srcp)[1];
00111           a2 = ((op_t *) srcp)[2];
00112           ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (32-8));
00113           ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (32-8));
00114           a0 = a2;
00115     
00116           srcp += 2 * OPSIZ;
00117           dstp += 2 * OPSIZ;
00118           len -= 2;
00119         }
00120       while (len != 0);
00121       break;
00122     case 2:
00123       do
00124         {
00125           a1 = ((op_t *) srcp)[1];
00126           a2 = ((op_t *) srcp)[2];
00127           ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (32-16));
00128           ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (32-16));
00129           a0 = a2;
00130     
00131           srcp += 2 * OPSIZ;
00132           dstp += 2 * OPSIZ;
00133           len -= 2;
00134         }
00135       while (len != 0);
00136       break;
00137     case 3:
00138       do
00139         {
00140           a1 = ((op_t *) srcp)[1];
00141           a2 = ((op_t *) srcp)[2];
00142           ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (32-24));
00143           ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (32-24));
00144           a0 = a2;
00145     
00146           srcp += 2 * OPSIZ;
00147           dstp += 2 * OPSIZ;
00148           len -= 2;
00149         }
00150       while (len != 0);
00151       break;
00152     }
00153 
00154 }
00155 
00156 /* _wordcopy_bwd_aligned -- Copy block finishing right before
00157    SRCP to block finishing right before DSTP with LEN `op_t' words
00158    (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
00159    operations on `op_t's.  */
00160 
00161 void
00162 _wordcopy_bwd_aligned (dstp, srcp, len)
00163      long int dstp;
00164      long int srcp;
00165      size_t len;
00166 {
00167   op_t a0, a1;
00168 
00169   if (len & 1)
00170   {
00171     srcp -= OPSIZ;
00172     dstp -= OPSIZ;
00173     ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
00174     
00175     if (len == 1)
00176       return;
00177     len -= 1;
00178   }
00179 
00180   do
00181     {
00182       srcp -= 2 * OPSIZ;
00183       dstp -= 2 * OPSIZ;
00184 
00185       a1 = ((op_t *) srcp)[1];
00186       a0 = ((op_t *) srcp)[0];
00187       ((op_t *) dstp)[1] = a1;
00188       ((op_t *) dstp)[0] = a0;
00189 
00190       len -= 2;
00191     }
00192   while (len != 0);
00193 }
00194 
00195 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
00196    before SRCP to block finishing right before DSTP with LEN `op_t'
00197    words (not LEN bytes!).  DSTP should be aligned for memory
00198    operations on `op_t', but SRCP must *not* be aligned.  */
00199 
00200 void
00201 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
00202      long int dstp;
00203      long int srcp;
00204      size_t len;
00205 {
00206   op_t a0, a1, a2;
00207   int sh_1, sh_2;
00208   int align;
00209 
00210   /* Calculate how to shift a word read at the memory operation
00211      aligned srcp to make it aligned for copy.  */
00212 
00213   align = srcp % OPSIZ;
00214   sh_1 = 8 * (srcp % OPSIZ);
00215   sh_2 = 8 * OPSIZ - sh_1;
00216 
00217   /* Make srcp aligned by rounding it down to the beginning of the op_t
00218      it points in the middle of.  */
00219   srcp &= -OPSIZ;
00220   a2 = ((op_t *) srcp)[0];
00221 
00222   if (len & 1)
00223   {
00224     srcp -= OPSIZ;
00225     dstp -= OPSIZ;
00226     a1 = ((op_t *) srcp)[0];
00227     ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
00228 
00229     if (len == 1)
00230       return;
00231 
00232     a2 = a1;
00233     len -= 1;
00234   }
00235 
00236   switch (align)
00237     {
00238     case 1:
00239       do
00240         {
00241           srcp -= 2 * OPSIZ;
00242           dstp -= 2 * OPSIZ;
00243     
00244           a1 = ((op_t *) srcp)[1];
00245           a0 = ((op_t *) srcp)[0];
00246           ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (32-8));
00247           ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (32-8));
00248           a2 = a0;
00249     
00250           len -= 2;
00251         }
00252       while (len != 0);
00253       break;
00254     case 2:
00255       do
00256         {
00257           srcp -= 2 * OPSIZ;
00258           dstp -= 2 * OPSIZ;
00259     
00260           a1 = ((op_t *) srcp)[1];
00261           a0 = ((op_t *) srcp)[0];
00262           ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (32-16));
00263           ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (32-16));
00264           a2 = a0;
00265     
00266           len -= 2;
00267         }
00268       while (len != 0);
00269       break;
00270     case 3:
00271       do
00272         {
00273           srcp -= 2 * OPSIZ;
00274           dstp -= 2 * OPSIZ;
00275     
00276           a1 = ((op_t *) srcp)[1];
00277           a0 = ((op_t *) srcp)[0];
00278           ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (32-24));
00279           ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (32-24));
00280           a2 = a0;
00281     
00282           len -= 2;
00283         }
00284       while (len != 0);
00285       break;
00286     }
00287 }