string-avr.h


/* 
   This file is part of the AVR C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

/*
 *	ISO C Standard: 4.11 STRING HANDLING	<string.h>
 */

#ifndef	__STRING_AVR_H_

#define	__STRING_AVR_H_ 1

/* Get size_t and NULL from <stddef.h>.  */
#define	__need_size_t
#define	__need_NULL
#include <stddef.h>

#define __ptr_t void *
#if 0
typedef void * __ptr_t;
#endif
#define __const const
#define __string_h_int__ char

/* Copy N bytes of SRC to DEST.  */
extern inline __ptr_t memcpy(__ptr_t __to, const void *__from, size_t __n)
{
  register void *__dummy1, *__dummy2, *__dummy3;
  if (__n)
  __asm__ __volatile__ (
			"L_hi%=:\t"
			"ld __tmp_reg__,%a0+\n\t"
			"st %a1+,__tmp_reg__\n\t"
			"sbiw %2,1\n\t"
			"brne L_hi%=\n"
			: "=&e" (__dummy1), "=&e" (__dummy2), "=&w" (__dummy3)
			: "0" (__from),"1" (__to),"2" (__n)
			: "memory");
  return (__to);
}
/* Copy N bytes of SRC to DEST, guaranteeing
   correct behavior for overlapping strings.  */
extern __ptr_t memmove (__ptr_t __dest, const void * __src,
			     size_t __n);

/* Copy no more than N bytes of SRC to DEST, stopping when C is found.
   Return the position in DEST one byte past where C was copied,
   or NULL if C was not found in the first N bytes of SRC.  */

/* Set N bytes of S to C.  */

extern inline __ptr_t
memset (__ptr_t __s, int __c, size_t __n)
{
  register void *__dummy1;
  register size_t __dummy2;
  if (__n)
    __asm__ __volatile__ ("mov __tmp_reg__, %2\n" /* Wrong. But needed for
						     disable errors if
						     constraints register
						     "r" equal "=&w"
						  */
							 
			  "L_hi%=:\t"
			  "st %a0+,__tmp_reg__\n\t"
			  "sbiw %1,1\n\t"
			  "brne L_hi%="
			  : "=&e" (__dummy1), "=&w" (__dummy2)
			  : "r" ((char)__c), "0" (__s), "1" (__n));
  return __s;
}

/* Compare N bytes of S1 and S2.  */
extern inline int
memcmp (__const void *__s1, __const void *__s2, size_t __n)
{
  register void *__dummy1, *__dummy2;
  register size_t __dummy3;
  register char __res;
  if (__n)
    __asm__ __volatile__ ("cmp_loop%=:\t"
			  "ld __tmp_reg__,%a2+\n\t"
			  "ld %0,%a1+\n\t"
			  "sub %0,__tmp_reg__\n\t"
			  "brne cmp_out%=\n\t"
			  "sbiw %3,1\n\t"
			  "brne cmp_loop%=\n"
			  "cmp_out%=:\tbrcc cmp_end%=\n\t"
			  "ldi %0,0xff\n"
			  "cmp_end%=:\n"
			  : "=d"(__res), "=e"(__dummy1),"=e"(__dummy2),"=w"(__dummy3)
			  : "1" (__s1), "2" (__s2), "3" (__n));
  return __res;
}

/* Search N bytes of S for C.  */
extern inline __ptr_t
memchr (__const void *__s, char __c, size_t __n)
{
  if (!__n)
    return NULL;
#if 0
  do
    {
      if (*(char*)__s == __c)
	return (__ptr_t)__s;
      ++(char*)__s;
    }
  while (--__n);
#else
  {
    __ptr_t __ret;
    size_t __dummy;
    __asm__ __volatile__ ("L_ho%=:\t"
			  "ld __tmp_reg__,%a0+\n\t"
			  "cp __tmp_reg__,%2\n\t"
			  "breq L_hi%=\n\t"
			  "sbiw %1,1\n\t"
			  "brne L_ho%=\n\t"
			  "ldi %A0,1\n\t"
			  "ldi %B0,0\n"
			  "L_hi%=:\t"
			  "sbiw %0,1"
			  : "=&e" (__ret), "=&w" (__dummy)
			  : "r" (__c), "0" (__s), "1" (__n));
    return __ret;
  }
#endif
}


