Subsections

- 1 What is it about?
- 2 Saturation support
- 3 Restrictions of MMX support
- 4 Supported MMX operations
- 5 Optimizing MMX support

#
5 Intel MMX support

#
1 What is it about?

Free Pascal supports the new MMX (Multi-Media extensions) instructions of Intel processors. The idea of MMX is to process multiple data with one instruction, for example the processor can add simultaneously 4 words. To implement this efficiently, the Pascal language needs to be extended. So Free Pascal allows to add for example two `array[0..3] of word`, if MMX support is switched on. The operation is done by the `MMX` unit and allows people without assembler knowledge to take advantage of the MMX extensions.

Here is an example:

    uses
       MMX;   { include some predefined data types }

    const
       { tmmxword = array[0..3] of word;, declared by unit MMX }
       w1 : tmmxword = (111,123,432,4356);
       w2 : tmmxword = (4213,63456,756,4);

    var
       w3 : tmmxword;
       l : longint;

    begin
       if is_mmx_cpu then  { is_mmx_cpu is exported from unit mmx }
         begin
    {$mmx+}   { turn mmx on }
            w3:=w1+w2;
    {$mmx-}
         end
       else
         begin
            for i:=0 to 3 do
              w3[i]:=w1[i]+w2[i];
         end;
    end.

#
2 Saturation support

One important point of MMX is the support of saturated operations. If a operation would cause an overflow, the value stays at the highest or lowest possible value for the data type: If you use byte values you get normally 250+12=6. This is very annoying when doing color manipulations or changing audio samples, when you have to do a word add and check if the value is greater than 255. The solution is saturation: 250+12 gives 255. Saturated operations are supported by the `MMX` unit. If you want to use them, you have simple turn the switch saturation on: `$saturation+`

Here is an example:

    Program SaturationDemo;
    {
      example for saturation, scales data (for example audio)
      with 1.5 with rounding to negative infinity
    }
    uses mmx;

    var
       audio1 : tmmxword;
       i: smallint;

    const
       helpdata1 : tmmxword = ($c000,$c000,$c000,$c000);
       helpdata2 : tmmxword = ($8000,$8000,$8000,$8000);

    begin
       { audio1 contains four 16 bit audio samples }
    {$mmx+}
       { convert it to $8000 is defined as zero, multiply data with 0.75 }
       audio1:=(audio1+helpdata2)*(helpdata1);
    {$saturation+}
       { avoid overflows (all values>$7fff becomes $ffff) }
       audio1:=(audio1+helpdata2)-helpdata2;
    {$saturation-}
       { now mupltily with 2 and change to integer }
       for i:=0 to 3 do
         audio1[i] := audio1[i] shl 1;
       audio1:=audio1-helpdata2;
    {$mmx-}
    end.

#
3 Restrictions of MMX support

In the beginning of 1997 the MMX instructions were introduced in the Pentium processors, so multitasking systems wouldn't save the newly introduced MMX registers. To work around that problem, Intel mapped the MMX registers to the FPU register.

The consequence is that you can't mix MMX and floating point operations. After using MMX operations and before using floating point operations, you have to call the routine `EMMS` of the `MMX` unit. This routine restores the FPU registers.

Careful: The compiler doesn't warn if you mix floating point and MMX operations, so be careful.

The MMX instructions are optimized for multi media (what else?). So it isn't possible to perform each operation, some operations give a type mismatch, see section for the supported MMX operations

An important restriction is that MMX operations aren't range or overflow checked, even when you turn range and overflow checking on. This is due to the nature of MMX operations.

The `MMX` unit must always be used when doing MMX operations because the exit code of this unit clears the MMX unit. If it wouldn't do that, other program will crash. A consequence of this is that you can't use MMX operations in the exit code of your units or programs, since they would interfere with the exit code of the `MMX` unit. The compiler can't check this, so you are responsible for this!

#
4 Supported MMX operations

The following operations are supported in the compiler when MMX extensions are enabled:

- addition (`+`)
- subtraction (`-`)
- multiplication(`*`)
- logical exclusive or (`xor`)
- logical and (`and`)
- logical or (`or`)
- sign change (`-`)

#
5 Optimizing MMX support

Here are some helpful hints to get optimal performance:

- The `EMMS` call takes a lot of time, so try to seperate floating point and MMX operations.
- Use MMX only in low level routines because the compiler saves all used MMX registers when calling a subroutine.
- The NOT-operator isn't supported natively by MMX, so the compiler has to generate a workaround and this operation is inefficient.
- Simple assignements of floating point numbers don't access floating point registers, so you need no call to the `EMMS` procedure. Only when doing arithmetic, you need to call the `EMMS` procedure.