(root)/
glibc-2.38/
sysdeps/
powerpc/
power4/
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  #ifndef WORDCOPY_FWD_DEST_ALIGNED
      68  # define WORDCOPY_FWD_DEST_ALIGNED _wordcopy_fwd_dest_aligned
      69  #endif
      70  
      71  void
      72  WORDCOPY_FWD_DEST_ALIGNED (long int dstp, long int srcp, 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  #ifndef WORDCOPY_BWD_ALIGNED
     123  # define WORDCOPY_BWD_ALIGNED _wordcopy_bwd_aligned
     124  #endif
     125  
     126  void
     127  WORDCOPY_BWD_ALIGNED (long int dstp, long int srcp, size_t len)
     128  {
     129    op_t a0, a1;
     130  
     131    if (len & 1)
     132    {
     133      srcp -= OPSIZ;
     134      dstp -= OPSIZ;
     135      ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
     136  
     137      if (len == 1)
     138        return;
     139      len -= 1;
     140    }
     141  
     142    do
     143      {
     144        srcp -= 2 * OPSIZ;
     145        dstp -= 2 * OPSIZ;
     146  
     147        a1 = ((op_t *) srcp)[1];
     148        a0 = ((op_t *) srcp)[0];
     149        ((op_t *) dstp)[1] = a1;
     150        ((op_t *) dstp)[0] = a0;
     151  
     152        len -= 2;
     153      }
     154    while (len != 0);
     155  }
     156  
     157  /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
     158     before SRCP to block finishing right before DSTP with LEN `op_t'
     159     words (not LEN bytes!).  DSTP should be aligned for memory
     160     operations on `op_t', but SRCP must *not* be aligned.  */
     161  
     162  #ifndef WORDCOPY_BWD_DEST_ALIGNED
     163  # define WORDCOPY_BWD_DEST_ALIGNED _wordcopy_bwd_dest_aligned
     164  #endif
     165  
     166  void
     167  WORDCOPY_BWD_DEST_ALIGNED (long int dstp, long int srcp, size_t len)
     168  {
     169    op_t a0, a1, a2;
     170    int sh_1, sh_2;
     171  
     172    /* Calculate how to shift a word read at the memory operation
     173       aligned srcp to make it aligned for copy.  */
     174  
     175    sh_1 = 8 * (srcp % OPSIZ);
     176    sh_2 = 8 * OPSIZ - sh_1;
     177  
     178    /* Make srcp aligned by rounding it down to the beginning of the op_t
     179       it points in the middle of.  */
     180    srcp &= -OPSIZ;
     181    a2 = ((op_t *) srcp)[0];
     182  
     183    if (len & 1)
     184    {
     185      srcp -= OPSIZ;
     186      dstp -= OPSIZ;
     187      a1 = ((op_t *) srcp)[0];
     188      ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
     189  
     190      if (len == 1)
     191        return;
     192  
     193      a2 = a1;
     194      len -= 1;
     195    }
     196  
     197    do
     198      {
     199        srcp -= 2 * OPSIZ;
     200        dstp -= 2 * OPSIZ;
     201  
     202        a1 = ((op_t *) srcp)[1];
     203        a0 = ((op_t *) srcp)[0];
     204        ((op_t *) dstp)[1] = MERGE (a1, sh_1, a2, sh_2);
     205        ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
     206        a2 = a0;
     207  
     208        len -= 2;
     209      }
     210    while (len != 0);
     211  }