int64p.inc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. movl %ebp,%edx
  29. movl $200,%eax
  30. call HandleErrorFrame
  31. jmp .Lexit
  32. .Lnodivzero:
  33. movl z+4,%edx
  34. movl z,%eax
  35. testl %ecx,%ecx
  36. jnz .Lqworddivbigdivisor
  37. cmpl %ebx,%edx
  38. jae .Lqworddivtwo_divs
  39. divl %ebx
  40. movl %ecx,%edx
  41. jmp .Lexit
  42. .Lqworddivtwo_divs:
  43. movl %eax,%ecx
  44. movl %edx,%eax
  45. xorl %edx,%edx
  46. divl %ebx
  47. xchgl %ecx,%eax
  48. divl %ebx
  49. movl %ecx,%edx
  50. jmp .Lexit
  51. .Lqworddivbigdivisor:
  52. movl %ecx,%edi
  53. shrl $1,%edx
  54. rcrl $1,%eax
  55. rorl $1,%edi
  56. rcrl $1,%ebx
  57. bsrl %ecx,%ecx
  58. shrdl %cl,%edi,%ebx
  59. shrdl %cl,%edx,%eax
  60. shrl %cl,%edx
  61. roll $1,%edi
  62. divl %ebx
  63. movl z,%ebx
  64. movl %eax,%ecx
  65. imull %eax,%edi
  66. mull n
  67. addl %edi,%edx
  68. subl %eax,%ebx
  69. movl %ecx,%eax
  70. movl z+4,%ecx
  71. sbbl %edx,%ecx
  72. sbbl $0,%eax
  73. xorl %edx,%edx
  74. .Lexit:
  75. movl saveebx,%ebx
  76. movl saveedi,%edi
  77. end;
  78. {$define FPC_SYSTEM_HAS_MOD_QWORD}
  79. function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc;
  80. var
  81. shift,lzz,lzn : longint;
  82. saveebx,saveedi : longint;
  83. asm
  84. movl %ebx,saveebx
  85. movl %edi,saveedi
  86. { the following piece of code is taken from the }
  87. { AMD Athlon Processor x86 Code Optimization manual }
  88. movl n+4,%ecx
  89. movl n,%ebx
  90. movl %ecx,%eax
  91. orl %ebx,%eax
  92. jnz .Lnodivzero
  93. movl %ebp,%edx
  94. movl $200,%eax
  95. call HandleErrorFrame
  96. jmp .Lexit
  97. .Lnodivzero:
  98. movl z+4,%edx
  99. movl z,%eax
  100. testl %ecx,%ecx
  101. jnz .Lqwordmodr_big_divisior
  102. cmpl %ebx,%edx
  103. jae .Lqwordmodr_two_divs
  104. divl %ebx
  105. movl %edx,%eax
  106. movl %ecx,%edx
  107. jmp .Lexit
  108. .Lqwordmodr_two_divs:
  109. movl %eax,%ecx
  110. movl %edx,%eax
  111. xorl %edx,%edx
  112. divl %ebx
  113. movl %ecx,%eax
  114. divl %ebx
  115. movl %edx,%eax
  116. xorl %edx,%edx
  117. jmp .Lexit
  118. .Lqwordmodr_big_divisior:
  119. movl %ecx,%edi
  120. shrl $1,%edx
  121. rcrl $1,%eax
  122. rorl $1,%edi
  123. rcrl $1,%ebx
  124. bsrl %ecx,%ecx
  125. shrdl %cl,%edi,%ebx
  126. shrdl %cl,%edx,%eax
  127. shrl %cl,%edx
  128. roll $1,%edi
  129. divl %ebx
  130. movl z,%ebx
  131. movl %eax,%ecx
  132. imull %eax,%edi
  133. mull n
  134. addl %edi,%edx
  135. subl %eax,%ebx
  136. movl z+4,%ecx
  137. movl n,%eax
  138. sbbl %edx,%ecx
  139. sbbl %edx,%edx
  140. andl %edx,%eax
  141. andl n+4,%edx
  142. addl %ebx,%eax
  143. adcl %ecx,%edx
  144. .Lexit:
  145. movl saveebx,%ebx
  146. movl saveedi,%edi
  147. end;
  148. {$define FPC_SYSTEM_HAS_MUL_QWORD}
  149. { multiplies two qwords
  150. the longbool for checkoverflow avoids a misaligned stack
  151. }
  152. function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; compilerproc;
  153. var
  154. r : qword;
  155. overflowed : boolean;
  156. begin
  157. overflowed:=false;
  158. { the following piece of code is taken from the
  159. AMD Athlon Processor x86 Code Optimization manual }
  160. asm
  161. movl f1+4,%edx
  162. movl f2+4,%ecx
  163. cmpl $0,checkoverflow
  164. jnz .Loverflowchecked
  165. orl %ecx,%edx
  166. movl f2,%edx
  167. movl f1,%eax
  168. jnz .Lqwordmultwomul
  169. mull %edx
  170. jmp .Lqwordmulready
  171. .Lqwordmultwomul:
  172. imul f1+4,%edx
  173. imul %eax,%ecx
  174. addl %edx,%ecx
  175. mull f2
  176. add %ecx,%edx
  177. .Lqwordmulready:
  178. movl %eax,r
  179. movl %edx,r+4
  180. jmp .Lend
  181. .Loverflowchecked:
  182. { if both upper dwords are <>0 then it overflows always }
  183. or %ecx,%ecx
  184. jz .Loverok1
  185. or %edx,%edx
  186. jnz .Loverflowed
  187. .Loverok1:
  188. { overflow checked code }
  189. orl %ecx,%edx
  190. movl f2,%edi
  191. movl f1,%esi
  192. jnz .Lqwordmultwomul2
  193. movl %edi,%eax
  194. mull %esi
  195. movl %eax,%esi
  196. movl %edx,%edi
  197. jmp .Lqwordmulready2
  198. .Lqwordmultwomul2:
  199. movl f1+4,%eax
  200. mull %edi
  201. movl %eax,%edi
  202. jc .Loverflowed
  203. movl %esi,%eax
  204. mull %ecx
  205. movl %eax,%ecx
  206. jc .Loverflowed
  207. addl %edi,%ecx
  208. jc .Loverflowed
  209. movl f2,%eax
  210. mull %esi
  211. movl %eax,%esi
  212. movl %edx,%edi
  213. addl %ecx,%edi
  214. jc .Loverflowed
  215. .Lqwordmulready2:
  216. movl %esi,r
  217. movl %edi,r+4
  218. jmp .Lend
  219. .Loverflowed:
  220. movb $1,overflowed
  221. .Lend:
  222. end [ 'eax','edx','ecx','edi','esi' ];
  223. fpc_mul_qword:=r;
  224. if overflowed then
  225. HandleErrorFrame(215,get_frame);
  226. end;