//PROFILE-NO
unit Procal;
{$O-}  // Do not remove! Delphi might crash !!!!
{$R-}
{$Q-}
{$A+}

interface
USES
  Windows;

TYPE
{$IFDEF VER90 }
  TMyComp  = Comp;
{$ELSE }
  {$IFDEF VER100 }
    TMyComp  = Comp;
  {$ELSE }
    TMyComp  = Int64;
  {$ENDIF }
{$ENDIF }
  TMyLargeInteger = RECORD
                    CASE Byte OF
                     0 : ( LowPart  : DWORD; HighPart : LongInt );
                     1 : ( QuadPart : TMyComp );
                  END;

FUNCTION TopFunction ( VAR index : Integer ) : TMyLargeInteger;
FUNCTION FunctionWith100( VAR index : Integer; loops : Integer ) : TMyLargeInteger;
FUNCTION FunctionWith1000( VAR index : Integer; loops : Integer ) : TMyLargeInteger;

VAR
  QPCAss : TMyLargeInteger; // Time used for PRTSC + mov + mov
implementation

VAR
  tsum   : TMyLargeInteger;

FUNCTION DeepFunction : Integer;
BEGIN
  Result := 0;
END;

FUNCTION MidFunction  : Integer;
VAR
  i : Integer;
BEGIN
  FOR i := 1 TO 10 DO
    Result := DeepFunction;
END;

FUNCTION TopFunction ( VAR index : Integer ) : TMyLargeInteger;
VAR
  i  : Integer;
  ta : TMyLargeInteger;
BEGIN
  asm
    DW 310FH;   // first PRTSC, get cycles before tested instruction
    mov ta.lowpart,eax
    mov ta.highpart,edx
  end;

  FOR i := 1 TO 10 DO
    index := MidFunction;
  Result.highpart := 0;
  Result.lowpart := 0;

  asm
    DW 310FH;   // get cycles after tested instructions
    // Next lines calculate the no of cycles now - no of cycles before first PRTSC
    sub eax,ta.lowpart
    sbb edx,ta.highpart
    // Next lines subtract no of cycles for the first PRTSC + mov instructions
    sub eax,QPCAss.lowpart
    sbb edx,QPCAss.highpart
    // = No of cycles for the measured instructions
    // stored in tsum
    mov tsum.lowpart,eax
    mov tsum.highpart,edx
  end;
  result.lowpart := tsum.lowpart;
END;

FUNCTION FunctionWith100( VAR index : Integer; loops : Integer ) : TMyLargeInteger;
VAR
  i  : Integer;
  ta : TMyLargeInteger;
BEGIN
  asm
    DW 310FH;   // first PRTSC, get cycles before tested instruction
    mov ta.lowpart,eax
    mov ta.highpart,edx
  end;

  FOR i := 1 TO loops DO
    index := index + 1;
  Result.lowpart  := 0;
  Result.highpart := 0;
  asm
    DW 310FH;   // get cycles after tested instructions
    // Next lines calculate the no of cycles now - no of cycles before first PRTSC
    sub eax,ta.lowpart
    sbb edx,ta.highpart
    // Next lines subtract no of cycles for the first PRTSC + mov instructions
    sub eax,QPCAss.lowpart
    sbb edx,QPCAss.highpart
    // = No of cycles for the measured instructions
    // stored in tsum
    mov tsum.lowpart,eax
    mov tsum.highpart,edx
  end;
  result.lowpart := tsum.lowpart;
END;

FUNCTION FunctionWith1000( VAR index : Integer; loops : Integer ) : TMyLargeInteger;
VAR
  i  : Integer;
  ta : TMyLargeInteger;
BEGIN
  asm
    DW 310FH;   // first PRTSC, get cycles before tested instruction
    mov ta.lowpart,eax
    mov ta.highpart,edx
  end;

  FOR i := 1 TO loops DO
    index := index + 1;
  Result.highpart := 0;
  Result.lowpart := 0;

  asm
    DW 310FH;   // get cycles after tested instructions
    // Next lines calculate the no of cycles now - no of cycles before first PRTSC
    sub eax,ta.lowpart
    sbb edx,ta.highpart
    // Next lines subtract no of cycles for the first PRTSC + mov instructions
    sub eax,QPCAss.lowpart
    sbb edx,QPCAss.highpart
    // = No of cycles for the measured instructions
    // stored in tsum
    mov tsum.lowpart,eax
    mov tsum.highpart,edx
  end;
  result.lowpart := tsum.lowpart;
END;

end.
