{
IntelMMX – модуль для работы с расширением MMX процессоров Intel.
Copyright © 2016, 2019, 2022–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit IntelMMX;
{$MODE DELPHI}
{$ASMMODE INTEL}
interface
uses
Lang;
{%region public }
type
byteMMX = packed array [0..7] of byte;
shortMMX = packed array [0..3] of short;
intMMX = packed array [0..1] of int;
byteMMX_Array1d = packed array of byteMMX;
shortMMX_Array1d = packed array of shortMMX;
intMMX_Array1d = packed array of intMMX;
{%endregion}
{%region routine }
function mmxSupported(): boolean;
function toByteMMX(byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7: int): byteMMX; inline;
function toShortMMX(short0, short1, short2, short3: int): shortMMX; inline;
function toIntMMX(int0, int1: int): intMMX; inline;
function byteMMX_Array1d_create(length: int): byteMMX_Array1d;
function shortMMX_Array1d_create(length: int): shortMMX_Array1d;
function intMMX_Array1d_create(length: int): intMMX_Array1d;
function toByteMMXArray1d(const arr: array of byteMMX): byteMMX_Array1d; overload;
function toByteMMXArray1d(const arr: byte_Array1d): byteMMX_Array1d; overload;
function toByteMMXArray1d(const arr: byte_Array1d; offset, length: int): byteMMX_Array1d; overload;
function toShortMMXArray1d(const arr: array of shortMMX): shortMMX_Array1d; overload;
function toShortMMXArray1d(const arr: short_Array1d): shortMMX_Array1d; overload;
function toShortMMXArray1d(const arr: short_Array1d; offset, length: int): shortMMX_Array1d; overload;
function toIntMMXArray1d(const arr: array of intMMX): intMMX_Array1d; overload;
function toIntMMXArray1d(const arr: int_Array1d): intMMX_Array1d; overload;
function toIntMMXArray1d(const arr: int_Array1d; offset, length: int): intMMX_Array1d; overload;
function mulhMMX(const data1, data2: shortMMX): shortMMX;
function mullMMX(const data1, data2: shortMMX): shortMMX;
function umulhMMX(const data1, data2: shortMMX): shortMMX;
function salMMX(const data: shortMMX; bits: int): shortMMX; overload;
function salMMX(const data: intMMX; bits: int): intMMX; overload;
function sarMMX(const data: shortMMX; bits: int): shortMMX; overload;
function sarMMX(const data: intMMX; bits: int): intMMX; overload;
function shrMMX(const data: shortMMX; bits: int): shortMMX; overload;
function shrMMX(const data: intMMX; bits: int): intMMX; overload;
{%endregion}
procedure returnToFPU();
implementation
{%region routine }
function mmxSupported(): boolean; assembler;
asm
pushfd
or dword[esp+$00], $00200000
popfd
pushfd
pop eax
test eax, $00200000
jz @0
and eax, $ffdfffff
push eax
popfd
mov eax, $00000001
cpuid
test edx, $00800000
jz @0
mov eax, $00000001
ret
@0: xor eax, eax
end;
function toByteMMX(byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7: int): byteMMX; inline;
begin
result[0] := byte(byte0);
result[1] := byte(byte1);
result[2] := byte(byte2);
result[3] := byte(byte3);
result[4] := byte(byte4);
result[5] := byte(byte5);
result[6] := byte(byte6);
result[7] := byte(byte7);
end;
function toShortMMX(short0, short1, short2, short3: int): shortMMX; inline;
begin
result[0] := short(short0);
result[1] := short(short1);
result[2] := short(short2);
result[3] := short(short3);
end;
function toIntMMX(int0, int1: int): intMMX; inline;
begin
result[0] := int0;
result[1] := int1;
end;
function byteMMX_Array1d_create(length: int): byteMMX_Array1d;
begin
setLength(result, length);
end;
function shortMMX_Array1d_create(length: int): shortMMX_Array1d;
begin
setLength(result, length);
end;
function intMMX_Array1d_create(length: int): intMMX_Array1d;
begin
setLength(result, length);
end;
function toByteMMXArray1d(const arr: array of byteMMX): byteMMX_Array1d;
begin
result := byteMMX_Array1d_create(length(arr));
move(arr[0], result[0], length(result) * sizeof(byteMMX));
end;
function toByteMMXArray1d(const arr: byte_Array1d): byteMMX_Array1d;
begin
result := toByteMMXArray1d(arr, 0, length(arr));
end;
function toByteMMXArray1d(const arr: byte_Array1d; offset, length: int): byteMMX_Array1d;
var
lim: int;
len: int;
alen: int;
begin
lim := offset + length;
len := System.length(arr);
if (lim > len) or (lim < offset) or (offset < 0) or (offset > len) then begin
raise ArrayIndexOutOfBoundsException.create('toByteMMXArray1d: индекс элемента массива выходит из диапазона.');
end;
alen := length shr 3;
if (length and 7) <> 0 then begin
inc(alen);
end;
result := byteMMX_Array1d_create(alen);
move(arr[offset], result[0], length * sizeof(byte));
end;
function toShortMMXArray1d(const arr: array of shortMMX): shortMMX_Array1d;
begin
result := shortMMX_Array1d_create(length(arr));
move(arr[0], result[0], length(result) * sizeof(shortMMX));
end;
function toShortMMXArray1d(const arr: short_Array1d): shortMMX_Array1d;
begin
result := toShortMMXArray1d(arr, 0, length(arr));
end;
function toShortMMXArray1d(const arr: short_Array1d; offset, length: int): shortMMX_Array1d;
var
lim: int;
len: int;
alen: int;
begin
lim := offset + length;
len := System.length(arr);
if (lim > len) or (lim < offset) or (offset < 0) or (offset > len) then begin
raise ArrayIndexOutOfBoundsException.create('toShortMMXArray1d: индекс элемента массива выходит из диапазона.');
end;
alen := length shr 2;
if (length and 3) <> 0 then begin
inc(alen);
end;
result := shortMMX_Array1d_create(alen);
move(arr[offset], result[0], length * sizeof(short));
end;
function toIntMMXArray1d(const arr: array of intMMX): intMMX_Array1d;
begin
result := intMMX_Array1d_create(length(arr));
move(arr[0], result[0], length(result) * sizeof(intMMX));
end;
function toIntMMXArray1d(const arr: int_Array1d): intMMX_Array1d;
begin
result := toIntMMXArray1d(arr, 0, length(arr));
end;
function toIntMMXArray1d(const arr: int_Array1d; offset, length: int): intMMX_Array1d;
var
lim: int;
len: int;
alen: int;
begin
lim := offset + length;
len := System.length(arr);
if (lim > len) or (lim < offset) or (offset < 0) or (offset > len) then begin
raise ArrayIndexOutOfBoundsException.create('toIntMMXArray1d: индекс элемента массива выходит из диапазона.');
end;
alen := length shr 1;
if (length and 1) <> 0 then begin
inc(alen);
end;
result := intMMX_Array1d_create(alen);
move(arr[offset], result[0], length * sizeof(int));
end;
function mulhMMX(const data1, data2: shortMMX): shortMMX; assembler; nostackframe;
asm
movq mm0, [eax+$00]
pmulhw mm0, [edx+$00]
movq qword[ecx+$00], mm0
end;
function mullMMX(const data1, data2: shortMMX): shortMMX; assembler; nostackframe;
asm
movq mm0, [eax+$00]
pmullw mm0, [edx+$00]
movq qword[ecx+$00], mm0
end;
function umulhMMX(const data1, data2: shortMMX): shortMMX; assembler; nostackframe;
asm
movq mm0, [eax+$00]
pmulhuw mm0, [edx+$00]
movq qword[ecx+$00], mm0
end;
function salMMX(const data: shortMMX; bits: int): shortMMX; assembler; nostackframe;
asm
and edx, $0f
push dword $00
push edx
movq mm0, [eax+$00]
psllw mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
function salMMX(const data: intMMX; bits: int): intMMX; assembler; nostackframe;
asm
and edx, $1f
push dword $00
push edx
movq mm0, [eax+$00]
pslld mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
function sarMMX(const data: shortMMX; bits: int): shortMMX; assembler; nostackframe;
asm
and edx, $0f
push dword $00
push edx
movq mm0, [eax+$00]
psraw mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
function sarMMX(const data: intMMX; bits: int): intMMX; assembler; nostackframe;
asm
and edx, $1f
push dword $00
push edx
movq mm0, [eax+$00]
psrad mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
function shrMMX(const data: shortMMX; bits: int): shortMMX; assembler; nostackframe;
asm
and edx, $0f
push dword $00
push edx
movq mm0, [eax+$00]
psrlw mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
function shrMMX(const data: intMMX; bits: int): intMMX; assembler; nostackframe;
asm
and edx, $1f
push dword $00
push edx
movq mm0, [eax+$00]
psrld mm0, [esp+$00]
movq qword[ecx+$00], mm0
lea esp, [esp+$08]
end;
procedure returnToFPU();
asm
emms
end;
{%endregion}
end.