; =========================================================================
;                  Fast floating point and memory operations
; =========================================================================
%ifdef  __UNIX__

; Use cdecl calling convention
%define DO_RET(arg) retn

; No name mangling
%macro  C_GLOBAL    2
	global  %1
%endmacro

%elifdef    __WIN32__

; Use __stdcall calling convention
%define DO_RET(arg) retn arg

%macro C_GLOBAL 2
	%define %1 _%1@%2
	global _%1@%2
%endmacro

%endif  ; __WIN32__

; ========================================================================
C_GLOBAL    v_abs_f,        4
C_GLOBAL    v_fsincos_f,    12
C_GLOBAL    v_fsincos_d,    16
;
; TODO: stole optimized code from glibc.
; TODO: memMove() (is it really needed ?)
;
C_GLOBAL    memFill,        12
C_GLOBAL    memZero,        8
C_GLOBAL    memCopy,        12
C_GLOBAL    memFill32,      12
C_GLOBAL    memFill4ub,     12
C_GLOBAL    memZero32,      8
C_GLOBAL    memCopy32,      12
; ========================================================================
section .text
bits 64
%define ALIGN   16
; ========================================================================
align ALIGN
v_abs_f:
	and     dword [esp+4], 07fffffffh
	fld     dword [esp+4]
	DO_RET(4)
; ========================================================================
align ALIGN
v_fsincos_f:
	fld     dword [esp+12]
	fsincos
	mov     eax, [esp+8]
	mov     edx, [esp+4]
	fstp    dword [eax]
	fstp    dword [edx]
	DO_RET(12)
; ========================================================================
align ALIGN
v_fsincos_d:
	fld     qword   [esp+12]
	fsincos
	mov     eax, [esp+8]
	mov     edx, [esp+4]
	fstp    qword   [eax]
	fstp    qword   [edx]
	DO_RET(16)
; ========================================================================
%ifndef NO_MEMOPS

align ALIGN
memFill:
	cld
	push    rdi
	movzx   rdi, dword [esp+8]
	mov     al, byte [esp+12]
	movzx   rdx, dword [esp+16]
	mov     ah, al
	mov     cx, ax
	shl     eax, 16
	mov     ax, cx
	mov     ecx, eax
	shl     rax, 32
	mov     eax, ecx
	mov     ecx, edx
	shr     ecx, 3
	rep     stosq
	mov     cl, dl
	and     cl, 7
	rep     stosb
	pop     edi
	DO_RET(12)
; ========================================================================
align ALIGN
memZero:
	cld
	push    edi
	mov     edi, dword [esp+8]
	mov     edx, dword [esp+12]
	xor     eax, eax
	mov     ecx, edx
	shr     ecx, 2
	rep     stosd
	mov     cl, dl
	and     cl, 3
	rep     stosb
	pop     edi
	DO_RET(8)
; ========================================================================
align ALIGN
memCopy:
	cld
	push    edi
	push    esi
	mov     edi, dword [esp+12]
	mov     esi, dword [esp+16]
	mov     eax, dword [esp+20]
	mov     ecx, eax
	shr     ecx, 2
	rep     movsd
	mov     cl, al
	and     cl, 3
	rep     movsb
	pop     esi
	pop     edi
	DO_RET(12)
; ========================================================================
align ALIGN
memFill32:
	cld
	push    edi
	mov     edi, dword [esp+8]
	mov     al, byte [esp+12]
	mov     ah, al
	mov     ecx, eax
	shl     eax, 16
	mov     ax, cx
	mov     ecx, dword [esp+16]
	rep     stosd   
	pop     edi
	DO_RET(12)
; ========================================================================
align ALIGN
memFill4ub:
	cld
	push    edi
	mov     edi, dword [esp+8]
	mov     eax, dword [esp+12]
	mov     ecx, dword [esp+16]
	rep     stosd   
	pop     edi
	DO_RET(12)
; ========================================================================
align ALIGN
memZero32:
	cld
	push    edi
	xor     eax, eax
	mov     edi, dword [esp+8]
	mov     ecx, dword [esp+12]
	rep     stosd
	pop     edi
	DO_RET(8)
; ========================================================================
align ALIGN
memCopy32:
	cld
	push    edi
	push    esi
	mov     ecx, dword [esp+20]
	mov     edi, dword [esp+12]
	mov     esi, dword [esp+16]
	rep     movsd   
	pop     esi
	pop     edi
	DO_RET(12)
; ========================================================================

%endif  ; NO_MEMOPS
