OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [machine/] [arm/] [strlen.c] - Diff between revs 207 and 345

Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
/*
/*
 * Copyright (c) 2008 ARM Ltd
 * Copyright (c) 2008 ARM Ltd
 * All rights reserved.
 * All rights reserved.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
 * are met:
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the company may not be used to endorse or promote
 * 3. The name of the company may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    products derived from this software without specific prior written
 *    permission.
 *    permission.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
#include "arm_asm.h"
#include "arm_asm.h"
#include <_ansi.h>
#include <_ansi.h>
#include <string.h>
#include <string.h>
#include <limits.h>
#include <limits.h>
 
 
#if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
#if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
  (defined (__thumb__) && !defined (__thumb2__))
  (defined (__thumb__) && !defined (__thumb2__))
 
 
size_t
size_t
strlen (const char* str)
strlen (const char* str)
{
{
  int scratch;
  int scratch;
#if defined (__thumb__) && !defined (__thumb2__)
#if defined (__thumb__) && !defined (__thumb2__)
  size_t len;
  size_t len;
  asm ("mov     %0, #0\n"
  asm ("mov     %0, #0\n"
       "1:\n\t"
       "1:\n\t"
       "ldrb    %1, [%2, %0]\n\t"
       "ldrb    %1, [%2, %0]\n\t"
       "add     %0, %0, #1\n\t"
       "add     %0, %0, #1\n\t"
       "cmp     %1, #0\n\t"
       "cmp     %1, #0\n\t"
       "bne     1b"
       "bne     1b"
       : "=&r" (len), "=&r" (scratch) : "r" (str) : "memory", "cc");
       : "=&r" (len), "=&r" (scratch) : "r" (str) : "memory", "cc");
  return len - 1;
  return len - 1;
#else
#else
  const char* end;
  const char* end;
  asm ("1:\n\t"
  asm ("1:\n\t"
       "ldrb    %1, [%0], #1\n\t"
       "ldrb    %1, [%0], #1\n\t"
       "cmp     %1, #0\n\t"
       "cmp     %1, #0\n\t"
       "bne     1b"
       "bne     1b"
       : "=&r" (end), "=&r" (scratch) : "0" (str) : "memory", "cc");
       : "=&r" (end), "=&r" (scratch) : "0" (str) : "memory", "cc");
  return end - str - 1;
  return end - str - 1;
#endif
#endif
}
}
#else
#else
 
 
size_t __attribute__((naked))
size_t __attribute__((naked))
strlen (const char* str)
strlen (const char* str)
{
{
  asm ("len .req r0\n\t"
  asm ("len .req r0\n\t"
       "data .req r3\n\t"
       "data .req r3\n\t"
       "addr .req r1\n\t"
       "addr .req r1\n\t"
 
 
       "optpld r0\n\t"
       "optpld r0\n\t"
       /* Word-align address */
       /* Word-align address */
       "bic     addr, r0, #3\n\t"
       "bic     addr, r0, #3\n\t"
       /* Get adjustment for start ... */
       /* Get adjustment for start ... */
       "ands    len, r0, #3\n\t"
       "ands    len, r0, #3\n\t"
       "neg     len, len\n\t"
       "neg     len, len\n\t"
       /* First word of data */
       /* First word of data */
       "ldr     data, [addr], #4\n\t"
       "ldr     data, [addr], #4\n\t"
       /* Ensure bytes preceeding start ... */
       /* Ensure bytes preceeding start ... */
       "add     ip, len, #4\n\t"
       "add     ip, len, #4\n\t"
       "mov     ip, ip, asl #3\n\t"
       "mov     ip, ip, asl #3\n\t"
       "mvn     r2, #0\n\t"
       "mvn     r2, #0\n\t"
       /* ... are masked out */
       /* ... are masked out */
#ifdef __thumb__
#ifdef __thumb__
       "itt     ne\n\t"
       "itt     ne\n\t"
# ifdef __ARMEB__
# ifdef __ARMEB__
       "lslne   r2, ip\n\t"
       "lslne   r2, ip\n\t"
# else
# else
       "lsrne   r2, ip\n\t"
       "lsrne   r2, ip\n\t"
# endif
# endif
       "orrne   data, data, r2\n\t"
       "orrne   data, data, r2\n\t"
#else
#else
       "it      ne\n\t"
       "it      ne\n\t"
# ifdef __ARMEB__
# ifdef __ARMEB__
       "orrne   data, data, r2, lsl ip\n\t"
       "orrne   data, data, r2, lsl ip\n\t"
# else
# else
       "orrne   data, data, r2, lsr ip\n\t"
       "orrne   data, data, r2, lsr ip\n\t"
# endif
# endif
#endif
#endif
       /* Magic const 0x01010101 */
       /* Magic const 0x01010101 */
#ifdef _ISA_ARM_7
#ifdef _ISA_ARM_7
       "movw    ip, #0x101\n\t"
       "movw    ip, #0x101\n\t"
#else
#else
       "mov     ip, #0x1\n\t"
       "mov     ip, #0x1\n\t"
       "orr     ip, ip, ip, lsl #8\n\t"
       "orr     ip, ip, ip, lsl #8\n\t"
