int64p.inc 7.4 KB

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