/* Return the length of S.  */
extern inline size_t
strlen (__const char *__s)
{
  char *__tmp;
  __asm__ __volatile__ ("L_hi%=:\t"
		"ld __tmp_reg__,%a0+\n\t"
		"tst __tmp_reg__\n\t"
		"brne L_hi%="
		: "=e" (__tmp)
		: "0" (__s));
  return (--__tmp) - __s;
}

/* Copy SRC to DEST.  */
extern inline char *
strcpy (char *__dest, __const char *__src)
{
  register void *__dummy1, *__dummy2;
  __asm__ __volatile__ ("L_ho%=:\t"
			"ld __tmp_reg__,%a1+\n\t"
			"st %a0+,__tmp_reg__\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_ho%="
			: "=e" (__dummy1), "=e" (__dummy2)
			: "0" (__dest), "1" (__src)
			);
  return __dest;
}

/* Copy no more than N characters of SRC to DEST.  */
extern inline char *
strncpy (char *__dest, __const char *__src, size_t __n)
{
  register void *__dummy1, *__dummy2;
  register size_t __dummy3;
  if (__n)
    __asm__ __volatile__ ("L_ho%=:\t"
			  "ld __tmp_reg__,%a1+\n\t"
			  "st %a0+,__tmp_reg__\n\t"
			  "sbiw %2,1\n\t"
			  "breq L_hi%=\n\t"
			  "tst __tmp_reg__\n\t"
			  "brne L_ho%=\n"
			  "L_hi%=:"
			  : "=e" (__dummy1), "=e" (__dummy2), "=w" (__dummy3)
			  : "2" (__n), "0" (__dest), "1" (__src)
			  );
  return __dest;
}

/* Append SRC onto DEST.  */
extern inline char *
strcat (char *__dest, __const char *__src)
{
  register void *__dummy1, *__dummy2;
  __asm__ __volatile__ ("L_hi%=:\t"
			"ld __tmp_reg__,%a1+\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_hi%=\n\t"
			"sbiw %1,1\n"
			"L_ho%=:\t"
			"ld __tmp_reg__,%a0+\n\t"
			"st %a1+,__tmp_reg__\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_ho%="
			: "=e" (__dummy1), "=e" (__dummy2)
			: "1" (__dest), "0" (__src)
			);
  return __dest;
}

/* Append no more than N characters from SRC onto DEST.  */
extern inline char *
strncat (char *__dest, __const char *__src, size_t __n)
{
  register void *__dummy1, *__dummy2;
  register size_t __dummy3;
  __asm__ __volatile__ ("L_hi%=:\t"
			"ld __tmp_reg__,%a1+\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_hi%=\n\t"
			"sbiw %1,1\n"
			"L_ho%=:\t"
			"ld __tmp_reg__,%a0+\n\t"
			"st %a1+,__tmp_reg__\n\t"
			"sbiw %2,1\n\t"
			"breq L_hh%=\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_ho%=\n"
			"L_hh%=:"
			: "=e" (__dummy1), "=e" (__dummy2), "=w" (__dummy3)
			: "1" (__dest), "0" (__src), "2" (__n)
			);
  return __dest;
}


/* Compare S1 and S2.  */
extern inline int
strcmp (__const char *__s1, __const char *__s2)
{
  register void *__dummy1, *__dummy2;
  register char __res;
  __asm__ __volatile__ ("cmp_loop%=:\t"
			"ld __tmp_reg__,%a2+\n\t"
			"ld %0,%a1+\n\t"
			"sub %0,__tmp_reg__\n\t"
			"brne cmp_out%=\n\t"
			"tst __tmp_reg__\n\t"
			"brne cmp_loop%=\n"
			"cmp_out%=:\tbrcc cmp_end%=\n\t"
			"ldi %0,0xff\n"
			"cmp_end%=:\n"
			: "=d" (__res), "=e" (__dummy1), "=e" (__dummy2)
			: "1" (__s1), "2" (__s2));
  return __res;
}

