blea.pp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. { %CPU=i386,x86_64 }
  2. program blea;
  3. {$IF not defined(CPUX86) and not defined(CPUX86_64)}
  4. {$FATAL This test program requires an Intel x86 or x64 processor }
  5. {$ENDIF}
  6. {$MODE OBJFPC}
  7. {$ASMMODE Intel}
  8. {$DEFINE DETECTCPU}
  9. uses
  10. SysUtils {$ifdef DETECTCPU}, CPU {$endif};
  11. type
  12. TBenchmarkProc = function(const Input, X, Y: LongWord): LongWord;
  13. function Checksum_PAS(const Input, X, Y: LongWord): LongWord;
  14. var
  15. Counter: LongWord;
  16. begin
  17. Result := Input;
  18. Counter := Y;
  19. while (Counter > 0) do
  20. begin
  21. Result := Result + X + $87654321;
  22. Result := Result xor Counter;
  23. Dec(Counter);
  24. end;
  25. end;
  26. function Checksum_ADD(const Input, X, Y: LongWord): LongWord; assembler; nostackframe;
  27. asm
  28. @Loop1:
  29. ADD Input, $87654321
  30. ADD Input, X
  31. XOR Input, Y
  32. DEC Y
  33. JNZ @Loop1
  34. MOV Result, Input
  35. end;
  36. function Checksum_LEA(const Input, X, Y: LongWord): LongWord; assembler; nostackframe;
  37. asm
  38. @Loop2:
  39. LEA Input, [Input + X - 2023406815] {+$87654321 in decimal}
  40. XOR Input, Y
  41. DEC Y
  42. JNZ @Loop2
  43. MOV Result, Input
  44. end;
  45. function Benchmark(const name: string; proc: TBenchmarkProc; Z, X: LongWord): LongWord;
  46. const
  47. internal_reps = 1000;
  48. var
  49. start: TDateTime;
  50. time: double;
  51. reps: cardinal;
  52. begin
  53. Result := Z;
  54. reps := 0;
  55. Write(name, ': ');
  56. start := Now;
  57. repeat
  58. inc(reps);
  59. Result := proc(Result, X, internal_reps);
  60. until (reps >= 100000);
  61. time := ((((Now - start) * SecsPerDay) * 1e9) / internal_reps) / reps;
  62. WriteLn(time:0:(2 * ord(time < 10)), ' ns/call');
  63. end;
  64. var
  65. Results: array[0..2] of LongWord;
  66. FailureCode: Integer;
  67. begin
  68. {$ifdef CPUX86_64}
  69. Write('64-bit');
  70. {$else CPUX86_64}
  71. Write('32-bit');
  72. {$endif CPUX86_64}
  73. {$ifdef DETECTCPU}
  74. if CPUBrandString <> '' then
  75. begin
  76. WriteLn(' CPU = ', CPUBrandString);
  77. WriteLn('-------------', StringOfChar('-', length(CPUBrandString)));
  78. end;
  79. {$else}
  80. WriteLn;
  81. {$endif}
  82. Results[0] := Benchmark(' Pascal control case', @Checksum_PAS, 5000000, 1000);
  83. Results[1] := Benchmark(' Using LEA instruction', @Checksum_LEA, 5000000, 1000);
  84. Results[2] := Benchmark('Using ADD instructions', @Checksum_ADD, 5000000, 1000);
  85. FailureCode := 0;
  86. if (Results[0] <> Results[1]) then
  87. begin
  88. WriteLn('ERROR: Checksum_LEA doesn''t match control case');
  89. FailureCode := FailureCode or 1;
  90. end;
  91. if (Results[0] <> Results[2]) then
  92. begin
  93. WriteLn('ERROR: Checksum_ADD doesn''t match control case');
  94. FailureCode := FailureCode or 2
  95. end;
  96. if FailureCode <> 0 then
  97. Halt(FailureCode);
  98. end.