int64p.inc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. This file contains some helper routines for int64 and qword
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$Q- no overflow checking }
  12. {$R- no range checking }
  13. {$define FPC_SYSTEM_HAS_DIV_QWORD}
  14. function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
  15. var
  16. shift,lzz,lzn : longint;
  17. saveebx,saveedi : longint;
  18. asm
  19. movl %ebx,saveebx
  20. movl %edi,saveedi
  21. { the following piece of code is taken from the }
  22. { AMD Athlon Processor x86 Code Optimization manual }
  23. movl n+4,%ecx
  24. movl n,%ebx
  25. movl %ecx,%eax
  26. orl %ebx,%eax
  27. jnz .Lnodivzero
  28. {$ifdef REGCALL}
  29. movl %ebp,%edx
  30. movl $200,%eax
  31. {$else}
  32. pushl %ebp
  33. pushl $200
  34. {$endif}
  35. call HandleErrorFrame
  36. jmp .Lexit
  37. .Lnodivzero:
  38. movl z+4,%edx
  39. movl z,%eax
  40. testl %ecx,%ecx
  41. jnz .Lqworddivbigdivisor
  42. cmpl %ebx,%edx
  43. jae .Lqworddivtwo_divs
  44. divl %ebx
  45. movl %ecx,%edx
  46. jmp .Lexit
  47. .Lqworddivtwo_divs:
  48. movl %eax,%ecx
  49. movl %edx,%eax
  50. xorl %edx,%edx
  51. divl %ebx
  52. xchgl %ecx,%eax
  53. divl %ebx
  54. movl %ecx,%edx
  55. jmp .Lexit
  56. .Lqworddivbigdivisor:
  57. movl %ecx,%edi
  58. shrl $1,%edx
  59. rcrl $1,%eax
  60. rorl $1,%edi
  61. rcrl $1,%ebx
  62. bsrl %ecx,%ecx
  63. shrdl %cl,%edi,%ebx
  64. shrdl %cl,%edx,%eax
  65. shrl %cl,%edx
  66. roll $1,%edi
  67. divl %ebx
  68. movl z,%ebx
  69. movl %eax,%ecx
  70. imull %eax,%edi
  71. mull n
  72. addl %edi,%edx
  73. subl %eax,%ebx
  74. movl %ecx,%eax
  75. movl z+4,%ecx
  76. sbbl %edx,%ecx
  77. sbbl $0,%eax
  78. xorl %edx,%edx
  79. .Lexit:
  80. movl saveebx,%ebx
  81. movl saveedi,%edi
  82. end;
  83. {$define FPC_SYSTEM_HAS_MOD_QWORD}
  84. function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc;
  85. var
  86. shift,lzz,lzn : longint;
  87. saveebx,saveedi : longint;
  88. asm
  89. movl %ebx,saveebx
  90. movl %edi,saveedi
  91. { the following piece of code is taken from the }
  92. { AMD Athlon Processor x86 Code Optimization manual }
  93. movl n+4,%ecx
  94. movl n,%ebx
  95. movl %ecx,%eax
  96. orl %ebx,%eax
  97. jnz .Lnodivzero
  98. {$ifdef REGCALL}
  99. movl %ebp,%edx
  100. movl $200,%eax
  101. {$else}
  102. pushl %ebp
  103. pushl $200
  104. {$endif}
  105. call HandleErrorFrame
  106. jmp .Lexit
  107. .Lnodivzero:
  108. movl z+4,%edx
  109. movl z,%eax
  110. testl %ecx,%ecx
  111. jnz .Lqwordmodr_big_divisior
  112. cmpl %ebx,%edx
  113. jae .Lqwordmodr_two_divs
  114. divl %ebx
  115. movl %edx,%eax
  116. movl %ecx,%edx
  117. jmp .Lexit
  118. .Lqwordmodr_two_divs:
  119. movl %eax,%ecx
  120. movl %edx,%eax
  121. xorl %edx,%edx
  122. divl %ebx
  123. movl %ecx,%eax
  124. divl %ebx
  125. movl %edx,%eax
  126. xorl %edx,%edx
  127. jmp .Lexit
  128. .Lqwordmodr_big_divisior:
  129. movl %ecx,%edi
  130. shrl $1,%edx
  131. rcrl $1,%eax
  132. rorl $1,%edi
  133. rcrl $1,%ebx
  134. bsrl %ecx,%ecx
  135. shrdl %cl,%edi,%ebx
  136. shrdl %cl,%edx,%eax
  137. shrl %cl,%edx
  138. roll $1,%edi
  139. divl %ebx
  140. movl z,%ebx
  141. movl %eax,%ecx
  142. imull %eax,%edi
  143. mull n
  144. addl %edi,%edx
  145. subl %eax,%ebx
  146. movl z+4,%ecx
  147. movl n,%eax
  148. sbbl %edx,%ecx
  149. sbbl %edx,%edx
  150. andl %edx,%eax
  151. andl n+4,%edx
  152. addl %ebx,%eax
  153. adcl %ecx,%edx
  154. .Lexit:
  155. movl saveebx,%ebx
  156. movl saveedi,%edi
  157. end;
  158. {$define FPC_SYSTEM_HAS_MUL_QWORD}
  159. { multiplies two qwords
  160. the longbool for checkoverflow avoids a misaligned stack
  161. }
  162. function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; compilerproc;
  163. var
  164. r : qword;
  165. overflowed : boolean;
  166. begin
  167. overflowed:=false;
  168. { the following piece of code is taken from the
  169. AMD Athlon Processor x86 Code Optimization manual }
  170. asm
  171. movl f1+4,%edx
  172. movl f2+4,%ecx
  173. cmpl $0,checkoverflow
  174. jnz .Loverflowchecked
  175. orl %ecx,%edx
  176. movl f2,%edx
  177. movl f1,%eax
  178. jnz .Lqwordmultwomul
  179. mull %edx
  180. jmp .Lqwordmulready
  181. .Lqwordmultwomul:
  182. imul f1+4,%edx
  183. imul %eax,%ecx
  184. addl %edx,%ecx
  185. mull f2
  186. add %ecx,%edx
  187. .Lqwordmulready:
  188. movl %eax,r
  189. movl %edx,r+4
  190. jmp .Lend
  191. .Loverflowchecked:
  192. { if both upper dwords are <>0 then it overflows always }
  193. or %ecx,%ecx
  194. jz .Loverok1
  195. or %edx,%edx
  196. jnz .Loverflowed
  197. .Loverok1:
  198. { overflow checked code }
  199. orl %ecx,%edx
  200. movl f2,%edi
  201. movl f1,%esi
  202. jnz .Lqwordmultwomul2
  203. movl %edi,%eax
  204. mull %esi
  205. movl %eax,%esi
  206. movl %edx,%edi
  207. jmp .Lqwordmulready2
  208. .Lqwordmultwomul2:
  209. movl f1+4,%eax
  210. mull %edi
  211. movl %eax,%edi
  212. jc .Loverflowed
  213. movl %esi,%eax
  214. mull %ecx
  215. movl %eax,%ecx
  216. jc .Loverflowed
  217. addl %edi,%ecx
  218. jc .Loverflowed
  219. movl f2,%eax
  220. mull %esi
  221. movl %eax,%esi
  222. movl %edx,%edi
  223. addl %ecx,%edi
  224. jc .Loverflowed
  225. .Lqwordmulready2:
  226. movl %esi,r
  227. movl %edi,r+4
  228. jmp .Lend
  229. .Loverflowed:
  230. movb $1,overflowed
  231. .Lend:
  232. end [ 'eax','edx','ecx','edi','esi' ];
  233. fpc_mul_qword:=r;
  234. if overflowed then
  235. HandleErrorFrame(215,get_frame);
  236. end;