/* Compare N characters of S1 and S2.  */
extern inline
int strncmp (__const char *__s1, __const char *__s2, size_t __n)
{
  register void *__dummy1, *__dummy2;
  register size_t __dummy3;
  register char __res;
  if (__n)
    __asm__ __volatile__ ("cmp_loop%=:\t"
			  "ld __tmp_reg__,%a2+\n\t"
			  "ld %0,%a1+\n\t"
			  "sub %0,__tmp_reg__\n\t"
			  "brne cmp_end%=\n\t"
			  "sbiw %3,1\n\t"
			  "breq cmp_out%=\n\t"
			  "tst __tmp_reg__\n\t"
			  "brne cmp_loop%=\n"
			  "cmp_out%=:\tbrcc cmp_end%=\n\t"
			  "ldi %0,0xff\n"
			  "cmp_end%=:\n"
			  : "=d" (__res),"=e"(__dummy1),"=e"(__dummy2),"=w"(__dummy3)
			  : "1" (__s1), "2" (__s2), "3" (__n));
  return __res;
}

#if defined (__USE_GNU) && defined (__GNUC__)
/* Duplicate S, returning an identical alloca'd string.  */
#define strdupa(s)							      \
  (__extension__							      \
    ({									      \
      __const char *__old = (s);					      \
      size_t __len = strlen (__old) + 1;				      \
      char *__new = __builtin_alloca (__len);				      \
      memcpy (__new, __old, __len);					      \
    }))

/* Return an alloca'd copy of at most N bytes of string.  */
#define strndupa(s, n)							      \
  (__extension__							      \
    ({									      \
      __const char *__old = (s);					      \
      size_t __len = strnlen (__old, (n));				      \
      char *__new = __builtin_alloca (__len + 1);			      \
      __new[__len] = '\0';						      \
      memcpy (__new, __old, __len);					      \
    }))
#endif

/* Find the first occurrence of C in S.  */
extern inline char *
strchr (const char * __s, __string_h_int__ __c)
{
  __asm__ __volatile__ ("L_hi%=:\t"
			"ld __tmp_reg__,%a0+\n\t"
			"cp __tmp_reg__,%2\n\t"
			"breq L_ho%=\n\t"
			"tst __tmp_reg__\n\t"
			"brne L_hi%=\n\t"
			"ldi %A0,1\n\t"
			"ldi %B0,0\n"
			"L_ho%=:\t"
			"sbiw %0,1"
			: "=e" (__s)
			: "0" (__s), "r" (__c));
  return (char*)__s;
}


/* Find the last occurrence of C in S.  */
extern inline char *
strrchr (__const char *__src, __string_h_int__ __c)
{
  register void *__dummy;
  register char *__ret;
  __asm__ __volatile__ (
			"L_hi%=:\t"
			"ld __tmp_reg__,%a0+\n\t"
			"cp __tmp_reg__,%2\n\t"
			"brne L_ho%=\n\t"
			"mov %A1,%A0\n\t"
			"mov %B1,%B0\n"
			"L_ho%=:\t"
			"tst __tmp_reg__\n\t"
			"brne L_hi%=\n\t"
			: "=e" (__dummy), "=r" (__ret)
			: "r" (__c), "1" (1L), "0" (__src)
			);
  return --__ret;
}

/* Find the length of STRING, but scan at most MAXLEN characters.
   If no '\0' terminator is found in that many characters, return MAXLEN.  */
extern inline size_t
strnlen (__const char *__string, size_t __maxlen)
{
  __const char *__end = (__const char *) memchr (__string, '\0', __maxlen);
  return __end ? __end - __string : __maxlen;
}

#endif /* string-avr.h  */



Back