int64p.inc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. pushl %ebp
  100. pushl $200
  101. call HandleErrorFrame
  102. jmp .Lexit
  103. .Lnodivzero:
  104. movl z+4,%edx
  105. movl z,%eax
  106. testl %ecx,%ecx
  107. jnz .Lqwordmodr_big_divisior
  108. cmpl %ebx,%edx
  109. jae .Lqwordmodr_two_divs
  110. divl %ebx
  111. movl %edx,%eax
  112. movl %ecx,%edx
  113. jmp .Lexit
  114. .Lqwordmodr_two_divs:
  115. movl %eax,%ecx
  116. movl %edx,%eax
  117. xorl %edx,%edx
  118. divl %ebx
  119. movl %ecx,%eax
  120. divl %ebx
  121. movl %edx,%eax
  122. xorl %edx,%edx
  123. jmp .Lexit
  124. .Lqwordmodr_big_divisior:
  125. movl %ecx,%edi
  126. shrl $1,%edx
  127. rcrl $1,%eax
  128. rorl $1,%edi
  129. rcrl $1,%ebx
  130. bsrl %ecx,%ecx
  131. shrdl %cl,%edi,%ebx
  132. shrdl %cl,%edx,%eax
  133. shrl %cl,%edx
  134. roll $1,%edi
  135. divl %ebx
  136. movl z,%ebx
  137. movl %eax,%ecx
  138. imull %eax,%edi
  139. mull n
  140. addl %edi,%edx
  141. subl %eax,%ebx
  142. movl z+4,%ecx
  143. movl n,%eax
  144. sbbl %edx,%ecx
  145. sbbl %edx,%edx
  146. andl %edx,%eax
  147. andl n+4,%edx
  148. addl %ebx,%eax
  149. adcl %ecx,%edx
  150. .Lexit:
  151. movl saveebx,%ebx
  152. movl saveedi,%edi
  153. end;
  154. {$define FPC_SYSTEM_HAS_MUL_QWORD}
  155. { multiplies two qwords
  156. the longbool for checkoverflow avoids a misaligned stack
  157. }
  158. function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  159. var
  160. r : qword;
  161. overflowed : boolean;
  162. begin
  163. overflowed:=false;
  164. { the following piece of code is taken from the
  165. AMD Athlon Processor x86 Code Optimization manual }
  166. asm
  167. movl f1+4,%edx
  168. movl f2+4,%ecx
  169. cmpl $0,checkoverflow
  170. jnz .Loverflowchecked
  171. orl %ecx,%edx
  172. movl f2,%edx
  173. movl f1,%eax
  174. jnz .Lqwordmultwomul
  175. mull %edx
  176. jmp .Lqwordmulready
  177. .Lqwordmultwomul:
  178. imul f1+4,%edx
  179. imul %eax,%ecx
  180. addl %edx,%ecx
  181. mull f2
  182. add %ecx,%edx
  183. .Lqwordmulready:
  184. movl %eax,r
  185. movl %edx,r+4
  186. jmp .Lend
  187. .Loverflowchecked:
  188. { if both upper dwords are <>0 then it overflows always }
  189. or %ecx,%ecx
  190. jz .Loverok1
  191. or %edx,%edx
  192. jnz .Loverflowed
  193. .Loverok1:
  194. { overflow checked code }
  195. orl %ecx,%edx
  196. movl f2,%edi
  197. movl f1,%esi
  198. jnz .Lqwordmultwomul2
  199. movl %edi,%eax
  200. mull %esi
  201. movl %eax,%esi
  202. movl %edx,%edi
  203. jmp .Lqwordmulready2
  204. .Lqwordmultwomul2:
  205. movl f1+4,%eax
  206. mull %edi
  207. movl %eax,%edi
  208. jc .Loverflowed
  209. movl %esi,%eax
  210. mull %ecx
  211. movl %eax,%ecx
  212. jc .Loverflowed
  213. addl %edi,%ecx
  214. jc .Loverflowed
  215. movl f2,%eax
  216. mull %esi
  217. movl %eax,%esi
  218. movl %edx,%edi
  219. addl %ecx,%edi
  220. jc .Loverflowed
  221. .Lqwordmulready2:
  222. movl %esi,r
  223. movl %edi,r+4
  224. jmp .Lend
  225. .Loverflowed:
  226. movb $1,overflowed
  227. .Lend:
  228. end [ 'eax','edx','ecx','edi','esi' ];
  229. fpc_mul_qword:=r;
  230. if overflowed then
  231. HandleErrorFrame(215,get_frame);
  232. end;
  233. {
  234. $Log$
  235. Revision 1.5 2004-09-26 08:52:51 florian
  236. * fixed overflow checking in qword multiplication
  237. Revision 1.4 2004/07/25 11:50:39 florian
  238. * assembler version of mod_qword_word reactivated
  239. Revision 1.3 2004/05/10 20:58:20 florian
  240. * fpc_mul_qword uses always the assembler implementation
  241. Revision 1.2 2003/12/23 23:09:43 peter
  242. * fix call to handleerror for regcall
  243. Revision 1.1 2003/09/14 11:34:13 peter
  244. * moved int64 asm code to int64p.inc
  245. * save ebx,esi
  246. }