| |
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
|
|
|