| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 | 
							- /* Copyright (C) 1991,1993,1995,1997,1998,2003,2004
 
-    Free Software Foundation, Inc.
 
-    This file is part of the GNU C Library.
 
-    Contributed by Torbjorn Granlund (tege@sics.se).
 
-    The GNU C Library is free software; you can redistribute it and/or
 
-    modify it under the terms of the GNU Lesser General Public
 
-    License as published by the Free Software Foundation; either
 
-    version 2.1 of the License, or (at your option) any later version.
 
-    The GNU C Library is distributed in the hope that it will be useful,
 
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
-    Lesser General Public License for more details.
 
-    You should have received a copy of the GNU Lesser General Public
 
-    License along with the GNU C Library; if not, write to the Free
 
-    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
-    02111-1307 USA.  */
 
- #include "api.h"
 
- #undef	__ptr_t
 
- #if defined __cplusplus || (defined __STDC__ && __STDC__)
 
- # define __ptr_t	void *
 
- #else /* Not C++ or ANSI C.  */
 
- # undef	const
 
- # define const
 
- # define __ptr_t	char *
 
- #endif /* C++ or ANSI C.  */
 
- # include <sysdeps/generic/memcopy.h>
 
- # include <host_endian.h>
 
- # if __BYTE_ORDER == __BIG_ENDIAN
 
- #  define WORDS_BIGENDIAN
 
- # endif
 
- #ifdef WORDS_BIGENDIAN
 
- # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
 
- #else
 
- # define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
 
- #endif
 
- /* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
 
- /* The strategy of this memcmp is:
 
-    1. Compare bytes until one of the block pointers is aligned.
 
-    2. Compare using memcmp_common_alignment or
 
-       memcmp_not_common_alignment, regarding the alignment of the other
 
-       block after the initial byte operations.  The maximum number of
 
-       full words (of type op_t) are compared in this way.
 
-    3. Compare the few remaining bytes.  */
 
- #ifndef WORDS_BIGENDIAN
 
- /* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine.
 
-    A and B are known to be different.
 
-    This is needed only on little-endian machines.  */
 
- static int memcmp_bytes (op_t a, op_t b)
 
- {
 
-     long int srcp1 = (long int) &a;
 
-     long int srcp2 = (long int) &b;
 
-     op_t a0, b0;
 
-     do {
 
-         a0 = ((byte *) srcp1)[0];
 
-         b0 = ((byte *) srcp2)[0];
 
-         srcp1 += 1;
 
-         srcp2 += 1;
 
-     } while (a0 == b0);
 
-     return a0 - b0;
 
- }
 
- #endif
 
- /* (memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
 
-    objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
 
-    memory operations on `op_t's.  */
 
- static int memcmp_common_alignment (long srcp1, long srcp2, int len)
 
- {
 
-     op_t a0, a1;
 
-     op_t b0, b1;
 
-     switch (len % 4) {
 
-         default: /* Avoid warning about uninitialized local variables.  */
 
-         case 2:
 
-             a0 = ((op_t *) srcp1)[0];
 
-             b0 = ((op_t *) srcp2)[0];
 
-             srcp1 -= 2 * OPSIZ;
 
-             srcp2 -= 2 * OPSIZ;
 
-             len += 2;
 
-             goto do1;
 
-         case 3:
 
-             a1 = ((op_t *) srcp1)[0];
 
-             b1 = ((op_t *) srcp2)[0];
 
-             srcp1 -= OPSIZ;
 
-             srcp2 -= OPSIZ;
 
-             len += 1;
 
-             goto do2;
 
-         case 0:
 
-             if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
-                 return 0;
 
-             a0 = ((op_t *) srcp1)[0];
 
-             b0 = ((op_t *) srcp2)[0];
 
-             goto do3;
 
-         case 1:
 
-             a1 = ((op_t *) srcp1)[0];
 
-             b1 = ((op_t *) srcp2)[0];
 
-             srcp1 += OPSIZ;
 
-             srcp2 += OPSIZ;
 
-             len -= 1;
 
-             if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
-                 goto do0;
 
-             /* Fall through.  */
 
-     }
 
-     do {
 
-         a0 = ((op_t *) srcp1)[0];
 
-         b0 = ((op_t *) srcp2)[0];
 
-         if (a1 != b1)
 
-             return CMP_LT_OR_GT (a1, b1);
 
- do3:
 
-         a1 = ((op_t *) srcp1)[1];
 
-         b1 = ((op_t *) srcp2)[1];
 
-         if (a0 != b0)
 
-             return CMP_LT_OR_GT (a0, b0);
 
- do2:
 
-         a0 = ((op_t *) srcp1)[2];
 
-         b0 = ((op_t *) srcp2)[2];
 
-         if (a1 != b1)
 
-             return CMP_LT_OR_GT (a1, b1);
 
- do1:
 
-         a1 = ((op_t *) srcp1)[3];
 
-         b1 = ((op_t *) srcp2)[3];
 
-         if (a0 != b0)
 
-             return CMP_LT_OR_GT (a0, b0);
 
-         srcp1 += 4 * OPSIZ;
 
-         srcp2 += 4 * OPSIZ;
 
-         len -= 4;
 
-     } while (len != 0);
 
-     /* This is the right position for do0.  Please don't move
 
-        it into the loop.  */
 
- do0:
 
-     if (a1 != b1)
 
-         return CMP_LT_OR_GT (a1, b1);
 
-     return 0;
 
- }
 
- /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
 
-    `op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
 
-    operations on `op_t', but SRCP1 *should be unaligned*.  */
 
