(root)/
glibc-2.38/
sysdeps/
powerpc/
power6/
wordcopy.c
       1  /* _memcopy.c -- subroutines for memory copy functions.
       2     Copyright (C) 1991-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       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.
       9  
      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.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
      20  
      21  #include <stddef.h>
      22  #include <memcopy.h>
      23  
      24  /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
      25     block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
      26     Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
      27  
      28  #ifndef WORDCOPY_FWD_ALIGNED
      29  # define WORDCOPY_FWD_ALIGNED _wordcopy_fwd_aligned
      30  #endif
      31  
      32  void
      33  WORDCOPY_FWD_ALIGNED (long int dstp, long int srcp, size_t len)
      34  {
      35    op_t a0, a1;
      36  
      37    if (len & 1)
      38    {
      39      ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
      40  
      41      if (len == 1)
      42        return;
      43      srcp += OPSIZ;
      44      dstp += OPSIZ;
      45      len -= 1;
      46    }
      47  
      48    do
      49      {
      50        a0 = ((op_t *) srcp)[0];
      51        a1 = ((op_t *) srcp)[1];
      52        ((op_t *) dstp)[0] = a0;
      53        ((op_t *) dstp)[1] = a1;
      54  
      55        srcp += 2 * OPSIZ;
      56        dstp += 2 * OPSIZ;
      57        len -= 2;
      58      }
      59    while (len != 0);
      60  }
      61  
      62  /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
      63     block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
      64     DSTP should be aligned for memory operations on `op_t's, but SRCP must
      65     *not* be aligned.  */
      66  
      67  #define fwd_align_merge(align)                                         \
      68    do                                                                   \
      69      {                                                                  \
      70        a1 = ((op_t *) srcp)[1];                                         \
      71        a2 = ((op_t *) srcp)[2];                                         \
      72        ((op_t *) dstp)[0] = MERGE (a0, align*8, a1, (__WORDSIZE-align*8)); \
      73        ((op_t *) dstp)[1] = MERGE (a1, align*8, a2, (__WORDSIZE-align*8)); \
      74        a0 = a2;                                                         \
      75        srcp += 2 * OPSIZ;                                               \
      76        dstp += 2 * OPSIZ;                                               \
      77        len -= 2;                                                                \
      78      }                                                                  \
      79    while (len != 0)
      80  
      81  #ifndef WORDCOPY_FWD_DEST_ALIGNED
      82  # define WORDCOPY_FWD_DEST_ALIGNED _wordcopy_fwd_dest_aligned
      83  #endif
      84  
      85  void
      86  WORDCOPY_FWD_DEST_ALIGNED (long int dstp, long int srcp, size_t len)
      87  {
      88    op_t a0, a1, a2;
      89    int sh_1, sh_2;
      90    int align;
      91  
      92    /* Calculate how to shift a word read at the memory operation
      93       aligned srcp to make it aligned for copy.  */
      94  
      95    align = srcp % OPSIZ;
      96    sh_1 = 8 * (srcp % OPSIZ);
      97    sh_2 = 8 * OPSIZ - sh_1;
      98  
      99    /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
     100       it points in the middle of.  */
     101    srcp &= -OPSIZ;
     102    a0 = ((op_t *) srcp)[0];
     103  
     104    if (len & 1)
     105    {
     106      a1 = ((op_t *) srcp)[1];
     107      ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
     108  
     109      if (len == 1)
     110        return;
     111  
     112      a0 = a1;
     113      srcp += OPSIZ;
     114      dstp += OPSIZ;
     115      len -= 1;
     116    }
     117  
     118    fwd_align_merge (align);
     119  
     120  }
     121  
     122  /* _wordcopy_bwd_aligned -- Copy block finishing right before
     123     SRCP to block finishing right before DSTP with LEN `op_t' words
     124     (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
     125     operations on `op_t's.  */
     126  
     127  #ifndef WORDCOPY_BWD_ALIGNED
     128  # define WORDCOPY_BWD_ALIGNED _wordcopy_bwd_aligned
     129  #endif
     130  
     131  void
     132  WORDCOPY_BWD_ALIGNED (long int dstp, long int srcp, size_t len)
     133  {
     134    op_t a0, a1;
     135  
     136    if (len & 1)
     137    {
     138      srcp -= OPSIZ;
     139      dstp -= OPSIZ;
     140      ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
     141  
     142      if (len == 1)
     143        return;
     144      len -= 1;
     145    }
     146  
     147    do
     148      {
     149        srcp -= 2 * OPSIZ;
     150        dstp -= 2 * OPSIZ;
     151  
     152        a1 = ((op_t *) srcp)[1];
     153        a0 = ((op_t *) srcp)[0];
     154        ((op_t *) dstp)[1] = a1;
     155        ((op_t *) dstp)[0] = a0;
     156  
     157        len -= 2;
     158      }
     159    while (len != 0);
     160  }
     161  
     162  #define bwd_align_merge(align)                                         \
     163    do                                                                   \
     164      {                                                                  \
     165        srcp -= 2 * OPSIZ;                                               \
     166        dstp -= 2 * OPSIZ;                                               \
     167        a1 = ((op_t *) srcp)[1];                                         \
     168        a0 = ((op_t *) srcp)[0];                                         \
     169        ((op_t *) dstp)[1] = MERGE (a1, align*8, a2, (__WORDSIZE-align*8)); \
     170        ((op_t *) dstp)[0] = MERGE (a0, align*8, a1, (__WORDSIZE-align*8)); \
     171        a2 = a0;                                                         \
     172        len -= 2;                                                                \
     173      }                                                                  \
     174    while (len != 0)
     175  
     176  /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
     177     before SRCP to block finishing right before DSTP with LEN `op_t'
     178     words (not LEN bytes!).  DSTP should be aligned for memory
     179     operations on `op_t', but SRCP must *not* be aligned.  */
     180  
     181  #ifndef WORDCOPY_BWD_DEST_ALIGNED
     182  # define WORDCOPY_BWD_DEST_ALIGNED _wordcopy_bwd_dest_aligned
     183  #endif
     184  
     185  void
     186  WORDCOPY_BWD_DEST_ALIGNED (long int dstp, long int srcp, size_t len)
     187  {
     188    op_t a0, a1, a2;
     189    int sh_1, sh_2;
     190    int align;
     191  
     192    /* Calculate how to shift a word read at the memory operation
     193       aligned srcp to make it aligned for copy.  */
     194  
     195    align = srcp % OPSIZ;
     196    sh_1 = 8 * (srcp % OPSIZ);
     197    sh_2 = 8 * OPSIZ - sh_1;
     198  
     199    /* Make srcp aligned by rounding it down to the beginning of the op_t
     200       it points in the middle of.  */
     201    srcp &= -OPSIZ;
     202    a2 = ((op_t *) srcp)[0];
     203  
     204    if (len & 1)
     205    {
     206      srcp -= OPSIZ;
     207      dstp -= OPSIZ;
     208      a1 = ((op_t *) srcp)[0];
     209      ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
     210  
     211      if (len == 1)
     212        return;
     213  
     214      a2 = a1;
     215      len -= 1;
     216    }
     217  
     218    bwd_align_merge (align);
     219  }