                              The Memory Unit

                         Written by Thomas Schatzl



FEATURES

   * Fast memory transfers by using the FPU, speed increase of up to 100%
     on Intel Pentium systems
   * Fast memory set procedures
   * Replaces the go32 move* and fillchar* functions with high speed
     assembler procedures completely
   * 16 boolean operations between two memory regions or memory and a
     single value possible
   * Boolean operations match Mircosoft ROP order
   * Automatically uses MMX extensions if available

   * Writes information to stderr if DEBUG is defind

BACKGROUND

This unit was done because I need fast memory copy routines and boolean bit
operation for a greater project of mine, a graphics library which uses the
2D acceleration features of most graphics chips nowadays. Some procedures
are needed to support all functions (bitblt, HW memory copies..) in
software for chipsets which don't support HW acceleration or miss one or
another feature or are simply older.
On the other hand I wanted to know what comes out if you take advantage of
modern chipsets available instruction sets. And it seems it was worth the
effort, because there's a speed gain of up to 400% when using FPU or MMX 
instructions to copy memory, or using Intel's MMX extensions for boolean 
operations on my P200 MMX.


SYSTEM REQUIREMENTS

This unit requires an IBM PC or compatible with an 80386 or higher
processor.


PROGRAMMING LANGUAGE

This Memory unit can be compiled with FPC Pascal (32-bit protected mode
freeware DOS compiler) and a GNU assembler version of 2.9.1 or higher.

Supports following extenders:

   * GO32V1
   * GO32V2
   * PMODE D/J

Needs the following switches enabled:

   * none

WHERE TO GET FPC PASCAL COMPILER

You will find latest version of FPC Pascal compiler on
http://home.pages.de/~FPK-Pascal




                           MEMORY UNIT REFERENCE

                                    Index



Memory types

Mem_Op (enumeration)
DWord (type)


Memory Functions

procedure memcpy (var src, dst; size : DWord)

procedure memsetB (var x; size : DWord; value : Byte)
procedure memsetW (var x; size : DWord; value : Word)
procedure memsetD (var x; size : DWord; value : DWord)

procedure memchange (var src, dst; size : DWord; op : Mem_Op)

procedure memchangeValueB (var x; size : DWord; value : Byte; op : Mem_Op)
procedure memchangeValueW (var x; size : DWord; value : Word; op : Mem_Op)
procedure memchangeValueD (var x; size : DWord; value : DWord; op : Mem_Op)

procedure seg_memcpy (srcsel : Word; srcofs : DWord; dstsel : Word; dstofs
: Dword; size : DWord)

procedure seg_memsetB (sel : Word; ofs : DWord; size : DWord; value : Byte)
procedure seg_memsetW (sel : Word; ofs : DWord; size : DWord; value : Word)

procedure seg_memsetD (sel : Word; ofs : DWord; size : DWord; value :
DWord)

procedure seg_memchange (srcsel : Word; srcofs : DWord; dstsel : Word;
dstofs : DWord; size : DWord; op : Mem_Op)

procedure seg_memchangeValue (sel : Word; ofs : DWord; size : DWord; value
: Byte; op : Mem_Op)
procedure seg_memchangeValueW (sel : Word; ofs : DWord; size : DWord; value
: Word; op : Mem_Op)
procedure seg_memchangeValueD (sel : Word; ofs : DWord; size : DWord; value
: DWord; op : Mem_Op)




                                Memory Types



Mem_Op (enumeration)

Describes the 16 possible boolean operations between two values

Description
This enumeration describes the 16 possible boolean operations between two
bits (in this case src and dst) using the and, or, xor and not operators.

The following table shows these operation modes:

 Enumeration name    Boolean bit operation result  Description / Note
 MEM_CLEAR           dst = 0                       zero out destination
 MEM_NOT_DSTORSRC    dst = not (dst or src)
 MEM_DST_AND_NOTSRC  dst = dst and (not src)
 MEM_NOTSRC          dst = not src                 invert source and copy
 MEM_SRC_AND_NOTDST  dst = src and (not dst)
 MEM_NOTDST          dst = not dst                 invert destination
 MEM_DST_XOR_SRC     dst = dst xor src
 MEM_NOT_DSTANDSRC   dst = not (dst and src)
 MEM_DST_AND_SRC     dst = dst and src
 MEM_NOT_DSTXORSRC   dst = not (dst xor src)
 MEM_DST             dst = dst                     does nothing
 MEM_DST_OR_NOTSRC   dst = dst or (not src)
 MEM_SRC             dst = src                     copy / fill
 MEM_NOTDST_OR_SRC   dst = (not dst) or src
 MEM_DST_OR_SRC      dst = dst or src
 MEM_SET             dst = 1                       set destination


The result is archieved by combining src and dst values bit by bit.

Example 1:

