int64p.inc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. (*
  85. This does not work correctly
  86. {$define FPC_SYSTEM_HAS_MOD_QWORD}
  87. function fpc_mod_qword(n,z : qword) : qword;[public,alias: 'FPC_MOD_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  88. var
  89. shift,lzz,lzn : longint;
  90. saveebx,saveedi : longint;
  91. asm
  92. movl %ebx,saveebx
  93. movl %edi,saveedi
  94. { the following piece of code is taken from the }
  95. { AMD Athlon Processor x86 Code Optimization manual }
  96. movl n+4,%ecx
  97. movl n,%ebx
  98. movl %ecx,%eax
  99. orl %ebx,%eax
  100. jnz .Lnodivzero
  101. pushl %ebp
  102. pushl $200
  103. call HandleErrorFrame
  104. jmp .Lexit
  105. movl z+4,%edx
  106. movl z,%eax
  107. testl %ecx,%ecx
  108. jnz .Lqwordmodr_big_divisior
  109. cmpl %ebx,%edx
  110. jae .Lqwordmodr_two_divs
  111. divl %ebx
  112. movl %edx,%eax
  113. movl %ecx,%edx
  114. jmp .Lexit
  115. .Lqwordmodr_two_divs:
  116. movl %eax,%ecx
  117. movl %edx,%eax
  118. xorl %edx,%edx
  119. divl %ebx
  120. movl %ecx,%eax
  121. divl %ebx
  122. movl %edx,%eax
  123. xorl %edx,%edx
  124. jmp .Lexit
  125. .Lqwordmodr_big_divisior:
  126. movl %ecx,%edi
  127. shrl $1,%edx
  128. rcrl $1,%eax
  129. rorl $1,%edi
  130. rcrl $1,%ebx
  131. bsrl %ecx,%ecx
  132. shrdl %cl,%edi,%ebx
  133. shrdl %cl,%edx,%eax
  134. shrl %cl,%edx
  135. rorl $1,%edi
  136. divl %ebx
  137. movl z,%ebx
  138. movl %eax,%ecx
  139. imull %eax,%edi
  140. mull n
  141. addl %edi,%edx
  142. subl %eax,%ebx
  143. movl z+4,%ecx
  144. movl n,%eax
  145. sbbl %edx,%ecx
  146. sbbl %edx,%edx
  147. andl %edx,%eax
  148. andl n+4,%edx
  149. addl %ebx,%eax
  150. adcl %ecx,%edx
  151. .Lexit:
  152. movl saveebx,%ebx
  153. movl saveedi,%edi
  154. end;
  155. *)
  156. {$define FPC_SYSTEM_HAS_MUL_QWORD}
  157. { multiplies two qwords
  158. the longbool for checkoverflow avoids a misaligned stack
  159. }
  160. function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  161. var
  162. _f1,bitpos : qword;
  163. l : longint;
  164. r : qword;
  165. begin
  166. if not(checkoverflow) then
  167. begin
  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. orl %ecx,%edx
  174. movl f2,%edx
  175. movl f1,%eax
  176. jnz .Lqwordmultwomul
  177. mull %edx
  178. jmp .Lqwordmulready
  179. .Lqwordmultwomul:
  180. imul f1+4,%edx
  181. imul %eax,%ecx
  182. addl %edx,%ecx
  183. mull f2
  184. add %ecx,%edx
  185. .Lqwordmulready:
  186. movl %eax,r
  187. movl %edx,r+4
  188. end [ 'eax','edx','ecx' ];
  189. fpc_mul_qword:=r;
  190. end
  191. else
  192. begin
  193. fpc_mul_qword:=0;
  194. bitpos:=1;
  195. // store f1 for overflow checking
  196. _f1:=f1;
  197. for l:=0 to 63 do
  198. begin
  199. if (f2 and bitpos)<>0 then
  200. fpc_mul_qword:=fpc_mul_qword+f1;
  201. f1:=f1 shl 1;
  202. bitpos:=bitpos shl 1;
  203. end;
  204. { if one of the operands is greater than the result an }
  205. { overflow occurs }
  206. if checkoverflow and (_f1 <> 0) and (f2 <>0) and
  207. ((_f1>fpc_mul_qword) or (f2>fpc_mul_qword)) then
  208. HandleErrorFrame(215,get_frame);
  209. end;
  210. end;
  211. {
  212. $Log$
  213. Revision 1.2 2003-12-23 23:09:43 peter
  214. * fix call to handleerror for regcall
  215. Revision 1.1 2003/09/14 11:34:13 peter
  216. * moved int64 asm code to int64p.inc
  217. * save ebx,esi
  218. }