uses crt;
{ $ASMMODE INTEL}
{$i386_intel}
function cpuid_support : boolean;assembler;
{
Check if the ID-flag can be changed, if changed then CpuID is supported.
Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
}
asm
pushf
pushf
pop eax
mov ebx,eax
xor eax,200000h
push eax
popf
pushf
pop eax
popf
and eax,200000h
and ebx,200000h
cmp eax,ebx
setnz al
end;
function cr0 : longint;assembler;
asm
DB 0Fh,20h,0C0h
{ mov eax,cr0
special registers are not allowed in the assembler
parsers }
end;
function cpuidax(par:longword):longword; assembler; asm
mov eax,par
DB 00fh, 0a2h
mov eax,eax
end;
function cpuidbx(par:longword):longword; assembler; asm
mov eax,par
DB 00fh, 0a2h
mov eax,ebx
end;
function cpuidcx(par:longword):longword; assembler; asm
mov eax,par
DB 00fh, 0a2h
mov eax,ecx
end;
function cpuiddx(par:longword):longword; assembler; asm
mov eax,par
DB 00fh, 0a2h
mov eax,edx
end;
function eflags: longword; assembler; asm
pushf
pop eax
end;
CONST
desc:array[0..31] of string=(
// vol2a, table 3-16, page 217/750. EDX(1)
{ 0} 'Floating Point Unit On-Chip.',
{ 1} 'Virtual 8086 Mode Enhancements.',
{ 2} 'Debugging Extensions.',
{ 3} 'Page Size Extension.',
{ 4} 'Time Stamp Counter.',
{ 5} 'Model Specific Registers RDMSR and WRMSR Instructions.',
{ 6} 'Physical Address Extension.',
{ 7} 'Machine Check Exception.',
{ 8} 'CMPXCHG8B Instruction.',
{ 9} 'APIC On-Chip.',
{10} 'Reserved',
{11} 'SYSENTER and SYSEXIT Instructions.',
{12} 'Memory Type Range Registers.',
{13} 'PTE Global Bit.',
{14} 'Machine Check Architecture.',
{15} 'Conditional Move Instructions.',
{16} 'Page Attribute Table.',
{17} '36-Bit Page Size Extension.',
{18} 'Processor Serial Number.',
{19} 'CLFLUSH Instruction.',
{20} 'Reserved',
{21} 'Debug Store.',
{22} 'Thermal Monitor and Software Controlled Clock Facilities.',
{23} 'Intel MMX Technology.',
{24} 'FXSAVE and FXRSTOR Instructions.',
{25} 'SSE.',
{26} 'SSE2.',
{27} 'Self Snoop.',
{28} 'Multi-Threading.',
{29} 'Thermal Monitor.',
{30} 'Reserved',
{31} 'Pending Break Enable.');
procedure cpuid4(par:longword);
begin
writeln(
par:8, #32,
hexstr(cpuidax(par),8), #32,
hexstr(cpuidbx(par),8), #32,
hexstr(cpuidcx(par),8), #32,
hexstr(cpuiddx(par),8), #32);
end;
procedure opis;
var x,i:longword;
begin
writeln('EFLAG ', hexstr(eflags, 8));
writeln('--------.---AX--- ---BX--- ---CX--- ---DX---');
for x:=0 to cpuidax(0) do
cpuid4(x);
x:=cpuidbx(0);
while x>0 do begin
write(char(x mod 256));
x:=x div 256
end;
x:=cpuiddx(0);
while x>0 do begin
write(char(x mod 256));
x:=x div 256
end;
x:=cpuidcx(0);
while x>0 do begin
write(char(x mod 256));
x:=x div 256
end;
writeln; writeln;
writeln('------- Supported -------');
x:=cpuiddx(1);
for i:=0 to 31 do begin
if odd(x) then writeln(desc[i]);
x:=x shr 1
end;
writeln;
writeln('----- NOT suported ------');
x:=cpuiddx(1);
for i:=0 to 31 do begin
if not odd(x) then writeln(desc[i]);
x:=x shr 1
end;
writeln;
end;
function rdtsc:qword; assembler; asm
rdtsc
end;
function GetTickCount : longint; external 'kernel32' name 'GetTickCount';
type pqword=^qword;
function qpc(q: pqword):boolean; external
'kernel32' name 'QueryPerformanceCounter';
function qpf(q: pqword):boolean; external
'kernel32' name 'QueryPerformanceFrequency';
var x,a,cp,ck:longword; p,k,s: qword;
begin writeln;
(*
p:=rdtsc; writeln(p);
opis;
k:=rdtsc; writeln(k);
writeln(k-p);
p:=69;
if qpf(addr(p)) then
writeln('Frequency = ',p/1e6:0:3,' MHz, ',1/p*1e6:20:15, ' uS');
writeln;
s:=0;
for x:=1 to 32 do begin
p:=rdtsc(); cp:=gettickcount();
delay(1000);
k:=rdtsc(); ck:=gettickcount();
s+=k-p;
writeln(k-p:16, ' ticks, ', s div x:12, ' aver, ', ck-cp:8, ' mS (circa)');
end;
writeln;
writeln((s div x) div (ck-cp):10);
*)
cp:=gettickcount(); while gettickcount=cp do;
cp:=gettickcount(); while gettickcount=cp do;
cp:=gettickcount();
ck:=cp+1000;
p:=rdtsc;
while gettickcount()<ck do
;
k:=rdtsc;
ck:=gettickcount;
writeln( (k-p)/1e6:0:3, ' milions ticks');
writeln(((k-p) / (ck-cp)*1e3)/1e6 :20:6, ' MHz');
//if cpuiD_support then writeln(hexstr(cr0,8))
end.