home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1997 May
/
Pcwk0597.iso
/
delphi
/
dnarrays.lzh
/
FASTMEM.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-07-16
|
12KB
|
461 lines
{+------------------------------------------------------------
| Unit FastMem
|
| Version: 1.0 Last modified: 05/11/95, 16:47:25
| Author : P. Below
| Project: Common utilities
| Description:
| This Unit contains a number of routines to do memory moves,
| fills and swaps as fast as possible. The routines are all
| implemented in assembler; the Win32-version will generate
| different code from the Win16 version.
| WARNING! The Win32 version is totally untested since a
| 32bit version of Delphi is not yet available!
|
| This version will compile as is in BP 7
+------------------------------------------------------------}
Unit FastMem;
Interface
{$IFDEF VER70}
Type
Cardinal = Word;
{$ENDIF}
Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte );
Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
Procedure MemDWordFill(pTarget: Pointer;
numDWords: Cardinal; value: LongInt );
Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal);
Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal );
Implementation
{************************************************************
* Procedure MemFill
*
* Parameters:
* pTarget : pointer to memory to fill
* numBytes: number of bytes to fill
* value : byte value to fill with
* Description:
* Like System.FillChar, only faster, since it fills in the largest
* possible unit (word or dword) as far as possible.
* Error Conditions:
* May generate a GPF if the memory area addressed by pTarget cannot
* take numBytes bytes!
*
*Created: 05/11/95 16:53:42 by P. Below
************************************************************}
Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte ); Assembler;
{$IFNDEF WIN32}
Asm
mov cx, numBytes
jcxz @done
mov al, value
mov ah, al
les di, pTarget
push cx
cld
shr cx, 1 (* fill words first *)
jz @moveone
rep stosw
@moveone: (* fill remaining byte *)
pop cx
and cx, 1
jz @done
stosb
@done:
End;
{$ELSE}
{ we assume flat memory model here with 32bit near pointers
and ds=es!
This code is UNTESTED!
}
asm
mov ecx, numBytes
or ecx, ecx
jz @done
mov al, value
mov ah, al
mov bx,ax
shl eax, 16
mov ax, bx
mov edi, pTarget
cld
push ecx
shr ecx, 2 (* fill dwords first *)
jz @fillrest
rep stosd
@fillrest: (* fill rest bytewise *)
pop ecx
and ecx, 3
@fill:
jz @done
mov [ edi ], al
inc edi
dec ecx
jmp @fill
@done:
end;
{$ENDIF}
{************************************************************
* Procedure MemWordFill
*
* Parameters:
* pTarget : pointer to memory to fill
* numWords: number of words to fill
* value : word value to fill with
* Description:
* Fills the target memory area with numWords copies of value.
* Error Conditions:
* May generate a GPF if the memory area addressed by pTarget cannot
* take numWord words!
*
*Created: 05/11/95 16:53:42 by P. Below
************************************************************}
Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
Assembler;
{$IFNDEF WIN32}
Asm
mov cx, numWords
jcxz @done
mov ax, value
les di, pTarget
cld
rep stosw
@done:
End;
{$ELSE}
{ we assume flat memory model here with 32bit near pointers
and ds=es!
This code is UNTESTED!
}
asm
mov ecx, numWords
or ecx, ecx
jz @done
mov ax, value
mov bx,ax
shl eax, 16
mov ax, bx
mov edi, pTarget
cld
push ecx
shr ecx, 1 (* fill dwords first *)
jz @fillrest
rep stosd
@fillrest: (* fill rest *)
pop ecx
and ecx, 1
jz @done
mov [ edi ], ax
@done:
end;
{$ENDIF}
{************************************************************
* Procedure MemDWordFill
*
* Parameters:
* pTarget : pointer to memory to fill
* numDWords: number of dwords to fill
* value : dword value to fill with
* Description:
* Fills the target memory area with numDWords copies of value.
* Error Conditions:
* May generate a GPF if the memory area addressed by pTarget cannot
* take numDWord dwords!
*
*Created: 05/11/95 16:53:42 by P. Below
************************************************************}
Procedure MemDWordFill(pTarget: Pointer; numDWords: Cardinal; value: LongInt );
Assembler;
{$IFNDEF WIN32}
Asm
mov cx, numDWords
jcxz @done
push ds
mov ax, word ptr value
mov dx, word ptr value+2
lds bx, pTarget
@loop:
mov [ bx ], ax
inc bx
inc bx
mov [ bx ], dx
inc bx
inc bx
dec cx
jnz @loop
pop ds
@done:
End;
{$ELSE}
{ we assume flat memory model here with 32bit near pointers
and ds=es!
This code is UNTESTED!
}
asm
mov ecx, numDWords
or ecx, ecx
jz @done
mov eax, value
mov edi, pTarget
cld
rep stosd
@done:
end;
{$ENDIF}
Function CheckOverlap: Boolean; Assembler;
Asm
{$IFNDEF WIN32}
(* assumes: ds:si source pointer, es:di target pointer
cx number of bytes to copy.
returns: al = 0 if no overlap,
al = 1 if overlap, in which case the pointers
are returned corrected! *)
mov ax, ds (* compare the selectors *)
mov bx, es
cmp ax, bx
jne @no_overlap
mov ax, si (* selectors equal, check offset parts *)
cmp ax, di (* target <= source is never a problem *)
jnb @no_overlap
add ax, cx (* check for source+count > target, which signifies *)
cmp ax, di (* problematic overlap *)
jna @no_overlap
mov ax, 1 (* we have overlap, correct pointers to point at *)
add si, cx (* last byte in source and target range *)
add di, cx
dec si
dec di
jmp @done
@no_overlap:
sub ax, ax
@done:
{$ELSE}
(* assumes: esi source pointer, edi target pointer
ecx number of bytes to copy.
returns: al = 0 if no overlap,
al = 1 if overlap, in which case the pointers
are returned corrected! *)
mov eax, esi (* selectors equal by default, check offset parts *)
cmp eax, edi
jnb @no_overlap
add eax, ecx (* for source+count > target, which signifies *)
cmp eax, edi (* overlap *)
jna @no_overlap
mov eax, 1
add esi, ecx
add edi, ecx
dec esi
dec edi
jmp @done
@no_overlap:
sub eax, eax
@done:
{$ENDIF}
End;
{************************************************************
* Procedure MemMove
*
* Parameters:
* pSource : pointer to source memory
* pTarget : pointer to target memory
* numBytes : number of bytes to copy
* Description:
* Like System.Move, only faster for larger numbers of bytes,
* since it does the copy word or dword-wise, as far as possible.
* The procedure checks for overlap of source and target regions
* and performs the copy from highest address backwards, if the
* regions overlap in a problematic way. The logic is optimized
* for the source address beeing even (data word or dword-aligned).
*
* Error Conditions:
* May cause a GPF if the memory addressed by the pointers has
* a size of less than numBytes bytes.
*
*Created: 05/11/95 16:58:34 by P. Below
************************************************************}
Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal); Assembler;
{$IFNDEF WIN32}
Asm
push ds
mov cx, numBytes
jcxz @done
lds si, pSource
les di, pTarget
call CheckOverlap
or al,al
jnz @overlap
cld (* address ascending *)
push cx
shr cx, 1 (* move words first *)
jz @moveone
rep movsw
@moveone: (* move remaining byte *)
pop cx
and cx, 1
jz @done
movsb
jmp @done
@overlap:
std
test cx, 1 (* check for odd count of bytes *)
je @moverest
movsb (* if odd, move one byte first *)
@moverest:
shr cx, 1 (* count is now in words *)
jz @done
dec si
dec di
rep movsw (* move rest as words *)
cld
@done:
pop ds
End;
{$ELSE}
{ we assume flat memory model here with 32bit near pointers
and ds=es!
This code is UNTESTED!
}
asm
mov ecx, numBytes
or ecx, ecx
jz @done
mov esi, pSource
mov edi, pTarget
call CheckOverlap
or al,al
jnz @overlap
cld
push ecx
shr ecx, 2 (* move dwords first *)
jz @moverest
rep movsd
@moverest: (* move rest bytewise *)
pop ecx
and ecx, 3
jz @done
rep movsb
jmp @done
@overlap:
std
test ecx, 1 (* check for odd count of bytes *)
jz @move2
movsb (* if odd, move one byte first *)
@move2:
shr ecx, 1
dec esi
dec edi
jz @done
test ecx, 1 (* check for odd count of words *)
jz @move3
movsw (* if yes, move one word *)
@move3:
shr ecx, 1
jz @done
dec esi,2
dec edi,2
rep movsd
cld
@done:
end;
{$ENDIF}
{************************************************************
* Procedure MemSwap
*
* Parameters:
* pSource : pointer to source memory
* pTarget : pointer to target memory
* numBytes : number of bytes to swap
* Description:
* exchanges the contents of the memory addressed by the two
* pointers. These areas should never overlap or the results
* will invariably be somewhat strange!
* Error Conditions:
* May cause a GPF if the memory addressed by the pointers has
* a size of less than numBytes bytes.
*
*Created: 05/11/95 16:58:34 by P. Below
************************************************************}
Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal ); Assembler;
{$IFNDEF WIN32}
Asm
push ds
mov cx, numBytes
jcxz @done
lds si, pSource
les di, pTarget
cmp cx, 1
je @swapone
@loop:
mov ax, [ si ]
xchg ax, es:[ di ]
mov [ si ], ax
inc si
inc si
inc di
inc di
dec cx
dec cx
jz @done
cmp cx, 1
ja @loop
@swapone:
mov al, [ si ]
xchg al, es:[ di ]
mov [ si ], al
@done:
pop ds
End;
{$ELSE}
{ we assume flat memory model here with 32bit near pointers
and ds=es!
This code is UNTESTED!
}
asm
mov ecx, numBytes
or ecx, ecx
jz @done
mov esi, pSource
mov edi, pTarget
cmp ecx, 3
jna @swapremains
@loop:
mov eax, [ esi ]
xchg eax, [ edi ]
mov [ esi ], eax
inc esi, 4
inc edi, 4
dec ecx, 4
jz @done
cmp ecx, 3
ja @loop
@swapremains:
cmp ecx, 1
je @swapone
mov ax, [ esi ]
xchg ax, [ edi ]
mov [ esi ], ax
inc esi, 2
inc edi, 2
dec ecx, 2
jz @done
@swapone:
mov al, [ esi ]
xchg al, [ edi ]
mov [ esi ], al
@done:
end;
{$ENDIF}
End.