/*--------------------------------------------------------------------------
 * File: xstdlib.c
 * Written by: Alexander Boczar, 1997-05-01
 * Description: Extended stdlib
 *
 * Updates:
 * -- Date -- | ----- Name ----- |-- Did what....
 * 1997-06-08 | Alexander Boczar | Byte namn på memcpy32,memset32 till memcpy4, memset4..
 * 1997-06-08 | Alexander Boczar | La till en memcpy16 , som använder sig av matteprocessorn
 *
 -------------------------------------------------------------------------------*/

#include "system/xstring.h"
#include "system/xstdio.h"
#include "system/xstdlib.h"
//#include "debug/mono.h"
#include <malloc.h>

/************************************************************************
 *
 * Func: memcpy/memset(4,16)
 * Auth: Alexander Boczar
 * Date: 1997-05-01 - Implementation
 *
 * Desc: Identiska med memcpy/memset, fast snabbare och length = antal dwords
 *
 ************************************************************************/

#if !defined(__WATCOMC__) && defined(__X86__)

void memset4( void *dst, DWORD data, DWORD len)
{
	__asm
	{
		push edi
		mov eax,data
		mov edi,dst
		mov ecx,len
		rep stosd
		pop edi
	}
}

void memcpy4( void *dst, void *src, DWORD len)
{
	__asm
	{
		push edi
		push esi
		mov esi,src
		mov edi,dst
		mov ecx,len
		rep movsd
		pop esi
		pop edi
	}
}


void memset16( void *dst, DWORD data, DWORD len)
{
  __asm
	{
		push edi
    mov edi,dst
    mov eax,data
    mov [edi+0],eax
    mov [edi+4],eax
    fild qword ptr [edi]
		mov ecx,len
		l:
    fst qword ptr [edi]
    fst qword ptr [edi+8]
    add edi,16
		dec ecx
		jnz l
    fstp st(0)
    pop edi
	}
}

void memcpy16( void *dst, void *src, DWORD len)
{
	__asm
	{
		push esi
		push edi
		mov esi,src
		mov edi,dst
		mov ecx,len
		l:
    fld qword ptr [esi]
    fld qword ptr [esi+8]
		fxch
    fstp qword ptr [edi]
    fstp qword ptr [edi+8]
		add esi,16
		add edi,16
		dec ecx
		jnz l
		pop edi
		pop esi
	}
}

#elif !defined(__X86__)

void memset4( void *dst, DWORD data, DWORD length)
{
  for( ; length; length--)
    *(((DWORD *)dst)++) = data;
}

void memcpy4( void *dst, void *src, DWORD length)
{
	memcpy( dst, src, length << 2);
}

void memset16( void *dst, DWORD data, DWORD length)
{
  memset4( dst, data, length << 2);
}

void memcpy16( void *dst, void *src, DWORD length)
{
	memcpy( dst, src, length << 4);
}


#endif

/************************************************************************
 *
 * Func: xmalloc
 * Auth: Alexander Boczar
 * Date: 1997-05-10 - Implementation
 *
 * Desc: malloc + clear
 *
 ************************************************************************/

static int allocblocks = 0, allocblocks_max = 0;
static int allocbytes = 0, allocbytes_max = 0;

void *xmalloc( DWORD size)
{
  void *buffer = malloc( size);
  if( buffer != NULL)
	{
		allocbytes += size;
		if( allocbytes_max < allocbytes)
			allocbytes_max = allocbytes;
		allocblocks++;
		if( allocblocks_max < allocblocks)
			allocblocks_max = allocblocks;
    memset( buffer, 0, size);
	}
  //debug_printfxy( 0, 24, "Allocated memory: %d Kb (%d) , Peak: %d Kb (%d)       \n", allocbytes/1024, allocblocks, allocbytes_max/1024, allocblocks_max);
	return( buffer);
}
int xbytes_allocated (void)
{
	return allocbytes;
}
int xbytes_peak (void)
{
	return allocbytes_max;
}
int xblocks_allocated (void)
{
	return allocblocks;
}
int xblocks_peak (void)
{
	return allocblocks_max;
}

void *xsafe_malloc( DWORD size)
{
  void *buffer = xmalloc( size);
  if( buffer == NULL)
  {
		fprintf( stderr, "[!] Fatal memory allocation failure!\n");
    exit(-1);
  }
  return( buffer);
}

/************************************************************************
 *
 * Func: xfree
 * Auth: Alexander Boczar
 * Date: 1997-05-10 - Implementation
 *
 * Desc: free + hantering av NULL
 *
 ************************************************************************/

void xfree( void *buffer)
{
  if( buffer != NULL)
	{
		allocblocks--;
		allocbytes -= _msize( buffer);		// Function _msize is non ANSI
    free( buffer);
	}
  //debug_printfxy( 0, 24, "Allocated memory: %d Kb (%d) , Peak: %d Kb (%d)       \n", allocbytes/1024, allocblocks, allocbytes_max/1024, allocblocks_max);
}

