Ticket #144: inetutils-1.5-memcpy_sparc64.patch

File inetutils-1.5-memcpy_sparc64.patch, 22.5 kB (added by kb0iic, 5 months ago)

Patch for inetutils-1.5 and sparc64 to work around a segfault

  • inetutils-1.5/ping/Makefile.in

    old new  
    109109PROGRAMS = $(bin_PROGRAMS) 
    110110am_ping_OBJECTS = ping.$(OBJEXT) ping_common.$(OBJEXT) \ 
    111111        ping_echo.$(OBJEXT) ping_address.$(OBJEXT) \ 
    112         ping_router.$(OBJEXT) ping_timestamp.$(OBJEXT) 
     112        ping_router.$(OBJEXT) ping_timestamp.$(OBJEXT) \ 
     113        wordcopy.$(OBJEXT) 
    113114ping_OBJECTS = $(am_ping_OBJECTS) 
    114115ping_DEPENDENCIES = 
    115116am_ping6_OBJECTS = ping6.$(OBJEXT) ping_common.$(OBJEXT) 
     
    333334ping_LDADD = -L../libinetutils -linetutils -L../libicmp -licmp -L../lib -lgnu 
    334335ping6_LDADD = -L../lib -lgnu -L../libinetutils -linetutils 
    335336INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/libicmp  
    336 ping_SOURCES = ping.c ping_common.c ping_echo.c ping_address.c \ 
    337   ping_router.c ping_timestamp.c ping_common.h  ping_impl.h 
     337ping_SOURCES = memcopy.h pagecopy.h ping.c ping_common.c \ 
     338  ping_echo.c ping_address.c ping_router.c ping_timestamp.c \ 
     339  ping_common.h  ping_impl.h wordcopy.c 
    338340 
    339341ping6_SOURCES = ping6.c ping_common.c ping_common.h ping6.h 
    340342SUIDMODE = -o root -m 4775 
  • inetutils-1.5/ping/memcopy.h

    old new  
     1/* memcopy.h -- definitions for memory copy functions.  Generic C version. 
     2   Copyright (C) 1991, 1992, 1993, 1997, 2004 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/* The strategy of the memory functions is: 
     22 
     23     1. Copy bytes until the destination pointer is aligned. 
     24 
     25     2. Copy words in unrolled loops.  If the source and destination 
     26     are not aligned in the same way, use word memory operations, 
     27     but shift and merge two read words before writing. 
     28 
     29     3. Copy the few remaining bytes. 
     30 
     31   This is fast on processors that have at least 10 registers for 
     32   allocation by GCC, and that can access memory at reg+const in one 
     33   instruction. 
     34 
     35   I made an "exhaustive" test of this memmove when I wrote it, 
     36   exhaustive in the sense that I tried all alignment and length 
     37   combinations, with and without overlap.  */ 
     38 
     39#include <sys/cdefs.h> 
     40#include <endian.h> 
     41 
     42/* The macros defined in this file are: 
     43 
     44   BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) 
     45 
     46   BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) 
     47 
     48   WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy) 
     49 
     50   WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy) 
     51 
     52   MERGE(old_word, sh_1, new_word, sh_2) 
     53     [I fail to understand.  I feel stupid.  --roland] 
     54*/ 
     55 
     56/* Type to use for aligned memory operations. 
     57   This should normally be the biggest type supported by a single load 
     58   and store.  */ 
     59#define op_t    unsigned long int 
     60#define OPSIZ   (sizeof(op_t)) 
     61 
     62/* Type to use for unaligned operations.  */ 
     63typedef unsigned char byte; 
     64 
     65/* Optimal type for storing bytes in registers.  */ 
     66#define reg_char        char 
     67 
     68#if __BYTE_ORDER == __LITTLE_ENDIAN 
     69#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) 
     70#endif 
     71#if __BYTE_ORDER == __BIG_ENDIAN 
     72#define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) 
     73#endif 
     74 
     75/* Copy exactly NBYTES bytes from SRC_BP to DST_BP, 
     76   without any assumptions about alignment of the pointers.  */ 
     77#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes)                                 \ 
     78  do                                                                          \ 
     79    {                                                                         \ 
     80      size_t __nbytes = (nbytes);                                             \ 
     81      while (__nbytes > 0)                                                    \ 
     82        {                                                                     \ 
     83          byte __x = ((byte *) src_bp)[0];                                    \ 
     84          src_bp += 1;                                                        \ 
     85          __nbytes -= 1;                                                      \ 
     86          ((byte *) dst_bp)[0] = __x;                                         \ 
     87          dst_bp += 1;                                                        \ 
     88        }                                                                     \ 
     89    } while (0) 
     90 
     91/* Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, 
     92   beginning at the bytes right before the pointers and continuing towards 
     93   smaller addresses.  Don't assume anything about alignment of the 
     94   pointers.  */ 
     95#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes)                                 \ 
     96  do                                                                          \ 
     97    {                                                                         \ 
     98      size_t __nbytes = (nbytes);                                             \ 
     99      while (__nbytes > 0)                                                    \ 
     100        {                                                                     \ 
     101          byte __x;                                                           \ 
     102          src_ep -= 1;                                                        \ 
     103          __x = ((byte *) src_ep)[0];                                         \ 
     104          dst_ep -= 1;                                                        \ 
     105          __nbytes -= 1;                                                      \ 
     106          ((byte *) dst_ep)[0] = __x;                                         \ 
     107        }                                                                     \ 
     108    } while (0) 
     109 
     110/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with 
     111   the assumption that DST_BP is aligned on an OPSIZ multiple.  If 
     112   not all bytes could be easily copied, store remaining number of bytes 
     113   in NBYTES_LEFT, otherwise store 0.  */ 
     114extern void _wordcopy_fwd_aligned (long int, long int, size_t) __THROW; 
     115extern void _wordcopy_fwd_dest_aligned (long int, long int, size_t) __THROW; 
     116#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes)                    \ 
     117  do                                                                          \ 
     118    {                                                                         \ 
     119      if (src_bp % OPSIZ == 0)                                                \ 
     120        _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);             \ 
     121      else                                                                    \ 
     122        _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);        \ 
     123      src_bp += (nbytes) & -OPSIZ;                                            \ 
     124      dst_bp += (nbytes) & -OPSIZ;                                            \ 
     125      (nbytes_left) = (nbytes) % OPSIZ;                                       \ 
     126    } while (0) 
     127 
     128/* Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, 
     129   beginning at the words (of type op_t) right before the pointers and 
     130   continuing towards smaller addresses.  May take advantage of that 
     131   DST_END_PTR is aligned on an OPSIZ multiple.  If not all bytes could be 
     132   easily copied, store remaining number of bytes in NBYTES_REMAINING, 
     133   otherwise store 0.  */ 
     134extern void _wordcopy_bwd_aligned (long int, long int, size_t) __THROW; 
     135extern void _wordcopy_bwd_dest_aligned (long int, long int, size_t) __THROW; 
     136#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes)                    \ 
     137  do                                                                          \ 
     138    {                                                                         \ 
     139      if (src_ep % OPSIZ == 0)                                                \ 
     140        _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);             \ 
     141      else                                                                    \ 
     142        _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);        \ 
     143      src_ep -= (nbytes) & -OPSIZ;                                            \ 
     144      dst_ep -= (nbytes) & -OPSIZ;                                            \ 
     145      (nbytes_left) = (nbytes) % OPSIZ;                                       \ 
     146    } while (0) 
     147 
     148 
     149/* Threshold value for when to enter the unrolled loops.  */ 
     150#define OP_T_THRES      16 
  • inetutils-1.5/ping/pagecopy.h

    old new  
     1/* Macros for copying by pages; used in memcpy, memmove.  Generic macros. 
     2   Copyright (C) 1995, 1997 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, write to the Free 
     17   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
     18   02111-1307 USA.  */ 
     19 
     20/* This file defines the macro: 
     21 
     22   PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nbytes) 
     23 
     24   which is invoked like WORD_COPY_FWD et al.  The pointers should be at 
     25   least word aligned.  This will check if virtual copying by pages can and 
     26   should be done and do it if so. 
     27 
     28   System-specific pagecopy.h files should define these macros and then 
     29   #include this file: 
     30 
     31   PAGE_COPY_THRESHOLD 
     32   -- Minimum size for which virtual copying by pages is worthwhile. 
     33 
     34   PAGE_SIZE 
     35   -- Size of a page. 
     36 
     37   PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes) 
     38   -- Macro to perform the virtual copy operation. 
     39   The pointers will be aligned to PAGE_SIZE bytes. 
     40*/ 
     41 
     42 
     43#if PAGE_COPY_THRESHOLD 
     44 
     45#include <assert.h> 
     46 
     47#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes)                  \ 
     48  do                                                                          \ 
     49    {                                                                         \ 
     50      if ((nbytes) >= PAGE_COPY_THRESHOLD &&                                  \ 
     51          PAGE_OFFSET ((dstp) - (srcp)) == 0)                                 \ 
     52        {                                                                     \ 
     53          /* The amount to copy is past the threshold for copying             \ 
     54             pages virtually with kernel VM operations, and the               \ 
     55             source and destination addresses have the same alignment.  */    \ 
     56          size_t nbytes_before = PAGE_OFFSET (-(dstp));                       \ 
     57          if (nbytes_before != 0)                                             \ 
     58            {                                                                 \ 
     59              /* First copy the words before the first page boundary.  */     \ 
     60              WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before);         \ 
     61              assert (nbytes_left == 0);                                      \ 
     62              nbytes -= nbytes_before;                                        \ 
     63            }                                                                 \ 
     64          PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes);                    \ 
     65        }                                                                     \ 
     66    } while (0) 
     67 
     68/* The page size is always a power of two, so we can avoid modulo division.  */ 
     69#define PAGE_OFFSET(n)  ((n) & (PAGE_SIZE - 1)) 
     70 
     71#else 
     72 
     73#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) /* nada */ 
     74 
     75#endif 
  • inetutils-1.5/ping/ping_echo.c

    old new  
    5757 
    5858#include <xalloc.h> 
    5959 
     60#ifndef memcpy 
     61#include "memcopy.h" 
     62#include "pagecopy.h" 
     63#endif 
     64 
    6065static int handler (int code, void *closure, 
    6166                   struct sockaddr_in *dest, struct sockaddr_in *from, 
    6267                   struct ip *ip, icmphdr_t *icmp, int datalen); 
     
    6873void print_icmp_header (struct sockaddr_in *from, 
    6974                              struct ip *ip, icmphdr_t *icmp, int len); 
    7075static void print_ip_opt (struct ip *ip, int hlen); 
    71  
    7276int 
    7377ping_echo (int argc, char **argv) 
    7478{ 
     
    169173      timing++; 
    170174      tp = (struct timeval *) icmp->icmp_data; 
    171175 
     176#define OP_T_THRES      16 
     177#undef memcpy 
     178void * 
     179        memcpy (dstpp, srcpp, len) 
     180        void *dstpp; 
     181const void *srcpp; 
     182size_t len; 
     183{ 
     184        unsigned long int dstp = (long int) dstpp; 
     185        unsigned long int srcp = (long int) srcpp; 
     186 
     187        /* Copy from the beginning to the end. */ 
     188 
     189        /* If there not too few bytes to copy, use word copy. */ 
     190        if (len >= OP_T_THRES) 
     191        { 
     192                /* Copy just a few bytes to make DSTP aligned. */ 
     193                len -= (-dstp) % OPSIZ; 
     194                BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); 
     195 
     196                /* Copy whole pages from SRCP to DSTP by virtual address 
     197                   manipulation, as much as possible. */ 
     198 
     199                PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); 
     200 
     201                /* Copy from SRCP to DSTP taking advantage of the known alignment 
     202                   of DSTP. Number of bytes remaining is put in the third argument, 
     203                   i.e. in LEN. This number may vary from machine to machine. */ 
     204 
     205                WORD_COPY_FWD (dstp, srcp, len, len); 
     206 
     207                /* Fall out and copy the tail. */ 
     208        } 
     209 
     210        /* There are just a few bytes to copy. Use byte memory operations. */ 
     211        BYTE_COPY_FWD (dstp, srcp, len); 
     212 
     213        return dstpp; 
     214} 
     215 
    172216      /* Avoid unaligned data: */ 
    173217      memcpy (&tv1, tp, sizeof (tv1)); 
    174218      tvsub (&tv, &tv1); 
  • inetutils-1.5/ping/wordcopy.c

    old new  
     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 
     30void 
     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  switch (len % 8) 
     39    { 
     40    case 2: 
     41      a0 = ((op_t *) srcp)[0]; 
     42      srcp -= 6 * OPSIZ; 
     43      dstp -= 7 * OPSIZ; 
     44      len += 6; 
     45      goto do1; 
     46    case 3: 
     47      a1 = ((op_t *) srcp)[0]; 
     48      srcp -= 5 * OPSIZ; 
     49      dstp -= 6 * OPSIZ; 
     50      len += 5; 
     51      goto do2; 
     52    case 4: 
     53      a0 = ((op_t *) srcp)[0]; 
     54      srcp -= 4 * OPSIZ; 
     55      dstp -= 5 * OPSIZ; 
     56      len += 4; 
     57      goto do3; 
     58    case 5: 
     59      a1 = ((op_t *) srcp)[0]; 
     60      srcp -= 3 * OPSIZ; 
     61      dstp -= 4 * OPSIZ; 
     62      len += 3; 
     63      goto do4; 
     64    case 6: 
     65      a0 = ((op_t *) srcp)[0]; 
     66      srcp -= 2 * OPSIZ; 
     67      dstp -= 3 * OPSIZ; 
     68      len += 2; 
     69      goto do5; 
     70    case 7: 
     71      a1 = ((op_t *) srcp)[0]; 
     72      srcp -= 1 * OPSIZ; 
     73      dstp -= 2 * OPSIZ; 
     74      len += 1; 
     75      goto do6; 
     76 
     77    case 0: 
     78      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     79        return; 
     80      a0 = ((op_t *) srcp)[0]; 
     81      srcp -= 0 * OPSIZ; 
     82      dstp -= 1 * OPSIZ; 
     83      goto do7; 
     84    case 1: 
     85      a1 = ((op_t *) srcp)[0]; 
     86      srcp -=-1 * OPSIZ; 
     87      dstp -= 0 * OPSIZ; 
     88      len -= 1; 
     89      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     90        goto do0; 
     91      goto do8;                 /* No-op.  */ 
     92    } 
     93 
     94  do 
     95    { 
     96    do8: 
     97      a0 = ((op_t *) srcp)[0]; 
     98      ((op_t *) dstp)[0] = a1; 
     99    do7: 
     100      a1 = ((op_t *) srcp)[1]; 
     101      ((op_t *) dstp)[1] = a0; 
     102    do6: 
     103      a0 = ((op_t *) srcp)[2]; 
     104      ((op_t *) dstp)[2] = a1; 
     105    do5: 
     106      a1 = ((op_t *) srcp)[3]; 
     107      ((op_t *) dstp)[3] = a0; 
     108    do4: 
     109      a0 = ((op_t *) srcp)[4]; 
     110      ((op_t *) dstp)[4] = a1; 
     111    do3: 
     112      a1 = ((op_t *) srcp)[5]; 
     113      ((op_t *) dstp)[5] = a0; 
     114    do2: 
     115      a0 = ((op_t *) srcp)[6]; 
     116      ((op_t *) dstp)[6] = a1; 
     117    do1: 
     118      a1 = ((op_t *) srcp)[7]; 
     119      ((op_t *) dstp)[7] = a0; 
     120 
     121      srcp += 8 * OPSIZ; 
     122      dstp += 8 * OPSIZ; 
     123      len -= 8; 
     124    } 
     125  while (len != 0); 
     126 
     127  /* This is the right position for do0.  Please don't move 
     128     it into the loop.  */ 
     129 do0: 
     130  ((op_t *) dstp)[0] = a1; 
     131} 
     132 
     133/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to 
     134   block beginning at DSTP with LEN `op_t' words (not LEN bytes!). 
     135   DSTP should be aligned for memory operations on `op_t's, but SRCP must 
     136   *not* be aligned.  */ 
     137 
     138void 
     139_wordcopy_fwd_dest_aligned (dstp, srcp, len) 
     140     long int dstp; 
     141     long int srcp; 
     142     size_t len; 
     143{ 
     144  op_t a0, a1, a2, a3; 
     145  int sh_1, sh_2; 
     146 
     147  /* Calculate how to shift a word read at the memory operation 
     148     aligned srcp to make it aligned for copy.  */ 
     149 
     150  sh_1 = 8 * (srcp % OPSIZ); 
     151  sh_2 = 8 * OPSIZ - sh_1; 
     152 
     153  /* Make SRCP aligned by rounding it down to the beginning of the `op_t' 
     154     it points in the middle of.  */ 
     155  srcp &= -OPSIZ; 
     156 
     157  switch (len % 4) 
     158    { 
     159    case 2: 
     160      a1 = ((op_t *) srcp)[0]; 
     161      a2 = ((op_t *) srcp)[1]; 
     162      srcp -= 1 * OPSIZ; 
     163      dstp -= 3 * OPSIZ; 
     164      len += 2; 
     165      goto do1; 
     166    case 3: 
     167      a0 = ((op_t *) srcp)[0]; 
     168      a1 = ((op_t *) srcp)[1]; 
     169      srcp -= 0 * OPSIZ; 
     170      dstp -= 2 * OPSIZ; 
     171      len += 1; 
     172      goto do2; 
     173    case 0: 
     174      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     175        return; 
     176      a3 = ((op_t *) srcp)[0]; 
     177      a0 = ((op_t *) srcp)[1]; 
     178      srcp -=-1 * OPSIZ; 
     179      dstp -= 1 * OPSIZ; 
     180      len += 0; 
     181      goto do3; 
     182    case 1: 
     183      a2 = ((op_t *) srcp)[0]; 
     184      a3 = ((op_t *) srcp)[1]; 
     185      srcp -=-2 * OPSIZ; 
     186      dstp -= 0 * OPSIZ; 
     187      len -= 1; 
     188      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     189        goto do0; 
     190      goto do4;                 /* No-op.  */ 
     191    } 
     192 
     193  do 
     194    { 
     195    do4: 
     196      a0 = ((op_t *) srcp)[0]; 
     197      ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); 
     198    do3: 
     199      a1 = ((op_t *) srcp)[1]; 
     200      ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2); 
     201    do2: 
     202      a2 = ((op_t *) srcp)[2]; 
     203      ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2); 
     204    do1: 
     205      a3 = ((op_t *) srcp)[3]; 
     206      ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2); 
     207 
     208      srcp += 4 * OPSIZ; 
     209      dstp += 4 * OPSIZ; 
     210      len -= 4; 
     211    } 
     212  while (len != 0); 
     213 
     214  /* This is the right position for do0.  Please don't move 
     215     it into the loop.  */ 
     216 do0: 
     217  ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); 
     218} 
     219 
     220/* _wordcopy_bwd_aligned -- Copy block finishing right before 
     221   SRCP to block finishing right before DSTP with LEN `op_t' words 
     222   (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory 
     223   operations on `op_t's.  */ 
     224 
     225void 
     226_wordcopy_bwd_aligned (dstp, srcp, len) 
     227     long int dstp; 
     228     long int srcp; 
     229     size_t len; 
     230{ 
     231  op_t a0, a1; 
     232 
     233  switch (len % 8) 
     234    { 
     235    case 2: 
     236      srcp -= 2 * OPSIZ; 
     237      dstp -= 1 * OPSIZ; 
     238      a0 = ((op_t *) srcp)[1]; 
     239      len += 6; 
     240      goto do1; 
     241    case 3: 
     242      srcp -= 3 * OPSIZ; 
     243      dstp -= 2 * OPSIZ; 
     244      a1 = ((op_t *) srcp)[2]; 
     245      len += 5; 
     246      goto do2; 
     247    case 4: 
     248      srcp -= 4 * OPSIZ; 
     249      dstp -= 3 * OPSIZ; 
     250      a0 = ((op_t *) srcp)[3]; 
     251      len += 4; 
     252      goto do3; 
     253    case 5: 
     254      srcp -= 5 * OPSIZ; 
     255      dstp -= 4 * OPSIZ; 
     256      a1 = ((op_t *) srcp)[4]; 
     257      len += 3; 
     258      goto do4; 
     259    case 6: 
     260      srcp -= 6 * OPSIZ; 
     261      dstp -= 5 * OPSIZ; 
     262      a0 = ((op_t *) srcp)[5]; 
     263      len += 2; 
     264      goto do5; 
     265    case 7: 
     266      srcp -= 7 * OPSIZ; 
     267      dstp -= 6 * OPSIZ; 
     268      a1 = ((op_t *) srcp)[6]; 
     269      len += 1; 
     270      goto do6; 
     271 
     272    case 0: 
     273      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     274        return; 
     275      srcp -= 8 * OPSIZ; 
     276      dstp -= 7 * OPSIZ; 
     277      a0 = ((op_t *) srcp)[7]; 
     278      goto do7; 
     279    case 1: 
     280      srcp -= 9 * OPSIZ; 
     281      dstp -= 8 * OPSIZ; 
     282      a1 = ((op_t *) srcp)[8]; 
     283      len -= 1; 
     284      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     285        goto do0; 
     286      goto do8;                 /* No-op.  */ 
     287    } 
     288 
     289  do 
     290    { 
     291    do8: 
     292      a0 = ((op_t *) srcp)[7]; 
     293      ((op_t *) dstp)[7] = a1; 
     294    do7: 
     295      a1 = ((op_t *) srcp)[6]; 
     296      ((op_t *) dstp)[6] = a0; 
     297    do6: 
     298      a0 = ((op_t *) srcp)[5]; 
     299      ((op_t *) dstp)[5] = a1; 
     300    do5: 
     301      a1 = ((op_t *) srcp)[4]; 
     302      ((op_t *) dstp)[4] = a0; 
     303    do4: 
     304      a0 = ((op_t *) srcp)[3]; 
     305      ((op_t *) dstp)[3] = a1; 
     306    do3: 
     307      a1 = ((op_t *) srcp)[2]; 
     308      ((op_t *) dstp)[2] = a0; 
     309    do2: 
     310      a0 = ((op_t *) srcp)[1]; 
     311      ((op_t *) dstp)[1] = a1; 
     312    do1: 
     313      a1 = ((op_t *) srcp)[0]; 
     314      ((op_t *) dstp)[0] = a0; 
     315 
     316      srcp -= 8 * OPSIZ; 
     317      dstp -= 8 * OPSIZ; 
     318      len -= 8; 
     319    } 
     320  while (len != 0); 
     321 
     322  /* This is the right position for do0.  Please don't move 
     323     it into the loop.  */ 
     324 do0: 
     325  ((op_t *) dstp)[7] = a1; 
     326} 
     327 
     328/* _wordcopy_bwd_dest_aligned -- Copy block finishing right 
     329   before SRCP to block finishing right before DSTP with LEN `op_t' 
     330   words (not LEN bytes!).  DSTP should be aligned for memory 
     331   operations on `op_t', but SRCP must *not* be aligned.  */ 
     332 
     333void 
     334_wordcopy_bwd_dest_aligned (dstp, srcp, len) 
     335     long int dstp; 
     336     long int srcp; 
     337     size_t len; 
     338{ 
     339  op_t a0, a1, a2, a3; 
     340  int sh_1, sh_2; 
     341 
     342  /* Calculate how to shift a word read at the memory operation 
     343     aligned srcp to make it aligned for copy.  */ 
     344 
     345  sh_1 = 8 * (srcp % OPSIZ); 
     346  sh_2 = 8 * OPSIZ - sh_1; 
     347 
     348  /* Make srcp aligned by rounding it down to the beginning of the op_t 
     349     it points in the middle of.  */ 
     350  srcp &= -OPSIZ; 
     351  srcp += OPSIZ; 
     352 
     353  switch (len % 4) 
     354    { 
     355    case 2: 
     356      srcp -= 3 * OPSIZ; 
     357      dstp -= 1 * OPSIZ; 
     358      a2 = ((op_t *) srcp)[2]; 
     359      a1 = ((op_t *) srcp)[1]; 
     360      len += 2; 
     361      goto do1; 
     362    case 3: 
     363      srcp -= 4 * OPSIZ; 
     364      dstp -= 2 * OPSIZ; 
     365      a3 = ((op_t *) srcp)[3]; 
     366      a2 = ((op_t *) srcp)[2]; 
     367      len += 1; 
     368      goto do2; 
     369    case 0: 
     370      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     371        return; 
     372      srcp -= 5 * OPSIZ; 
     373      dstp -= 3 * OPSIZ; 
     374      a0 = ((op_t *) srcp)[4]; 
     375      a3 = ((op_t *) srcp)[3]; 
     376      goto do3; 
     377    case 1: 
     378      srcp -= 6 * OPSIZ; 
     379      dstp -= 4 * OPSIZ; 
     380      a1 = ((op_t *) srcp)[5]; 
     381      a0 = ((op_t *) srcp)[4]; 
     382      len -= 1; 
     383      if (OP_T_THRES <= 3 * OPSIZ && len == 0) 
     384        goto do0; 
     385      goto do4;                 /* No-op.  */ 
     386    } 
     387 
     388  do 
     389    { 
     390    do4: 
     391      a3 = ((op_t *) srcp)[3]; 
     392      ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); 
     393    do3: 
     394      a2 = ((op_t *) srcp)[2]; 
     395      ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2); 
     396    do2: 
     397      a1 = ((op_t *) srcp)[1]; 
     398      ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2); 
     399    do1: 
     400      a0 = ((op_t *) srcp)[0]; 
     401      ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2); 
     402 
     403      srcp -= 4 * OPSIZ; 
     404      dstp -= 4 * OPSIZ; 
     405      len -= 4; 
     406    } 
     407  while (len != 0); 
     408 
     409  /* This is the right position for do0.  Please don't move 
     410     it into the loop.  */ 
     411 do0: 
     412  ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); 
     413}