Shared.Int64Em.pas 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. unit Shared.Int64Em;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2025 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Declaration of the Integer64 type - which represents an *unsigned* 64-bit
  8. integer value - and functions for manipulating Integer64's.
  9. }
  10. interface
  11. type
  12. Integer64 = record
  13. Lo, Hi: LongWord;
  14. class operator Implicit(const A: Integer64): Int64;
  15. class operator Implicit(const A: Int64): Integer64;
  16. end;
  17. function Compare64(const N1, N2: Integer64): Integer;
  18. procedure Dec64(var X: Integer64; N: LongWord);
  19. function Div64(var X: Integer64; const Divisor: LongWord): LongWord;
  20. function Inc6464(var X: Integer64; const N: Integer64): Boolean;
  21. function Mod64(const X: Integer64; const Divisor: LongWord): LongWord;
  22. procedure Multiply32x32to64(N1, N2: LongWord; var X: Integer64);
  23. function StrToInteger64(const S: String; var X: Integer64): Boolean; overload;
  24. function StrToInteger64(const S: String; var X: Int64): Boolean; overload;
  25. implementation
  26. uses
  27. SysUtils;
  28. function Compare64(const N1, N2: Integer64): Integer;
  29. { If N1 = N2, returns 0.
  30. If N1 > N2, returns 1.
  31. If N1 < N2, returns -1. }
  32. asm
  33. { Compare high words }
  34. mov ecx, [eax+4]
  35. cmp ecx, [edx+4]
  36. ja @@return1
  37. jb @@returnminus1
  38. { High words equal; compare low words }
  39. mov ecx, [eax]
  40. cmp ecx, [edx]
  41. ja @@return1
  42. jb @@returnminus1
  43. jmp @@return0
  44. @@return1:
  45. xor eax, eax
  46. inc eax
  47. jmp @@exit
  48. @@returnminus1:
  49. or eax, -1
  50. jmp @@exit
  51. @@return0:
  52. xor eax,eax
  53. @@exit:
  54. end;
  55. procedure Dec64(var X: Integer64; N: LongWord);
  56. asm
  57. sub [eax], edx
  58. sbb dword ptr [eax+4], 0
  59. end;
  60. function Inc64(var X: Integer64; N: LongWord): Boolean;
  61. { Adds N to X. In case of overflow, False is returned. }
  62. asm
  63. add [eax], edx
  64. adc dword ptr [eax+4], 0
  65. setnc al
  66. end;
  67. function Inc6464(var X: Integer64; const N: Integer64): Boolean;
  68. { Adds N to X. In case of overflow, False is returned. }
  69. asm
  70. mov ecx, [edx]
  71. add [eax], ecx
  72. mov ecx, [edx+4]
  73. adc [eax+4], ecx
  74. setnc al
  75. end;
  76. procedure Multiply32x32to64(N1, N2: LongWord; var X: Integer64);
  77. { Multiplies two 32-bit unsigned integers together and places the result
  78. in X. }
  79. asm
  80. mul edx { Multiplies EAX by EDX, places 64-bit result in EDX:EAX }
  81. mov [ecx], eax
  82. mov [ecx+4], edx
  83. end;
  84. function Mul64(var X: Integer64; N: LongWord): Boolean;
  85. { Multiplies X by N, and overwrites X with the result. In case of overflow,
  86. False is returned (X is valid but truncated to 64 bits). }
  87. asm
  88. push esi
  89. push ebx
  90. mov esi, eax
  91. mov ecx, edx
  92. { Multiply high part }
  93. mov eax, [esi+4]
  94. mul ecx { CF set if resulting EDX <> 0 }
  95. setnc bl
  96. mov [esi+4], eax
  97. { Multiply low part, carry to high part }
  98. mov eax, [esi]
  99. mul ecx
  100. mov [esi], eax
  101. add [esi+4], edx { CF set on overflow }
  102. setnc al
  103. and al, bl
  104. pop ebx
  105. pop esi
  106. end;
  107. function Div64(var X: Integer64; const Divisor: LongWord): LongWord;
  108. { Divides X by Divisor, and overwrites X with the quotient. Returns the
  109. remainder. }
  110. asm
  111. push ebx
  112. push esi
  113. mov esi, eax
  114. mov ecx, edx
  115. mov eax, [esi]
  116. mov ebx, [esi+4]
  117. { Divide EBX:EAX by ECX. Quotient is stored in EBX:EAX, remainder in EDX. }
  118. xchg eax, ebx
  119. xor edx, edx
  120. div ecx
  121. xchg eax, ebx
  122. div ecx
  123. mov [esi], eax
  124. mov [esi+4], ebx
  125. mov eax, edx
  126. pop esi
  127. pop ebx
  128. end;
  129. function Mod64(const X: Integer64; const Divisor: LongWord): LongWord;
  130. { Divides X by Divisor and returns the remainder. Unlike Div64, X is left
  131. intact. }
  132. asm
  133. push ebx
  134. push esi
  135. mov esi, eax
  136. mov ecx, edx
  137. mov eax, [esi]
  138. mov ebx, [esi+4]
  139. { Divide EBX:EAX by ECX. Quotient is stored in EBX:EAX, remainder in EDX. }
  140. xchg eax, ebx
  141. xor edx, edx
  142. div ecx
  143. xchg eax, ebx
  144. div ecx
  145. mov eax, edx
  146. pop esi
  147. pop ebx
  148. end;
  149. function StrToInteger64(const S: String; var X: Integer64): Boolean;
  150. { Converts a string containing an unsigned decimal number, or hexadecimal
  151. number prefixed with '$', into an Integer64. Returns True if successful,
  152. or False if invalid characters were encountered or an overflow occurred.
  153. Supports digits separators. }
  154. var
  155. Len, Base, StartIndex, I: Integer;
  156. V: Integer64;
  157. C: Char;
  158. begin
  159. Result := False;
  160. Len := Length(S);
  161. Base := 10;
  162. StartIndex := 1;
  163. if Len > 0 then begin
  164. if S[1] = '$' then begin
  165. Base := 16;
  166. Inc(StartIndex);
  167. end else if S[1] = '_' then
  168. Exit;
  169. end;
  170. if (StartIndex > Len) or (S[StartIndex] = '_') then
  171. Exit;
  172. V := 0;
  173. for I := StartIndex to Len do begin
  174. C := UpCase(S[I]);
  175. case C of
  176. '0'..'9':
  177. begin
  178. if not Mul64(V, Base) then
  179. Exit;
  180. if not Inc64(V, Ord(C) - Ord('0')) then
  181. Exit;
  182. end;
  183. 'A'..'F':
  184. begin
  185. if Base <> 16 then
  186. Exit;
  187. if not Mul64(V, Base) then
  188. Exit;
  189. if not Inc64(V, Ord(C) - (Ord('A') - 10)) then
  190. Exit;
  191. end;
  192. '_':
  193. { Ignore }
  194. else
  195. Exit;
  196. end;
  197. end;
  198. X := V;
  199. Result := True;
  200. end;
  201. function StrToInteger64(const S: String; var X: Int64): Boolean;
  202. begin
  203. var X2: Integer64 := X;
  204. Result := StrToInteger64(S, X2);
  205. X := X2;
  206. end;
  207. { Integer64 }
  208. class operator Integer64.Implicit(const A: Int64): Integer64;
  209. begin
  210. Int64Rec(Result) := Int64Rec(A);
  211. end;
  212. class operator Integer64.Implicit(const A: Integer64): Int64;
  213. begin
  214. Int64Rec(Result) := Int64Rec(A);
  215. end;
  216. end.