src = %10001
dst = %01011
selected operation : MEM_DST_OR_NOTSRC

dst = dst or (not src)
    = %01011 or (not %10001)
    = %01011 or %01111
    = %01111

Example 2:

src = %10001
dst = %01001
selected operation : MEM_CLEAR

dst = 0
    = %00000

In this case the src and dst memory contents are not important at all.

The next table shows the results of the four different basic operations
according to given expressions A and B.

        AND                OR                XOR                NOT

   A     B   result   A     B  result    A    B   result
   0     0     0      0     0     0      0    0      0       A     result
   1     0     0      1     0     1      1    0      1       1       0
   0     1     0      0     1     1      0    1      1       0       1
   1     1     1      1     1     1      1    1      0

Example:

A = %10100
B = %01001
operation : XOR
result = %10100 xor %01001 = %10101



DWord (type)

This type defines a 32 bit unsigned integer.

type DWord = Cardinal;




                              Memory functions

procedure memcpy (var src, dst; size : DWord);

Copies a number of bytes between src and dst.

Description
Copies size bytes between src and dst. No range checking is performed and
it can handle overlapping memory areas correclty. A speed gain of up to
100% compared to go32.move() on Intel Pentiums is archieved by using 64 bit
floating point registers for copying.

See also
seg_memcpy




procedure memsetB (var x; size : DWord; value : Byte);

procedure memsetW (var x; size : DWord; value : Word);

procedure memsetD (var x; size : DWord; value : DWord);

Sets a number of bytes to a specific value.

Description
Sets size bytes beginning from x to the value value. No range checking is
performed, so the use of the sizeof() operator is recommened. Uses 64 bit
FPU registers for fast memory fill.
The difference between the three routines is the size of the value
argument. The one fills the memory with a Byte value, the other with a Word
value and the last with a DWord value.

See also
seg_memset*




procedure memchange (var src, dst; size : DWord; op : Mem_Op);

Does a boolean operation between two memory areas

Description
Combines size bytes of src and dst via the boolean operation op and stores
the result in dst. The boolean operation is applied on a bit to bit basis.
Automatically uses MMX extensions if available for speed enhancement. No
range checking is performed, so it is recommened to use the sizeof()
operator. When the src and dst memory area overlap the result is undefined.

See also
Mem_Op
seg_memchange




procedure memchangeValueB (var x; size : DWord; value : Byte; op : Mem_Op);

procedure memchangeValueW (var x; size : DWord; value : Word; op : Mem_Op);

procedure memchangeValueD (var x; size : DWord; value : DWord; op :
Mem_Op);

Does a boolean operation between a value and a memory area

Description
Combines size bytes of value and x via the selected boolean operation in op
and stores the result in x. Automatically uses MMX extensions when
available. No range checking is performed, so the use of the sizeof()
operator is recommened. The difference between the three procedures is the
size of the value, either Byte, Word or DWord.

See also
Mem_Op
seg_memchangeValue*



procedure seg_memcpy (srcsel : Word; srcofs : DWord; dstsel : Word; dstofs
: Dword; size : DWord);

Copies bytes from src to dst across selector boundaries.

Description
This procedure does the same as memcpy, except that the src and dst may
reside in different memory segments or outside the DS selector range.

See also
memcpy



procedure seg_memsetB (sel : Word; ofs : DWord; size : DWord; value : Byte);

procedure seg_memsetW (sel : Word; ofs : DWord; size : DWord; value :
Word);
procedure seg_memsetD (sel : Word; ofs : DWord; size : DWord; value :
DWord);

Sets size bytes across selector boundaries.

Description
This procedure does the same as memset*, except that the memory may reside
outside the DS selector range.

See also
memset*




procedure seg_memchange (srcsel : Word; srcofs : DWord; dstsel : Word;
dstofs : DWord; size : DWord);

Combines two memory areas by a boolean operation which aren't in the DS
selector range

Description
This procedure does the same as memchange, except that the memory areas may
reside outside the DS selector range or be in different memory areas.

See also
memchange
Mem_Op




procedure seg_memchangeValueB (sel : Word; ofs : DWord; size : DWord; value
: Byte; op : Mem_Op);

procedure seg_memchangeValueW (sel : Word; ofs : DWord; size : DWord; value
: Word; op : Mem_Op);

procedure seg_memchangeValueD (sel : Word; ofs : DWord; size : DWord; value
: DWord; op : Mem_Op);

 Combines a memory area with a value by a boolean operation which is
outside the DS selector range.

Description
This procedure does the same as memchangeValue*, except that the memory
area may reside outside the DS selector range.

See also
memchangeValue*
Mem_Op



  ------------------------------------------------------------------------

          If you have any questions or feedback then e-mail me at
          tom_at_work@geocities.com.

Last update : 02.01.1999
  ------------------------------------------------------------------------
