362 lines
7.0 KiB
ObjectPascal
362 lines
7.0 KiB
ObjectPascal
unit Mmx;
|
|
{* MMX support unit. By Vladimir Kladov, 2003. }
|
|
|
|
interface
|
|
|
|
{$I KOLDEF.INC}
|
|
|
|
uses
|
|
Windows, Kol;
|
|
|
|
type
|
|
TCpuId = ( cpuNew486, cpuMMX, cpuMMX_Plus, cpu3DNow, cpu3DNow_Plus,
|
|
cpuSSE, cpuSSE2 );
|
|
{* Enumeration type to represent CPU type.
|
|
cpuOld486: Old 486 Processor and earlier
|
|
cpuNew486: New 486 Processor to Pentium1 without MMX
|
|
cpuMMX : MMX supported (but not SSE or SSE2)
|
|
cpuSSE : MMX and SSE supported (but not SSE2)
|
|
cpuSSE2 : MMX, SSE and SSE2 supported
|
|
}
|
|
|
|
TCpuCaps = set of TCpuId;
|
|
|
|
function GetCPUType: TCpuCaps;
|
|
{* Checks CPU (Intel PC x86 Architecture) for MMX support.
|
|
|<p><p>
|
|
|
|
Use following constants in shuffle commands (like "pshufw") as third operand
|
|
to instruct to which locations (0,1,2,3) source parts should be placed: }
|
|
const
|
|
SH0000 = $00;
|
|
SH0001 = $01;
|
|
SH0002 = $02;
|
|
SH0003 = $03;
|
|
SH0010 = $04;
|
|
SH0011 = $05;
|
|
SH0012 = $06;
|
|
SH0013 = $07;
|
|
SH0020 = $08;
|
|
SH0021 = $09;
|
|
SH0022 = $0A;
|
|
SH0023 = $0B;
|
|
SH0030 = $0C;
|
|
SH0031 = $0D;
|
|
SH0032 = $0E;
|
|
SH0033 = $0F;
|
|
SH0100 = $10;
|
|
SH0101 = $11;
|
|
SH0102 = $12;
|
|
SH0103 = $13;
|
|
SH0110 = $14;
|
|
SH0111 = $15;
|
|
SH0112 = $16;
|
|
SH0113 = $17;
|
|
SH0120 = $18;
|
|
SH0121 = $19;
|
|
SH0122 = $1A;
|
|
SH0123 = $1B;
|
|
SH0130 = $1C;
|
|
SH0131 = $1D;
|
|
SH0132 = $1E;
|
|
SH0133 = $1F;
|
|
SH0200 = $20;
|
|
SH0201 = $21;
|
|
SH0202 = $22;
|
|
SH0203 = $23;
|
|
SH0210 = $24;
|
|
SH0211 = $25;
|
|
SH0212 = $26;
|
|
SH0213 = $27;
|
|
SH0220 = $28;
|
|
SH0221 = $29;
|
|
SH0222 = $2A;
|
|
SH0223 = $2B;
|
|
SH0230 = $2C;
|
|
SH0231 = $2D;
|
|
SH0232 = $2E;
|
|
SH0233 = $2F;
|
|
SH0300 = $30;
|
|
SH0301 = $31;
|
|
SH0302 = $32;
|
|
SH0303 = $33;
|
|
SH0310 = $34;
|
|
SH0311 = $35;
|
|
SH0312 = $36;
|
|
SH0313 = $37;
|
|
SH0320 = $38;
|
|
SH0321 = $39;
|
|
SH0322 = $3A;
|
|
SH0323 = $3B;
|
|
SH0330 = $3C;
|
|
SH0331 = $3D;
|
|
SH0332 = $3E;
|
|
SH0333 = $3F;
|
|
SH1000 = $40;
|
|
SH1001 = $41;
|
|
SH1002 = $42;
|
|
SH1003 = $43;
|
|
SH1010 = $44;
|
|
SH1011 = $45;
|
|
SH1012 = $46;
|
|
SH1013 = $47;
|
|
SH1020 = $48;
|
|
SH1021 = $49;
|
|
SH1022 = $4A;
|
|
SH1023 = $4B;
|
|
SH1030 = $4C;
|
|
SH1031 = $4D;
|
|
SH1032 = $4E;
|
|
SH1033 = $4F;
|
|
SH1100 = $50;
|
|
SH1101 = $51;
|
|
SH1102 = $52;
|
|
SH1103 = $53;
|
|
SH1110 = $54;
|
|
SH1111 = $55;
|
|
SH1112 = $56;
|
|
SH1113 = $57;
|
|
SH1120 = $58;
|
|
SH1121 = $59;
|
|
SH1122 = $5A;
|
|
SH1123 = $5B;
|
|
SH1130 = $5C;
|
|
SH1131 = $5D;
|
|
SH1132 = $5E;
|
|
SH1133 = $5F;
|
|
SH1200 = $60;
|
|
SH1201 = $61;
|
|
SH1202 = $62;
|
|
SH1203 = $63;
|
|
SH1210 = $64;
|
|
SH1211 = $65;
|
|
SH1212 = $66;
|
|
SH1213 = $67;
|
|
SH1220 = $68;
|
|
SH1221 = $69;
|
|
SH1222 = $6A;
|
|
SH1223 = $6B;
|
|
SH1230 = $6C;
|
|
SH1231 = $6D;
|
|
SH1232 = $6E;
|
|
SH1233 = $6F;
|
|
SH1300 = $70;
|
|
SH1301 = $71;
|
|
SH1302 = $72;
|
|
SH1303 = $73;
|
|
SH1310 = $74;
|
|
SH1311 = $75;
|
|
SH1312 = $76;
|
|
SH1313 = $77;
|
|
SH1320 = $78;
|
|
SH1321 = $79;
|
|
SH1322 = $7A;
|
|
SH1323 = $7B;
|
|
SH1330 = $7C;
|
|
SH1331 = $7D;
|
|
SH1332 = $7E;
|
|
SH1333 = $7F;
|
|
SH2000 = $80;
|
|
SH2001 = $81;
|
|
SH2002 = $82;
|
|
SH2003 = $83;
|
|
SH2010 = $84;
|
|
SH2011 = $85;
|
|
SH2012 = $86;
|
|
SH2013 = $87;
|
|
SH2020 = $88;
|
|
SH2021 = $89;
|
|
SH2022 = $8A;
|
|
SH2023 = $8B;
|
|
SH2030 = $8C;
|
|
SH2031 = $8D;
|
|
SH2032 = $8E;
|
|
SH2033 = $8F;
|
|
SH2100 = $90;
|
|
SH2101 = $91;
|
|
SH2102 = $92;
|
|
SH2103 = $93;
|
|
SH2110 = $94;
|
|
SH2111 = $95;
|
|
SH2112 = $96;
|
|
SH2113 = $97;
|
|
SH2120 = $98;
|
|
SH2121 = $99;
|
|
SH2122 = $9A;
|
|
SH2123 = $9B;
|
|
SH2130 = $9C;
|
|
SH2131 = $9D;
|
|
SH2132 = $9E;
|
|
SH2133 = $9F;
|
|
SH2200 = $A0;
|
|
SH2201 = $A1;
|
|
SH2202 = $A2;
|
|
SH2203 = $A3;
|
|
SH2210 = $A4;
|
|
SH2211 = $A5;
|
|
SH2212 = $A6;
|
|
SH2213 = $A7;
|
|
SH2220 = $A8;
|
|
SH2221 = $A9;
|
|
SH2222 = $AA;
|
|
SH2223 = $AB;
|
|
SH2230 = $AC;
|
|
SH2231 = $AD;
|
|
SH2232 = $AE;
|
|
SH2233 = $AF;
|
|
SH2300 = $B0;
|
|
SH2301 = $B1;
|
|
SH2302 = $B2;
|
|
SH2303 = $B3;
|
|
SH2310 = $B4;
|
|
SH2311 = $B5;
|
|
SH2312 = $B6;
|
|
SH2313 = $B7;
|
|
SH2320 = $B8;
|
|
SH2321 = $B9;
|
|
SH2322 = $BA;
|
|
SH2323 = $BB;
|
|
SH2330 = $BC;
|
|
SH2331 = $BD;
|
|
SH2332 = $BE;
|
|
SH2333 = $BF;
|
|
SH3000 = $C0;
|
|
SH3001 = $C1;
|
|
SH3002 = $C2;
|
|
SH3003 = $C3;
|
|
SH3010 = $C4;
|
|
SH3011 = $C5;
|
|
SH3012 = $C6;
|
|
SH3013 = $C7;
|
|
SH3020 = $C8;
|
|
SH3021 = $C9;
|
|
SH3022 = $CA;
|
|
SH3023 = $CB;
|
|
SH3030 = $CC;
|
|
SH3031 = $CD;
|
|
SH3032 = $CE;
|
|
SH3033 = $CF;
|
|
SH3100 = $D0;
|
|
SH3101 = $D1;
|
|
SH3102 = $D2;
|
|
SH3103 = $D3;
|
|
SH3110 = $D4;
|
|
SH3111 = $D5;
|
|
SH3112 = $D6;
|
|
SH3113 = $D7;
|
|
SH3120 = $D8;
|
|
SH3121 = $D9;
|
|
SH3122 = $DA;
|
|
SH3123 = $DB;
|
|
SH3130 = $DC;
|
|
SH3131 = $DD;
|
|
SH3132 = $DE;
|
|
SH3133 = $DF;
|
|
SH3200 = $E0;
|
|
SH3201 = $E1;
|
|
SH3202 = $E2;
|
|
SH3203 = $E3;
|
|
SH3210 = $E4;
|
|
SH3211 = $E5;
|
|
SH3212 = $E6;
|
|
SH3213 = $E7;
|
|
SH3220 = $E8;
|
|
SH3221 = $E9;
|
|
SH3222 = $EA;
|
|
SH3223 = $EB;
|
|
SH3230 = $EC;
|
|
SH3231 = $ED;
|
|
SH3232 = $EE;
|
|
SH3233 = $EF;
|
|
SH3300 = $F0;
|
|
SH3301 = $F1;
|
|
SH3302 = $F2;
|
|
SH3303 = $F3;
|
|
SH3310 = $F4;
|
|
SH3311 = $F5;
|
|
SH3312 = $F6;
|
|
SH3313 = $F7;
|
|
SH3320 = $F8;
|
|
SH3321 = $F9;
|
|
SH3322 = $FA;
|
|
SH3323 = $FB;
|
|
SH3330 = $FC;
|
|
SH3331 = $FD;
|
|
SH3332 = $FE;
|
|
SH3333 = $FF;
|
|
|
|
implementation
|
|
|
|
var cpu: TCpuCaps = [ ];
|
|
|
|
function GetCPUType: TCpuCaps;
|
|
var I, J: Integer;
|
|
Vend1: array[ 0..3 ] of Char;
|
|
begin
|
|
Result := cpu; // old 486 and earlier
|
|
if Result <> [] then Exit;
|
|
I := 0;
|
|
asm // check if bit 21 of EFLAGS can be set and reset
|
|
PUSHFD
|
|
POP EAX
|
|
OR EAX, 1 shl 21
|
|
PUSH EAX
|
|
POPFD
|
|
PUSHFD
|
|
POP EAX
|
|
TEST EAX, 1 shl 21
|
|
JZ @@1
|
|
AND EAX, not( 1 shl 21 )
|
|
PUSH EAX
|
|
POPFD
|
|
PUSHFD
|
|
POP EAX
|
|
TEST EAX, 1 shl 21
|
|
JNZ @@1
|
|
INC [ I ]
|
|
@@1:
|
|
end;
|
|
if I = 0 then Exit; // CPUID not supported
|
|
Include( Result, cpuNew486 ); // at least cpuNew486
|
|
asm // get CPU features flags using CPUID command
|
|
PUSH EBX
|
|
MOV EAX, 0
|
|
DB $0F, $A2 //CPUID : EAX, EBX, EDX and ECX are changed!!!
|
|
MOV [ Vend1 ], EBX
|
|
|
|
MOV EAX, 1
|
|
DB $0F, $A2 //CPUID : EAX, EBX, EDX and ECX are changed!!!
|
|
MOV [ I ], EDX // I := features information
|
|
POP EBX
|
|
end;
|
|
if (I and (1 shl 23)) = 0 then Exit; // MMX not supported at all
|
|
Include( Result, cpuMMX ); // MMX supported.
|
|
if Vend1 = 'Auth' then // AuthenticAMD ?
|
|
begin
|
|
asm
|
|
PUSH EBX
|
|
MOV EAX, $80000001
|
|
DB $0F, $A2 //CPUID : EAX, EBX, EDX and ECX are changed!!!
|
|
MOV [ J ], EDX
|
|
POP EBX
|
|
end;
|
|
if (J and (1 shl 22)) <> 0 then
|
|
Include( Result, cpuMMX_Plus ); // MMX+ supported.
|
|
if (J and (1 shl 31)) <> 0 then
|
|
begin
|
|
Include( Result, cpu3DNow ); // 3DNow! supported.
|
|
if (J and (1 shl 30)) <> 0 then
|
|
Include( Result, cpu3DNow_Plus );// 3DNow!+ supported.
|
|
end;
|
|
end;
|
|
if (I and (1 shl 25)) <> 0 then
|
|
begin
|
|
Include( Result, cpuSSE ); // SSE supported.
|
|
if (I and (1 shl 26)) <> 0 then
|
|
Include( Result, cpuSSE2 ); // SSE2 supported.
|
|
end;
|
|
cpu := Result;
|
|
end;
|
|
|
|
end.
|