timeunit.pp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. {$MODE objfpc}
  2. {$ASMMODE intel}
  3. {$goto on}
  4. Unit timeunit;
  5. Interface
  6. Type
  7. TGetClockTics = Function : QWord;
  8. Var
  9. TimerResolution : Double;
  10. CPS : Double;
  11. GetClockTics : TGetClockTics;
  12. Implementation
  13. Var
  14. UseRDTSC : Boolean;
  15. Clk1Lo, Clk1Hi, Clk2Lo, Clk2Hi : DWord;
  16. Clk1, Clk2 : QWord;
  17. ClkDelta : QWord;
  18. CpuFlags : DWord;
  19. Function GetClockTics_RDTSC : QWord; Assembler;
  20. Asm
  21. rdtsc
  22. End;
  23. Function GetClockTics_LAME : QWord;
  24. Begin
  25. GetClockTics_LAME := MemL[$46C];
  26. End;
  27. Procedure DetectCPUSpeed_RDTSC;
  28. Begin
  29. {word absolute $46C}
  30. Asm
  31. mov di, fs:[046Ch]
  32. @@1:
  33. cmp di, fs:[046Ch]
  34. je @@1
  35. rdtsc
  36. mov ebx, eax
  37. mov ecx, edx
  38. mov di, fs:[046Ch]
  39. @@2:
  40. mov ax, fs:[046Ch]
  41. sub ax, di
  42. cmp ax, 32
  43. jb @@2
  44. rdtsc
  45. mov [Clk1Lo], ebx
  46. mov [Clk1Hi], ecx
  47. mov [Clk2Lo], eax
  48. mov [Clk2Hi], edx
  49. End ['EAX','EBX','ECX','EDX','EDI'];
  50. { Clk1 := Clk1Lo Or (QWord(Clk1Hi) Shl 32);
  51. Clk2 := Clk2Lo Or (QWord(Clk2Hi) Shl 32);}
  52. Clk1 := Clk1Hi;
  53. Clk1 := Clk1 Shl 32;
  54. Clk1 := Clk1 + Clk1Lo;
  55. Clk2 := Clk2Hi;
  56. Clk2 := Clk2 Shl 32;
  57. Clk2 := Clk2 + Clk2Lo;
  58. ClkDelta := Clk2 - Clk1;
  59. CPS := (ClkDelta * 18.2) / 32;
  60. TimerResolution := 1 / CPS;
  61. End;
  62. Procedure _CPU; Assembler;
  63. Label
  64. nocpuid;
  65. Asm
  66. mov CpuFlags, 0
  67. pushf
  68. pop eax
  69. mov ecx, eax
  70. xor eax, 40000h
  71. push eax
  72. popf
  73. pushf
  74. pop eax
  75. xor eax, ecx
  76. jz nocpuid
  77. push ecx
  78. popf
  79. mov eax, ecx
  80. xor eax, 200000h
  81. push eax
  82. popf
  83. pushf
  84. pop eax
  85. xor eax, ecx
  86. je nocpuid
  87. pusha
  88. mov eax, 1
  89. cpuid
  90. mov CpuFlags, edx
  91. popa
  92. nocpuid:
  93. End;
  94. Procedure DetectCPU;
  95. Begin
  96. _CPU;
  97. If (CpuFlags And $10) <> 0 Then
  98. UseRDTSC := True
  99. Else
  100. UseRDTSC := False;
  101. If UseRDTSC Then
  102. Begin
  103. DetectCPUSpeed_RDTSC;
  104. GetClockTics := @GetClockTics_RDTSC;
  105. End
  106. Else
  107. Begin
  108. TimerResolution := 1 / 18.2;
  109. GetClockTics := @GetClockTics_LAME;
  110. End;
  111. End;
  112. Initialization
  113. Begin
  114. DetectCPU;
  115. End;
  116. End.