#endif
#endif
       "orr     ip, ip, ip, lsl #16\n"
       "orr     ip, ip, ip, lsl #16\n"
 
 
        /* This is the main loop.  We subtract one from each byte in
        /* This is the main loop.  We subtract one from each byte in
           the word: the sign bit changes iff the byte was zero or
           the word: the sign bit changes iff the byte was zero or
           0x80 -- we eliminate the latter case by anding the result
           0x80 -- we eliminate the latter case by anding the result
           with the 1-s complement of the data.  */
           with the 1-s complement of the data.  */
       "1:\n\t"
       "1:\n\t"
       /* test (data - 0x01010101)  */
       /* test (data - 0x01010101)  */
       "sub     r2, data, ip\n\t"
       "sub     r2, data, ip\n\t"
       /* ... & ~data */
       /* ... & ~data */
       "bic     r2, r2, data\n\t"
       "bic     r2, r2, data\n\t"
       /* ... & 0x80808080 == 0? */
       /* ... & 0x80808080 == 0? */
       "ands    r2, r2, ip, lsl #7\n\t"
       "ands    r2, r2, ip, lsl #7\n\t"
#ifdef _ISA_ARM_7
#ifdef _ISA_ARM_7
       /* yes, get more data... */
       /* yes, get more data... */
       "itt     eq\n\t"
       "itt     eq\n\t"
       "ldreq   data, [addr], #4\n\t"
       "ldreq   data, [addr], #4\n\t"
       /* and 4 more bytes  */
       /* and 4 more bytes  */
       "addeq   len, len, #4\n\t"
       "addeq   len, len, #4\n\t"
        /* If we have PLD, then unroll the loop a bit.  */
        /* If we have PLD, then unroll the loop a bit.  */
       "optpld addr, #8\n\t"
       "optpld addr, #8\n\t"
       /*  test (data - 0x01010101)  */
       /*  test (data - 0x01010101)  */
       "ittt    eq\n\t"
       "ittt    eq\n\t"
       "subeq   r2, data, ip\n\t"
       "subeq   r2, data, ip\n\t"
       /* ... & ~data */
       /* ... & ~data */
       "biceq   r2, r2, data\n\t"
       "biceq   r2, r2, data\n\t"
       /* ... & 0x80808080 == 0? */
       /* ... & 0x80808080 == 0? */
       "andeqs  r2, r2, ip, lsl #7\n\t"
       "andeqs  r2, r2, ip, lsl #7\n\t"
#endif
#endif
       "itt     eq\n\t"
       "itt     eq\n\t"
       /* yes, get more data... */
       /* yes, get more data... */
       "ldreq   data, [addr], #4\n\t"
       "ldreq   data, [addr], #4\n\t"
       /* and 4 more bytes  */
       /* and 4 more bytes  */
       "addeq   len, len, #4\n\t"
       "addeq   len, len, #4\n\t"
       "beq     1b\n\t"
       "beq     1b\n\t"
#ifdef __ARMEB__
#ifdef __ARMEB__
       "tst     data, #0xff000000\n\t"
       "tst     data, #0xff000000\n\t"
       "itttt   ne\n\t"
       "itttt   ne\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
       "tstne   data, #0xff0000\n\t"
       "tstne   data, #0xff0000\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
       "tstne   data, #0xff00\n\t"
       "tstne   data, #0xff00\n\t"
       "it      ne\n\t"
       "it      ne\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
#else
#else
# ifdef _ISA_ARM_5
# ifdef _ISA_ARM_5
        /* R2 is the residual sign bits from the above test.  All we
        /* R2 is the residual sign bits from the above test.  All we
        need to do now is establish the position of the first zero
        need to do now is establish the position of the first zero
        byte... */
        byte... */
        /* Little-endian is harder, we need the number of trailing
        /* Little-endian is harder, we need the number of trailing
        zeros / 8 */
        zeros / 8 */
#  ifdef _ISA_ARM_7
#  ifdef _ISA_ARM_7
       "rbit    r2, r2\n\t"
       "rbit    r2, r2\n\t"
       "clz     r2, r2\n\t"
       "clz     r2, r2\n\t"
#  else
#  else
       "rsb     r1, r2, #0\n\t"
       "rsb     r1, r2, #0\n\t"
       "and     r2, r2, r1\n\t"
       "and     r2, r2, r1\n\t"
       "clz     r2, r2\n\t"
       "clz     r2, r2\n\t"
       "rsb     r2, r2, #31\n\t"
       "rsb     r2, r2, #31\n\t"
#  endif
#  endif
       "add     len, len, r2, lsr #3\n\t"
       "add     len, len, r2, lsr #3\n\t"
# else  /* No CLZ instruction */
# else  /* No CLZ instruction */
       "tst     data, #0xff\n\t"
       "tst     data, #0xff\n\t"
       "itttt   ne\n\t"
       "itttt   ne\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
       "tstne   data, #0xff00\n\t"
       "tstne   data, #0xff00\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
       "tstne   data, #0xff0000\n\t"
       "tstne   data, #0xff0000\n\t"
       "it      ne\n\t"
       "it      ne\n\t"
       "addne   len, len, #1\n\t"
       "addne   len, len, #1\n\t"
# endif
# endif
#endif
#endif
       "RETURN");
       "RETURN");
}
}
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.