#ifndef V_X86_H
#define V_X86_H

#if		!defined(__INTEL__) || defined(__CYGWIN32__) \
		|| defined(__BORLANDC__)
#define	__NOX86__
#endif	/* !defined(__INTEL__) */

#ifdef	__NOX86__

#define	memFill(dest,value,length)		memset(dest,value,length)
#define	memZero(dest,length)			memset(dest,0,length)
#define	memCopy(dest,src,length)		memcpy(dest,src,length)
#define	memFill32(dest,value,dwords)	memset(dest,value,(dwords)<<2)
#define	memZero32(dest,dwords)			memset(dest,0,(dwords)<<2)
#define	memCopy32(dest,src,dwords)		memcpy(dest,src,(dwords)<<2)
#define	v_abs(x)						((vec_t)fabs((double)(x)))
#define	v_fsincos(s,c,r)				*((vec_t*)s)=sin(r);*((vec_t*)c)=cos(r)

#else     /* !__NOX86__ */

#ifdef		__WATCOMC__

/*
 *	Use WATCOM inline assembler for memory routines
 */
void        memFill( void *dest, unsigned char value, unsigned long length);
#pragma aux memFill = 				\
	"mov ah, al"					\
	"mov ecx, eax"					\
	"shl eax, 16"					\
	"mov ax, cx"					\
	"mov ecx, edx"					\
	"shr ecx, 2"					\
	"rep stosd"						\
	"mov cl, dl"					\
	"and cl, 3"						\
	"rep stosb"						\
	parm [EDI] [AL] [EDX] 			\
    modify exact [EAX ECX EDI];

void        memZero(void *dest, unsigned long length);
#pragma aux memZero = 				\
	"xor eax, eax"					\
	"mov ecx, edx"					\
	"shr ecx, 2"					\
	"rep stosd"						\
	"mov cl, dl"					\
	"and cl, 3"						\
	"rep stosb"						\
	parm [EDI] [EDX]	 			\
    modify exact [EAX ECX EDI];

void        memCopy( void *dest, void *src, unsigned long length );
#pragma aux memCopy =            	\
	"mov	ecx,eax"				\
	"shr    ecx,2"                  \
	"rep    movsd"                  \
	"mov	cl,al"					\
	"and	cl,3"					\
	"rep	movsb"					\
	parm [EDI] [ESI] [EAX]			\
	modify exact [EAX ECX ESI EDI];

void        memFill32(void *dest,unsigned char value,unsigned long dwords);
#pragma aux memFill32 = 			\
	".486" 	/* for bswap */			\
	"mov ah, al"					\
	"mov edx, eax"					\
	"bswap eax"						\
	"mov ax, dx"					\
	"rep stosd"						\
	parm [EDI] [AL] [ECX]			\
    modify exact [EAX ECX EDX EDI];

void        memFill4ub(void *dest,unsigned long values,unsigned long dwords);
#pragma aux memFill4ub = 			\
	"rep stosd"						\
	parm [EDI] [EAX] [ECX]			\
    modify exact [ECX EDI];

void        memZero32(void *dest,unsigned long dwords);
#pragma aux memZero32= 				\
	"xor eax, eax"					\
	"rep stosd"						\
	parm [EDI] [ECX] 				\
    modify exact [EAX ECX EDI];

void        memCopy32(void *dest, void *src, unsigned long dwords);
#pragma aux memCopy32= 				\
	"rep movsd"						\
	parm [EDI] [ESI] [ECX] 			\
    modify exact [EDI ESI ECX];

#else /* !__WATCOMC__ */

/*
 *	TODO: add GNUC inline assembler code
 */

#ifdef	__cplusplus
extern "C" {
#endif /* __cplusplus */
	void	V_GLOBAL	memFill(void *dest, unsigned char value, unsigned int _length);
	void	V_GLOBAL	memZero(void *dest, unsigned int _length);
	void	V_GLOBAL	memCopy(void *dest, void *src, unsigned int _length);
	void	V_GLOBAL	memFill32(void *dest,unsigned char value, unsigned int _dwords);
	void	V_GLOBAL	memFill4ub(void *dest,unsigned long values, unsigned int _dwords);
	void	V_GLOBAL	memZero32(void *dest, unsigned int _dwords);
	void	V_GLOBAL	memCopy32(void *dest, void *src, unsigned int _dwords);
#ifdef	__cplusplus
}
#endif /* __cplusplus */

#endif /* !__WATCOMC__ */

#ifdef	__cplusplus
extern "C" {
#endif	/* __cplusplus */
	float	V_GLOBAL	v_abs_f(float x);
	void	V_GLOBAL	v_fsincos_f(float *s,float *c,float radians);
	void	V_GLOBAL	v_fsincos_d(double *s,double *c,double radians);
#ifdef	__cplusplus
}
#endif	/* __cplusplus */

#ifdef CONFIG_DOUBLEVEC
#define v_abs(x)          fabs(x)
#define v_fsincos(s,c,r)  v_fsincos_d(s,c,r)
#else	/* !CONFIG_DOUBLEVEC */
#define v_abs(x)          v_abs_f(x)
#define v_fsincos(s,c,r)  v_fsincos_f(s,c,r)
#endif  /* !CONFIG_DOUBLEVEC */

#endif /* !__NOX86__ */

#endif /* V_X86_H */
