;///////////////////////////////////////////////////////////////////////////////
;/// @file memset.asm
;///
;/// @brief Destiny3D Memory Manager memset replacement
;///
;/// @author Lightning
;///
;/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
;/// contents of this file is subject to the Destiny3D Member License which
;/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
;///
;/// This file is distributed "AS IS" without warranty of any kind.  Novus
;/// Delta, LLC. does not guarantee the fitness of the contents of this file
;/// for any particular purpose.
;///
;/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
;///
;/// <hr>
;///                                 Change History
;/// <hr>
;///
;/// @date May 2001
;/// @author Lightning
;/// @remarks Creation
;///
;///////////////////////////////////////////////////////////////////////////////

.586p					;pentium commands allowed
.mmx					;MMX allowed
.k3d					;3DNow allowed
.model flat, C

.CODE

;i take care of pushing and popping edi, esi, ebp, and ebx if I need to use them
;as it makes it easier to cut down on the code that the function goes thru

ByteArray dd	Bytes_0, Bytes_1, Bytes_2, Bytes_3, Bytes_4, Bytes_5, Bytes_6, Bytes_7,
				075766F4Eh, 065442073h, 02C61746Ch, 0434C4C20h, 000444E00h
			
Bytes_0:
	pop eax
	pop ebx
	ret
		
Bytes_1:
	mov [ecx], bl
	pop eax
	pop ebx
	ret

Bytes_2:
	mov [ecx], bx
	pop eax
	pop ebx
	ret

Bytes_3:
	mov [ecx], bx
	mov [ecx+2], bl
	pop eax
	pop ebx
	ret

Bytes_4:
	mov [ecx], ebx
	pop eax
	pop ebx
	ret

Bytes_5:
	mov [ecx], ebx
	mov [ecx+4], bl
	pop eax
	pop ebx
	ret

Bytes_6:
	mov [ecx], ebx
	mov [ecx+4], bx
	pop eax
	pop ebx
	ret

Bytes_7:
	mov [ecx], ebx
	mov [ecx+4], bx
	mov [ecx+6], bl
	pop eax
	pop ebx
	ret

Internal_ASM_memset proc
	;the Paramaters are void *Ptr1, char SetChar, long Len

	push ebx
	mov ebx, esp
	align 4

	mov eax, [ebx + 10h]	;Len
	mov ecx, [ebx + 08h]	;Ptr1
	mov ebx, [ebx + 0Ch]	;SetChar

	;fill ebx with the byte to set with
	mov edx, ebx
	shl ebx, 8
	or ebx, edx
	mov edx, ebx
	shl ebx, 16
	or ebx, edx

	;push this on so it can be pop'd on ret in eax
	push ecx

	;see if there are 8 or more bytes to set
	test eax, 0FFFFFFF8h
	jnz Memset_LargerThan7

	;7 or less bytes, jump based on eax
	jmp dword ptr ByteArray[eax*4]

	Memset_LargerThan7:
		;set eax to the multiple of times we need to loop thru
		push ecx

		xor edx, edx
		mov ecx, 8
		div ecx

		;set ecx to where to write to
		pop ecx

	MemsetLoop:
		mov [ecx], ebx
		mov [ecx+4], ebx

		add ecx, 8
		dec eax
		jnz MemsetLoop

	jmp dword ptr ByteArray[edx*4]

Internal_ASM_memset endp

Internal_ASM_MMX_memset proc
	;the Paramaters are void *Ptr1, char SetChar, long Len

	push ebx
	mov ebx, esp
	align 4

	mov eax, [ebx + 10h]	;Len
	mov ecx, [ebx + 08h]	;Ptr1
	mov ebx, [ebx + 0Ch]	;SetChar

	;fill ebx with the byte to set with
	mov edx, ebx
	shl ebx, 8
	or ebx, edx
	mov edx, ebx
	shl ebx, 16
	or ebx, edx

	;save where we wrote to so we can pop it off on ret in eax
	push ecx

	;see if 7 or less bytes exist
	cmp eax, 07h
	jg MemsetMMX_LargerThan7

	;smaller than 8, jump to the place the array points to
	jmp dword ptr ByteArray[eax*4]


	MemsetMMX_LargerThan7:

		;fill mm0 with the byte to fill the data with
		movd mm0, ebx
		movd mm1, ebx
		punpckldq mm0, mm1
		movq mm1, mm0

		;see if there are 15 or less bytes, if so then jump
		;over some simple tests
		mov edx, eax
		test eax, 0FFFFFFF0h
		jz short MemsetMMX_SmallerThan15

		;15 or more bytes, do it

	MemsetMMX_LargerThan15:

		;set eax to the multiple of times we need to loop thru
		push ecx

		xor edx, edx
		mov ecx, 16
		div ecx

		;set ecx to where to write to
		pop ecx

	MemsetLoopMMX:
		movq [ecx], mm0
		movq [ecx+8], mm1

		add ecx, 16
		dec eax
		jnz MemsetLoopMMX

	MemsetMMX_SmallerThan15:
		test edx, 8
		jz short MemsetMMX_SmallerThan7

		movq [ecx], mm0
		add ecx, 8
		and edx, 7
		
	MemsetMMX_SmallerThan7:
		emms
		jmp dword ptr ByteArray[edx*4]

Internal_ASM_MMX_memset endp


END