- static int memcmp_not_common_alignment (long srcp1, long srcp2, int len)
 
- {
 
-     op_t a0, a1, a2, a3;
 
-     op_t b0, b1, b2, b3;
 
-     op_t x;
 
-     int shl, shr;
 
-     /* Calculate how to shift a word read at the memory operation
 
-        aligned srcp1 to make it aligned for comparison.  */
 
-     shl = 8 * (srcp1 % OPSIZ);
 
-     shr = 8 * OPSIZ - shl;
 
-     /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
 
-        it points in the middle of.  */
 
-     srcp1 &= -OPSIZ;
 
-     switch (len % 4) {
 
-         default: /* Avoid warning about uninitialized local variables.  */
 
-         case 2:
 
-             a1 = ((op_t *) srcp1)[0];
 
-             a2 = ((op_t *) srcp1)[1];
 
-             b2 = ((op_t *) srcp2)[0];
 
-             srcp1 -= 1 * OPSIZ;
 
-             srcp2 -= 2 * OPSIZ;
 
-             len += 2;
 
-             goto do1;
 
-         case 3:
 
-             a0 = ((op_t *) srcp1)[0];
 
-             a1 = ((op_t *) srcp1)[1];
 
-             b1 = ((op_t *) srcp2)[0];
 
-             srcp2 -= 1 * OPSIZ;
 
-             len += 1;
 
-             goto do2;
 
-         case 0:
 
-             if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
-                 return 0;
 
-             a3 = ((op_t *) srcp1)[0];
 
-             a0 = ((op_t *) srcp1)[1];
 
-             b0 = ((op_t *) srcp2)[0];
 
-             srcp1 += 1 * OPSIZ;
 
-             goto do3;
 
-         case 1:
 
-             a2 = ((op_t *) srcp1)[0];
 
-             a3 = ((op_t *) srcp1)[1];
 
-             b3 = ((op_t *) srcp2)[0];
 
-             srcp1 += 2 * OPSIZ;
 
-             srcp2 += 1 * OPSIZ;
 
-             len -= 1;
 
-             if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 
-                 goto do0;
 
-             /* Fall through.  */
 
-     }
 
-     do {
 
-         a0 = ((op_t *) srcp1)[0];
 
-         b0 = ((op_t *) srcp2)[0];
 
-         x = MERGE(a2, shl, a3, shr);
 
-         if (x != b3)
 
-             return CMP_LT_OR_GT (x, b3);
 
- do3:
 
-         a1 = ((op_t *) srcp1)[1];
 
-         b1 = ((op_t *) srcp2)[1];
 
-         x = MERGE(a3, shl, a0, shr);
 
-         if (x != b0)
 
-             return CMP_LT_OR_GT (x, b0);
 
- do2:
 
-         a2 = ((op_t *) srcp1)[2];
 
-         b2 = ((op_t *) srcp2)[2];
 
-         x = MERGE(a0, shl, a1, shr);
 
-         if (x != b1)
 
-             return CMP_LT_OR_GT (x, b1);
 
- do1:
 
-         a3 = ((op_t *) srcp1)[3];
 
-         b3 = ((op_t *) srcp2)[3];
 
-         x = MERGE(a1, shl, a2, shr);
 
-         if (x != b2)
 
-             return CMP_LT_OR_GT (x, b2);
 
-         srcp1 += 4 * OPSIZ;
 
-         srcp2 += 4 * OPSIZ;
 
-         len -= 4;
 
-     } while (len != 0);
 
-     /* This is the right position for do0.  Please don't move
 
-        it into the loop.  */
 
- do0:
 
-     x = MERGE(a2, shl, a3, shr);
 
-     if (x != b3)
 
-         return CMP_LT_OR_GT (x, b3);
 
-     return 0;
 
- }
 
- int memcmp (const __ptr_t s1, const __ptr_t s2, size_t len)
 
- {
 
-     op_t a0, b0, res;
 
-     long int srcp1 = (long int) s1;
 
-     long int srcp2 = (long int) s2;
 
-     if (len >= OP_T_THRES) {
 
-         /* There are at least some bytes to compare.  No need to test
 
-            for LEN == 0 in this alignment loop.  */
 
-         while (srcp2 % OPSIZ != 0) {
 
-             a0 = ((byte *) srcp1)[0];
 
-             b0 = ((byte *) srcp2)[0];
 
-             srcp1 += 1;
 
-             srcp2 += 1;
 
-             res = a0 - b0;
 
-             if (res != 0)
 
-                 return res;
 
-             len -= 1;
 
-         }
 
-         /* SRCP2 is now aligned for memory operations on `op_t'.
 
-            SRCP1 alignment determines if we can do a simple,
 
-            aligned compare or need to shuffle bits.  */
 
-         res = (srcp1 % OPSIZ == 0) ?
 
-               memcmp_common_alignment (srcp1, srcp2, len / OPSIZ) :
 
-               memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
 
-         if (res != 0)
 
-             return res;
 
-         /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
 
-         srcp1 += len & -OPSIZ;
 
-         srcp2 += len & -OPSIZ;
 
-         len %= OPSIZ;
 
-     }
 
-     /* There are just a few bytes to compare.  Use byte memory operations.  */
 
-     while (len != 0) {
 
-         a0 = ((byte *) srcp1)[0];
 
-         b0 = ((byte *) srcp2)[0];
 
-         srcp1 += 1;
 
-         srcp2 += 1;
 
-         res = a0 - b0;
 
-         if (res != 0)
 
-             return res;
 
-         len -= 1;
 
-     }
 
-     return 0;
 
- }
 
 
  |