linux/arch/blackfin/lib/memcmp.S
<<
>>
Prefs
   1/*
   2 * File:         arch/blackfin/lib/memcmp.S
   3 * Based on:
   4 * Author:
   5 *
   6 * Created:
   7 * Description:
   8 *
   9 * Modified:
  10 *               Copyright 2004-2006 Analog Devices Inc.
  11 *
  12 * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License as published by
  16 * the Free Software Foundation; either version 2 of the License, or
  17 * (at your option) any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, see the file COPYING, or write
  26 * to the Free Software Foundation, Inc.,
  27 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  28 */
  29
  30#include <linux/linkage.h>
  31
  32/* int memcmp(const void *s1, const void *s2, size_t n);
  33 * R0 = First Address (s1)
  34 * R1 = Second Address (s2)
  35 * R2 = count (n)
  36 *
  37 * Favours word aligned data.
  38 */
  39
  40.text
  41
  42.align 2
  43
  44ENTRY(_memcmp)
  45        I1 = P3;
  46        P0 = R0;                        /* P0 = s1 address */
  47        P3 = R1;                        /* P3 = s2 Address  */
  48        P2 = R2 ;                       /* P2 = count */
  49        CC = R2 <= 7(IU);
  50        IF CC JUMP .Ltoo_small;
  51        I0 = R1;                        /* s2 */
  52        R1 = R1 | R0;           /* OR addresses together */
  53        R1 <<= 30;              /* check bottom two bits */
  54        CC =  AZ;                       /* AZ set if zero. */
  55        IF !CC JUMP .Lbytes ;   /* Jump if addrs not aligned. */
  56
  57        P1 = P2 >> 2;           /* count = n/4 */
  58        R3 =  3;
  59        R2 = R2 & R3;           /* remainder */
  60        P2 = R2;                        /* set remainder */
  61
  62        LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1;
  63.Lquad_loop_s:
  64#if ANOMALY_05000202
  65        R0 = [P0++];
  66        R1 = [I0++];
  67#else
  68        MNOP || R0 = [P0++] || R1 = [I0++];
  69#endif
  70        CC = R0 == R1;
  71        IF !CC JUMP .Lquad_different;
  72.Lquad_loop_e:
  73        NOP;
  74
  75        P3 = I0;                        /* s2 */
  76.Ltoo_small:
  77        CC = P2 == 0;           /* Check zero count*/
  78        IF CC JUMP .Lfinished;  /* very unlikely*/
  79
  80.Lbytes:
  81        LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2;
  82.Lbyte_loop_s:
  83        R1 = B[P3++](Z);        /* *s2 */
  84        R0 = B[P0++](Z);        /* *s1 */
  85        CC = R0 == R1;
  86        IF !CC JUMP .Ldifferent;
  87.Lbyte_loop_e:
  88        NOP;
  89
  90.Ldifferent:
  91        R0 = R0 - R1;
  92        P3 = I1;
  93        RTS;
  94
  95.Lquad_different:
  96        /* We've read two quads which don't match.
  97         * Can't just compare them, because we're
  98         * a little-endian machine, so the MSBs of
  99         * the regs occur at later addresses in the
 100         * string.
 101         * Arrange to re-read those two quads again,
 102         * byte-by-byte.
 103         */
 104        P0 += -4;               /* back up to the start of the */
 105        P3 = I0;                /* quads, and increase the*/
 106        P2 += 4;                /* remainder count*/
 107        P3 += -4;
 108        JUMP .Lbytes;
 109
 110.Lfinished:
 111        R0 = 0;
 112        P3 = I1;
 113        RTS;
 114
 115ENDPROC(_memcmp)
 116