Change-Id: I2864dea04b3faf2d919165dcaa600af5b16c41c8 Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Raghu Gandham <raghu@mips.com>
		
			
				
	
	
		
			224 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2010 MIPS Technologies, Inc.
 | 
						|
 *
 | 
						|
 * All rights reserved.
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms, with or without
 | 
						|
 * modification, are permitted provided that the following conditions
 | 
						|
 * are met:
 | 
						|
 *
 | 
						|
 *      * Redistributions of source code must retain the above copyright
 | 
						|
 *        notice, this list of conditions and the following disclaimer.
 | 
						|
 *      * Redistributions in binary form must reproduce the above copyright
 | 
						|
 *        notice, this list of conditions and the following disclaimer
 | 
						|
 *        in the documentation and/or other materials provided with
 | 
						|
 *        the distribution.
 | 
						|
 *      * Neither the name of MIPS Technologies Inc. nor the names of its
 | 
						|
 *        contributors may be used to endorse or promote products derived
 | 
						|
 *        from this software without specific prior written permission.
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
						|
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
						|
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
						|
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
						|
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
						|
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
						|
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
						|
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
						|
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
						|
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
 */
 | 
						|
 | 
						|
#include "mips-string-ops.h"
 | 
						|
 | 
						|
#define do_strlen_word(__av) {\
 | 
						|
    if (detect_zero(x,x,_01s,_80s)) break;\
 | 
						|
    x = __av;\
 | 
						|
    cnt += sizeof (unsigned);\
 | 
						|
    }
 | 
						|
 | 
						|
