//
// lmisc.asm
//
// odds and ends
//
// Copyright (C) 1996-7 by Leonard Janke (janke@unixg.ubc.ca)

#include <lmisc/config.h>

inline void LMisc::MemZero(u8* x, int bytes)
{
  asm volatile("cld\n\t"
	       "movb $0, %%al\n\t"
	       "repe\n\t"
	       "stosb (%%edi)\n\t"
	       :
	       : "D" (x), "ecx" (bytes)
	       : "%edi", "%ecx", "%al", "memory"
	       );
}

inline void LMisc::MemZero(u32* x, int size)
{
  asm volatile("cld\n\t"
	       "movl $0, %%eax\n\t"
	       "repe\n\t"
	       "stosl (%%edi)\n\t"
	       :
	       : "D" (x), "ecx" (size)
	       : "%edi", "%ecx", "%eax", "memory"
	       );
}

inline void LMisc::MemCopy(u32* dest, const u32* source, int size)
{
  asm volatile("cld\n\t"
	       "rep\n\t"
	       "movsl (%%esi), (%%edi)\n\t"
	       :
	       : "S" (source), "D" (dest), "ecx" (size)
	       : "%ecx", "%esi", "%edi", "memory"
	       );
}

inline void LMisc::MemMove(u32* dest, u32* source, int size)
{
  if ( source > dest )
    {
      asm volatile("cld\n\t"
		   "rep\n\t"
		   "movsl (%%esi), (%%edi)\n\t"
		   :
		   : "S" (source), "D" (dest), "ecx" (size)
		   : "%ecx", "%esi", "%edi", "memory"
		   );
    }
  else
    {
      asm volatile("std\n\t"
		   "rep\n\t"
		   "movsl (%%esi), (%%edi)\n\t"
		   :
		   : "S" (source+size-1), "D" (dest+size-1), "ecx" (size)
		   : "%ecx", "%esi", "%edi", "memory"
		   );
    }
}

inline u32 LMisc::BSwap(u32 x)
{
#if #LC_CPU (i486) 
      asm("bswapl %0\n\t"
	  : "=r" (x)
	  : "0" (x)
	  : "%0"
	  );
#else
      asm("xchgb %%ah, %%al\n\t"
	  "rorl $16, %%eax\n\t"
	  "xchgb %%ah, %%al\n\t"
	  : "=eax" (x)
	  : "eax" (x)
	  : "%eax" 
	  );
#endif

  return x;
}
