home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / sysdeps / m68k / memcmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-24  |  6.8 KB  |  298 lines

  1. /* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
  2.    Contributed by Torbjorn Granlund (tege@sics.se).
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <string.h>
  21.  
  22. #include <memcopy.h>
  23.  
  24. #ifdef isbcmp
  25. #define memcmp  bcmp
  26. #define size_t  int
  27. #endif
  28.  
  29. /* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
  30.  
  31. /* The strategy of this memcmp is:
  32.  
  33.    1. Compare bytes until one of the block pointers is aligned.
  34.  
  35.    2. Compare using memcmp_common_alignment or
  36.       memcmp_not_common_alignment, regarding the alignment of the other
  37.       block after the initial byte operations.  The maximum number of
  38.       full words (of type op_t) are compared in this way.
  39.  
  40.    3. Compare the few remaining bytes.  */
  41.  
  42. /* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
  43.    objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
  44.    memory operations on `op_t's.  */
  45. #ifdef    __GNUC__
  46. __inline
  47. #endif
  48. static int
  49. memcmp_common_alignment (srcp1, srcp2, len)
  50.      long int srcp1;
  51.      long int srcp2;
  52.      size_t len;
  53. {
  54.   op_t a0, a1;
  55.   op_t b0, b1;
  56.   op_t res;
  57.  
  58.   switch (len % 4)
  59.     {
  60.     case 2:
  61.       a0 = ((op_t *) srcp1)[0];
  62.       b0 = ((op_t *) srcp2)[0];
  63.       srcp1 -= 2 * OPSIZ;
  64.       srcp2 -= 2 * OPSIZ;
  65.       len += 2;
  66.       goto do1;
  67.     case 3:
  68.       a1 = ((op_t *) srcp1)[0];
  69.       b1 = ((op_t *) srcp2)[0];
  70.       srcp1 -= OPSIZ;
  71.       srcp2 -= OPSIZ;
  72.       len += 1;
  73.       goto do2;
  74.     case 0:
  75.       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
  76.     return 0;
  77.       a0 = ((op_t *) srcp1)[0];
  78.       b0 = ((op_t *) srcp2)[0];
  79.       goto do3;
  80.     case 1:
  81.       a1 = ((op_t *) srcp1)[0];
  82.       b1 = ((op_t *) srcp2)[0];
  83.       srcp1 += OPSIZ;
  84.       srcp2 += OPSIZ;
  85.       len -= 1;
  86.       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
  87.     goto do0;
  88.       /* Fall through.  */
  89.     }
  90.  
  91.   do
  92.     {
  93.       a0 = ((op_t *) srcp1)[0];
  94.       b0 = ((op_t *) srcp2)[0];
  95.       res = a1 - b1;
  96.       if (res != 0)
  97.     return res;
  98.     do3:
  99.       a1 = ((op_t *) srcp1)[1];
  100.       b1 = ((op_t *) srcp2)[1];
  101.       res = a0 - b0;
  102.       if (res != 0)
  103.     return res;
  104.     do2:
  105.       a0 = ((op_t *) srcp1)[2];
  106.       b0 = ((op_t *) srcp2)[2];
  107.       res = a1 - b1;
  108.       if (res != 0)
  109.     return res;
  110.     do1:
  111.       a1 = ((op_t *) srcp1)[3];
  112.       b1 = ((op_t *) srcp2)[3];
  113.       res = a0 - b0;
  114.       if (res != 0)
  115.     return res;
  116.  
  117.       srcp1 += 4 * OPSIZ;
  118.       srcp2 += 4 * OPSIZ;
  119.       len -= 4;
  120.     }
  121.   while (len != 0);
  122.  
  123.   /* This is the right position for do0.  Please don't move
  124.      it into the loop.  */
  125.  do0:
  126.   return a1 - b1;
  127. }
  128.  
  129.  
  130. /* SRCP2 should be aligned for memory operations on `op_t',
  131.    but SRCP1 *should be unaligned*.  */
  132.  
  133. #ifdef    __GNUC__
  134. __inline
  135. #endif
  136. static int
  137. memcmp_not_common_alignment (srcp1, srcp2, len)
  138.      long int srcp1;
  139.      long int srcp2;
  140.      size_t len;
  141. {
  142.   op_t a0, a1, a2, a3;
  143.   op_t b0, b1, b2, b3;
  144.   op_t res;
  145.   op_t x;
  146.   int shl, shr;
  147.  
  148.   /* Calculate how to shift a word read at the memory operation
  149.      aligned srcp1 to make it aligned for comparison.  */
  150.  
  151.   shl = 8 * (srcp1 % OPSIZ);
  152.   shr = 8 * OPSIZ - shl;
  153.  
  154.   /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
  155.      it points in the middle of.  */
  156.   srcp1 &= -OPSIZ;
  157.  
  158.   switch (len % 4)
  159.     {
  160.     case 2:
  161.       a1 = ((op_t *) srcp1)[0];
  162.       a2 = ((op_t *) srcp1)[1];
  163.       b2 = ((op_t *) srcp2)[0];
  164.       srcp1 -= 1 * OPSIZ;
  165.       srcp2 -= 2 * OPSIZ;
  166.       len += 2;
  167.       goto do1;
  168.     case 3:
  169.       a0 = ((op_t *) srcp1)[0];
  170.       a1 = ((op_t *) srcp1)[1];
  171.       b1 = ((op_t *) srcp2)[0];
  172.       srcp2 -= 1 * OPSIZ;
  173.       len += 1;
  174.       goto do2;
  175.     case 0:
  176.       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
  177.     return 0;
  178.       a3 = ((op_t *) srcp1)[0];
  179.       a0 = ((op_t *) srcp1)[1];
  180.       b0 = ((op_t *) srcp2)[0];
  181.       srcp1 += 1 * OPSIZ;
  182.       goto do3;
  183.     case 1:
  184.       a2 = ((op_t *) srcp1)[0];
  185.       a3 = ((op_t *) srcp1)[1];
  186.       b3 = ((op_t *) srcp2)[0];
  187.       srcp1 += 2 * OPSIZ;
  188.       srcp2 += 1 * OPSIZ;
  189.       len -= 1;
  190.       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
  191.     goto do0;
  192.       /* Fall through.  */
  193.     }
  194.  
  195.   do
  196.     {
  197.       a0 = ((op_t *) srcp1)[0];
  198.       b0 = ((op_t *) srcp2)[0];
  199.       x = MERGE(a2, shl, a3, shr);
  200.       res = x - b3;
  201.       if (res != 0)
  202.     return res;
  203.     do3:
  204.       a1 = ((op_t *) srcp1)[1];
  205.       b1 = ((op_t *) srcp2)[1];
  206.       x = MERGE(a3, shl, a0, shr);
  207.       res = x - b0;
  208.       if (res != 0)
  209.     return res;
  210.     do2:
  211.       a2 = ((op_t *) srcp1)[2];
  212.       b2 = ((op_t *) srcp2)[2];
  213.       x = MERGE(a0, shl, a1, shr);
  214.       res = x - b1;
  215.       if (res != 0)
  216.     return res;
  217.     do1:
  218.       a3 = ((op_t *) srcp1)[3];
  219.       b3 = ((op_t *) srcp2)[3];
  220.       x = MERGE(a1, shl, a2, shr);
  221.       res = x - b2;
  222.       if (res != 0)
  223.     return res;
  224.  
  225.       srcp1 += 4 * OPSIZ;
  226.       srcp2 += 4 * OPSIZ;
  227.       len -= 4;
  228.     }
  229.   while (len != 0);
  230.  
  231.   /* This is the right position for do0.  Please don't move
  232.      it into the loop.  */
  233.  do0:
  234.   x = MERGE(a2, shl, a3, shr);
  235.   return x - b3;
  236. }
  237.  
  238. int
  239. memcmp (s1, s2, len)
  240.      const __ptr_t s1;
  241.      const __ptr_t s2;
  242.      size_t len;
  243. {
  244.   op_t a0;
  245.   op_t b0;
  246.   long int srcp1 = (long int) s1;
  247.   long int srcp2 = (long int) s2;
  248.   op_t res;
  249.  
  250.   if (len >= OP_T_THRES)
  251.     {
  252.       /* There are at least some bytes to compare.  No need to test
  253.      for LEN == 0 in this alignment loop.  */
  254.       while (srcp2 % OPSIZ != 0)
  255.     {
  256.       a0 = ((byte *) srcp1)[0];
  257.       b0 = ((byte *) srcp2)[0];
  258.       srcp1 += 1;
  259.       srcp2 += 1;
  260.       res = a0 - b0;
  261.       if (res != 0)
  262.         return res;
  263.       len -= 1;
  264.     }
  265.  
  266.       /* SRCP2 is now aligned for memory operations on `op_t'.
  267.      SRCP1 alignment determines if we can do a simple,
  268.      aligned compare or need to shuffle bits.  */
  269.  
  270.       if (srcp1 % OPSIZ == 0)
  271.     res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
  272.       else
  273.     res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
  274.       if (res != 0)
  275.     return res;
  276.  
  277.       /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
  278.       srcp1 += len & -OPSIZ;
  279.       srcp2 += len & -OPSIZ;
  280.       len %= OPSIZ;
  281.     }
  282.  
  283.   /* There are just a few bytes to compare.  Use byte memory operations.  */
  284.   while (len != 0)
  285.     {
  286.       a0 = ((byte *) srcp1)[0];
  287.       b0 = ((byte *) srcp2)[0];
  288.       srcp1 += 1;
  289.       srcp2 += 1;
  290.       res = a0 - b0;
  291.       if (res != 0)
  292.     return res;
  293.       len -= 1;
  294.     }
  295.  
  296.   return 0;
  297. }
  298.