#define do_strlen_byte(__x) {\
 | 
						|
  if ((bx.b.B##__x) == 0) break;\
 | 
						|
  ++cnt;\
 | 
						|
  }
 | 
						|
 | 
						|
#if SMOKE_TEST_MIPS_STRLEN
 | 
						|
#define strlen my_strlen
 | 
						|
#endif
 | 
						|
 | 
						|
int
 | 
						|
strlen (const void *_a)
 | 
						|
{
 | 
						|
  int cnt = 0;
 | 
						|
  unsigned x;
 | 
						|
 | 
						|
  /* align the string to word boundary so we can do word at a time.  */
 | 
						|
  if ((cvt_ptr_to (unsigned, _a) & (sizeof (unsigned) - 1)) != 0)
 | 
						|
    {
 | 
						|
      if ((cvt_ptr_to (unsigned, _a) & 1) != 0)
 | 
						|
	{
 | 
						|
	  if (get_byte (_a, 0) == 0)
 | 
						|
	    return cnt;
 | 
						|
	  /* set bit 1 so 2-bytes are checked and incremented. */
 | 
						|
	  inc_ptr_as (char *, _a, 1);
 | 
						|
	  ++cnt;
 | 
						|
	}
 | 
						|
      if ((cvt_ptr_to (unsigned, _a) & 2) != 0)
 | 
						|
	{
 | 
						|
	  if (get_byte (_a, 0) == 0)
 | 
						|
	    return cnt + 0;
 | 
						|
	  if (get_byte (_a, 1) == 0)
 | 
						|
	    return cnt + 1;
 | 
						|
	  inc_ptr_as (char *, _a, 2);
 | 
						|
	  cnt += 2;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
#if __mips64
 | 
						|
#error strlen: mips64 check for 4-byte alignment not implemented.
 | 
						|
#endif
 | 
						|
 | 
						|
  if (1)
 | 
						|
    {
 | 
						|
      def_and_set_01 (_01s);
 | 
						|
      def_and_set_80 (_80s);
 | 
						|
 | 
						|
      /* as advantagous as it is to performance, this code cannot pre-load
 | 
						|
         the following word, nor can it prefetch the next line at the start
 | 
						|
         of the loop since the string can be at the end of a page with the
 | 
						|
         following page unmapped. There are tests in the suite to catch
 | 
						|
         any attempt to go beyond the current word. */
 | 
						|
      x = get_word (_a, 0);
 | 
						|
      while (1)
 | 
						|
	{
 | 
						|
	  /* doing 8 words should cover most strings.  */
 | 
						|
	  do_strlen_word (get_word (_a, 1));
 | 
						|
	  do_strlen_word (get_word (_a, 2));
 | 
						|
	  do_strlen_word (get_word (_a, 3));
 | 
						|
	  do_strlen_word (get_word (_a, 4));
 | 
						|
	  do_strlen_word (get_word (_a, 5));
 | 
						|
	  do_strlen_word (get_word (_a, 6));
 | 
						|
	  do_strlen_word (get_word (_a, 7));
 | 
						|
	  do_strlen_word (get_word (_a, 8));
 | 
						|
	  inc_ptr_as (unsigned *, _a, 8);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  while (1)
 | 
						|
    {
 | 
						|
      /* pull apart the last word processed and find the zero.  */
 | 
						|
      bitfields_t bx;
 | 
						|
      bx.v = x;
 | 
						|
#if __mips64
 | 
						|
      do_strlen_byte (0);
 | 
						|
      do_strlen_byte (1);
 | 
						|
      do_strlen_byte (2);
 | 
						|
      do_strlen_byte (3);
 | 
						|
      do_strlen_byte (4);
 | 
						|
      do_strlen_byte (5);
 | 
						|
      do_strlen_byte (6);
 | 
						|
#else
 | 
						|
      do_strlen_byte (0);
 | 
						|
      do_strlen_byte (1);
 | 
						|
      do_strlen_byte (2);
 | 
						|
#endif
 | 
						|
      /* last byte is zero */
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return cnt;
 | 
						|
}
 | 
						|
 | 
						|
#undef do_strlen_byte
 | 
						|
#undef do_strlen_word
 | 
						|
 | 
						|
#if SMOKE_TEST_MIPS_STRLEN
 | 
						|
#include <stdio.h>
 | 
						|
char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
 | 
						|
char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
 | 
						|
 | 
						|
char str3[] = "another string";
 | 
						|
char str4[] = "another";
 | 
						|
 | 
						|
char str5[] = "somes tring";
 | 
						|
char str6[] = "somes_tring";
 | 
						|
 | 
						|
char str7[16], str8[16];
 | 
						|
 | 
						|
static char *
 | 
						|
chk (unsigned mine, unsigned libs, int *errors)
 | 
						|
{
 | 
						|
  static char answer[1024];
 | 
						|
  char *result = mine == libs ? "PASS" : "FAIL";
 | 
						|
  sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result);
 | 
						|
  if (mine != libs)
 | 
						|
    (*errors)++;
 | 
						|
  return answer;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
main (int argc, char **argv)
 | 
						|
{
 | 
						|
  int errors = 0;
 | 
						|
  /* set -1 in one position */
 | 
						|
  str6[5] = 0xff;
 | 
						|
  /* set zero in same position with junk in following 3 */
 | 
						|
  str7[0] = str8[0] = 0;
 | 
						|
  str7[1] = 0xff;
 | 
						|
  str7[2] = 'a';
 | 
						|
  str7[3] = 2;
 | 
						|
  str8[1] = 's';
 | 
						|
  str8[2] = -2;
 | 
						|
  str8[3] = 0;
 | 
						|
 | 
						|
  fprintf (stderr, "========== mips_strlen%s test...\n",
 | 
						|
	   argv[0] ? argv[0] : "unknown strlen");
 | 
						|
#define P(__x,__y) {\
 | 
						|
    int a = my_strlen(__x + __y);\
 | 
						|
    int b = (strlen)(__x + __y) /* library version */;\
 | 
						|
    fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\
 | 
						|
    }
 | 
						|
 | 
						|
  P (str1, 0);
 | 
						|
  P (str1, 1);
 | 
						|
  P (str1, 2);
 | 
						|
  P (str1, 3);
 | 
						|
 | 
						|
  P (str2, 0);
 | 
						|
  P (str2, 1);
 | 
						|
  P (str2, 2);
 | 
						|
  P (str2, 3);
 | 
						|
 | 
						|
  P (str3, 0);
 | 
						|
  P (str3, 1);
 | 
						|
  P (str3, 2);
 | 
						|
  P (str3, 3);
 | 
						|
 | 
						|
  P (str4, 0);
 | 
						|
  P (str4, 1);
 | 
						|
  P (str4, 2);
 | 
						|
  P (str4, 3);
 | 
						|
 | 
						|
  P (str5, 0);
 | 
						|
  P (str5, 1);
 | 
						|
  P (str5, 2);
 | 
						|
  P (str5, 3);
 | 
						|
 | 
						|
  P (str6, 0);
 | 
						|
  P (str6, 1);
 | 
						|
  P (str6, 2);
 | 
						|
  P (str6, 3);
 | 
						|
 | 
						|
  P (str7, 0);
 | 
						|
  P (str7, 1);
 | 
						|
  P (str7, 2);
 | 
						|
  P (str7, 3);
 | 
						|
 | 
						|
  P (str8, 0);
 | 
						|
  P (str8, 1);
 | 
						|
  P (str8, 2);
 | 
						|
  P (str8, 3);
 | 
						|
 | 
						|
  return errors;
 | 
						|
}
 | 
						|
#endif
 |