{ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ}
{Û                                                       Û}
{Û      Virtual Pascal Examples  Version 2.1             Û}
{Û      Implements high accuracy timer (Pentium Only)    Û}
{Û      ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÛ}
{Û      Copyright (C) 1998-2000 vpascal.com              Û}
{Û                                                       Û}
{ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}

{$Delphi+,H-,Use32+,G5+,Optimize+}

unit P5Timer;

interface

uses
  SysUtils;

type
  TQWord = Comp;

const
  // Modify this line to contain actual CPU speed
  CPUSpeed : TQWord = 400e6;

function tmCPUTicks: TQWord;
  // Get number of CPU ticks since machine was booted

function tmSecsElapsed(_Tick1, _Tick2: TQWord): Double;
  // Get difference between tick counts in milli-seconds

function tmElapsed(_Timer: Integer): Double;
  // Return current elapsed time in msecs

procedure tmStart(_Timer: Integer);
  // Start a timer

procedure tmPause(_Timer: Integer);
  // Pause a timer

function tmStop(_Timer: Integer): String;
  // Stop a timer; return elapsed time/msec as a formatted string

function tmElapsedStr(_Timer: Integer): String;
  // Return current elapsed time/msec as a formatted string

implementation

const
  cTimers = 4;
  lStart:   array[1..cTimers] of TQWord  = (0, 0, 0, 0);
  lElapsed: array[1..cTimers] of TQWord  = (0, 0, 0, 0);
  lPaused:  array[1..cTimers] of Boolean = (True, True, True, True);

procedure tmStart(_Timer: Integer);
begin
  asm
    push eax
  end;
  lPaused[_Timer] := False;
  lStart[_Timer]  := tmCPUTicks;
  asm
    pop eax
  end;
end;

procedure tmPause(_Timer: Integer);
begin
  asm
    push eax
  end;
  lPaused[_Timer]  := True;
  lElapsed[_Timer] := lElapsed[_Timer] + tmCPUTicks - lStart[_Timer];
  asm
    pop eax
  end;
end;

function tmElapsed(_Timer: Integer): Double;
var
  Ticks: TQWord;
begin
  if lPaused[_Timer] then
    Ticks := lElapsed[_Timer]
  else
    Ticks := lElapsed[_Timer] + tmCPUTicks - lStart[_Timer];
  Result := 1000*Ticks/CPUSpeed;
end;

function tmElapsedStr(_Timer: Integer): String;
begin
  Str(tmElapsed(_Timer):10:2, Result);
end;

function tmStop(_Timer: Integer): String;
begin
  Result := tmElapsedStr(_Timer);
  lElapsed[_Timer] := 0;
end;

function tmCPUTicks: TQWord; assembler; {&frame-} {&uses ecx,edx}
asm
  push   0
  push   0
  mov    ecx,esp
  rdtsc
  mov    [ecx+4],edx
  mov    [ecx],eax
  fild   qword ptr [ecx]
  pop    eax
  pop    eax
end;

function tmSecsElapsed(_Tick1, _Tick2: TQWord): Double;
begin
  Result := (Comp(_Tick2)-Comp(_Tick1)) / CPUSpeed;
end;

end.

