/*
 * $Id: strasm.h, simple string actions in assembly
 */

#ifndef STRASM_H
#define STRASM_H

#ifndef NULL
#define	NULL ((void *) 0x0)
#endif

static inline void * memcpy(void *dest, void *src, ulong count)
{
	int d1,d2,d3;
	__asm__ __volatile__ (
		"rep; movsb"
		: "=&c" (d1), "=&S" (d2), "=&D" (d3)
		: "0" (count), "1" ((ulong) src), "2" ((ulong) dest));
	return dest;
}

static inline char * strcpy(char *dest, char *src)
{
	int	d1, d2, d3;
	__asm__ __volatile__ (
		"1:\tlodsb\n\t"
		"stosb\n\t"
		"testb %%al, %%al\n\t"
		"jne 1b\n\t"
		: "=&a" (d1), "=&S" (d2), "=&D" (d3)
		: "1" ((ulong) src), "2" ((ulong) dest));
	return dest;
}

static inline char * strcat(char *dest, char *src)
{
	int	d1, d2, d3, d4;
	__asm__ __volatile__ (
		"decl	%0\n\t"
		"repnz; scasb\n\t"
		"decl   %1\n\t"
		"1:\tlodsb\n\t"
		"stosb\n\t"
		"testb %%al, %%al\n\t"
		"jnz 1b\n\t"
		: "=&a" (d1), "=&c" (d2), "=&D" (d3), "=&S" (d4)
		: "0" (0), "1" (0), "2" ((ulong) dest), "3" ((ulong) src));
	return dest;
}

static inline int strcmp(const char * cs,const char * ct)
{
int d0, d1;
register int __res;
__asm__ __volatile__(
	"1:\tlodsb\n\t"
	"scasb\n\t"
	"jne 2f\n\t"
	"testb %%al,%%al\n\t"
	"jne 1b\n\t"
	"xorl %%eax,%%eax\n\t"
	"jmp 3f\n"
	"2:\tsbbl %%eax,%%eax\n\t"
	"orb $1,%%al\n"
	"3:"
	:"=a" (__res), "=&S" (d0), "=&D" (d1)
		     :"1" (cs),"2" (ct));
return __res;
}

static inline char *strchr(char *s, char c)
{
	register char *res;
	int	d1, d2;
	uchar	d3;
	__asm__ __volatile__ (
		"1:\tlodsb\n\t"
		"test %%al, %%al\n\t"
		"jz 2f\n\t"
		"cmpb %2, %%al\n\t"
		"jne 1b\n\t"
		"lea -1(%%esi), %0\n\t"
		"jmp 1b\n\t"
		"2:\n\t"
		: "=&r" (res), "=&r" ((uchar) d3), "=&a"  (d1), "=&S" (d2)
		: "0" (0), "1" (c), "3" (s));
	return res;
}

static inline int strlen(char *s)
{
	int d1, d2;
	register int res;
	__asm__ __volatile (
		"decl %0\n\t"
		"repnz; scasb\n\t"
		"notl %0\n\t"
		"decl %0\n\t"
		: "=c" (res), "=&D" (d1), "=&a" (d2) : "0" (0), "1" (s), "2" (0));
	return res;
}

static inline void * memmove(void * dest,void * src, ulong n)
{
int d0, d1, d2;
if (dest<src)
__asm__ __volatile__(
	"rep\n\t"
	"movsb"
	: "=&c" (d0), "=&S" (d1), "=&D" (d2)
	:"0" (n),"1" (src),"2" (dest)
	: "memory");
else
__asm__ __volatile__(
	"std\n\t"
	"rep\n\t"
	"movsb\n\t"
	"cld"
	: "=&c" (d0), "=&S" (d1), "=&D" (d2)
	:"0" (n),
	 "1" (n-1+(const char *)src),
	 "2" (n-1+(char *)dest)
	:"memory");
return dest;
}

static inline void * memchr(const void * cs,int c,ulong count)
{
int d0;
register void * __res;
if (!count)
	return NULL;
__asm__ __volatile__(
	"repne\n\t"
	"scasb\n\t"
	"je 1f\n\t"
	"movl $1,%0\n"
	"1:\tdecl %0"
	:"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
return __res;
}

static inline void * memset(void * s, char c, ulong count)
{
int d0, d1;
__asm__ __volatile__(
	"rep\n\t"
	"stosb"
	: "=&c" (d0), "=&D" (d1)
	:"a" (c),"1" (s),"0" (count)
	:"memory");
return s;
}

static inline unsigned strnlen(const char * s, unsigned count)
{
        const char *sc;

        for (sc = s; count-- && *sc != '\0'; ++sc)
                /* nothing */;
        return sc - s;
}

static inline int memcmp(const void * cs,const void * ct,size_t count)
{
int	d0, d1, d2;
register int __res;
__asm__ __volatile__(
	"repe\n\t"
	"cmpsb\n\t"
	"je 1f\n\t"
	"sbbl %0,%0\n\t"
	"orb $1,%b0\n"
	"1:"
	:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
	:"0" (0), "1" (cs), "2" (ct), "3" (count));
return __res;
}

static inline int strncmp(const char * cs,const char * ct,size_t count)
{
register int __res;
int d0, d1, d2;
__asm__ __volatile__(
	"1:\tdecl %3\n\t"
	"js 2f\n\t"
	"lodsb\n\t"
	"scasb\n\t"
	"jne 3f\n\t"
	"testb %%al,%%al\n\t"
	"jne 1b\n"
	"2:\txorl %%eax,%%eax\n\t"
	"jmp 4f\n"
	"3:\tsbbl %%eax,%%eax\n\t"
	"orb $1,%%al\n"
	"4:"
		     :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
		     :"1" (cs),"2" (ct),"3" (count));
return __res;
}

#define	CLEAR(var) memset(&var, 0, sizeof(var))
#endif
