123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by the Free Pascal development team
- This file contains some helper routines for int64 and qword
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$Q- no overflow checking }
- {$R- no range checking }
- {$define FPC_SYSTEM_HAS_DIV_QWORD}
- function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
- var
- shift,lzz,lzn : longint;
- saveebx,saveedi : longint;
- asm
- movl %ebx,saveebx
- movl %edi,saveedi
- { the following piece of code is taken from the }
- { AMD Athlon Processor x86 Code Optimization manual }
- movl n+4,%ecx
- movl n,%ebx
- movl %ecx,%eax
- orl %ebx,%eax
- jnz .Lnodivzero
- {$ifdef REGCALL}
- movl %ebp,%edx
- movl $200,%eax
- {$else}
- pushl %ebp
- pushl $200
- {$endif}
- call HandleErrorFrame
- jmp .Lexit
- .Lnodivzero:
- movl z+4,%edx
- movl z,%eax
- testl %ecx,%ecx
- jnz .Lqworddivbigdivisor
- cmpl %ebx,%edx
- jae .Lqworddivtwo_divs
- divl %ebx
- movl %ecx,%edx
- jmp .Lexit
- .Lqworddivtwo_divs:
- movl %eax,%ecx
- movl %edx,%eax
- xorl %edx,%edx
- divl %ebx
- xchgl %ecx,%eax
- divl %ebx
- movl %ecx,%edx
- jmp .Lexit
- .Lqworddivbigdivisor:
- movl %ecx,%edi
- shrl $1,%edx
- rcrl $1,%eax
- rorl $1,%edi
- rcrl $1,%ebx
- bsrl %ecx,%ecx
- shrdl %cl,%edi,%ebx
- shrdl %cl,%edx,%eax
- shrl %cl,%edx
- roll $1,%edi
- divl %ebx
- movl z,%ebx
- movl %eax,%ecx
- imull %eax,%edi
- mull n
- addl %edi,%edx
- subl %eax,%ebx
- movl %ecx,%eax
- movl z+4,%ecx
- sbbl %edx,%ecx
- sbbl $0,%eax
- xorl %edx,%edx
- .Lexit:
- movl saveebx,%ebx
- movl saveedi,%edi
- end;
- {$define FPC_SYSTEM_HAS_MOD_QWORD}
- function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc;
- var
- shift,lzz,lzn : longint;
- saveebx,saveedi : longint;
- asm
- movl %ebx,saveebx
- movl %edi,saveedi
- { the following piece of code is taken from the }
- { AMD Athlon Processor x86 Code Optimization manual }
- movl n+4,%ecx
- movl n,%ebx
- movl %ecx,%eax
- orl %ebx,%eax
- jnz .Lnodivzero
- {$ifdef REGCALL}
- movl %ebp,%edx
- movl $200,%eax
- {$else}
- pushl %ebp
- pushl $200
- {$endif}
- call HandleErrorFrame
- jmp .Lexit
- .Lnodivzero:
- movl z+4,%edx
- movl z,%eax
- testl %ecx,%ecx
- jnz .Lqwordmodr_big_divisior
- cmpl %ebx,%edx
- jae .Lqwordmodr_two_divs
- divl %ebx
- movl %edx,%eax
- movl %ecx,%edx
- jmp .Lexit
- .Lqwordmodr_two_divs:
- movl %eax,%ecx
- movl %edx,%eax
- xorl %edx,%edx
- divl %ebx
- movl %ecx,%eax
- divl %ebx
- movl %edx,%eax
- xorl %edx,%edx
- jmp .Lexit
- .Lqwordmodr_big_divisior:
- movl %ecx,%edi
- shrl $1,%edx
- rcrl $1,%eax
- rorl $1,%edi
- rcrl $1,%ebx
- bsrl %ecx,%ecx
- shrdl %cl,%edi,%ebx
- shrdl %cl,%edx,%eax
- shrl %cl,%edx
- roll $1,%edi
- divl %ebx
- movl z,%ebx
- movl %eax,%ecx
- imull %eax,%edi
- mull n
- addl %edi,%edx
- subl %eax,%ebx
- movl z+4,%ecx
- movl n,%eax
- sbbl %edx,%ecx
- sbbl %edx,%edx
- andl %edx,%eax
- andl n+4,%edx
- addl %ebx,%eax
- adcl %ecx,%edx
- .Lexit:
- movl saveebx,%ebx
- movl saveedi,%edi
- end;
- {$define FPC_SYSTEM_HAS_MUL_QWORD}
- { multiplies two qwords
- the longbool for checkoverflow avoids a misaligned stack
- }
- function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; compilerproc;
- var
- r : qword;
- overflowed : boolean;
- begin
- overflowed:=false;
- { the following piece of code is taken from the
- AMD Athlon Processor x86 Code Optimization manual }
- asm
- movl f1+4,%edx
- movl f2+4,%ecx
- cmpl $0,checkoverflow
- jnz .Loverflowchecked
- orl %ecx,%edx
- movl f2,%edx
- movl f1,%eax
- jnz .Lqwordmultwomul
- mull %edx
- jmp .Lqwordmulready
- .Lqwordmultwomul:
- imul f1+4,%edx
- imul %eax,%ecx
- addl %edx,%ecx
- mull f2
- add %ecx,%edx
- .Lqwordmulready:
- movl %eax,r
- movl %edx,r+4
- jmp .Lend
- .Loverflowchecked:
- { if both upper dwords are <>0 then it overflows always }
- or %ecx,%ecx
- jz .Loverok1
- or %edx,%edx
- jnz .Loverflowed
- .Loverok1:
- { overflow checked code }
- orl %ecx,%edx
- movl f2,%edi
- movl f1,%esi
- jnz .Lqwordmultwomul2
- movl %edi,%eax
- mull %esi
- movl %eax,%esi
- movl %edx,%edi
- jmp .Lqwordmulready2
- .Lqwordmultwomul2:
- movl f1+4,%eax
- mull %edi
- movl %eax,%edi
- jc .Loverflowed
- movl %esi,%eax
- mull %ecx
- movl %eax,%ecx
- jc .Loverflowed
- addl %edi,%ecx
- jc .Loverflowed
- movl f2,%eax
- mull %esi
- movl %eax,%esi
- movl %edx,%edi
- addl %ecx,%edi
- jc .Loverflowed
- .Lqwordmulready2:
- movl %esi,r
- movl %edi,r+4
- jmp .Lend
- .Loverflowed:
- movb $1,overflowed
- .Lend:
- end [ 'eax','edx','ecx','edi','esi' ];
- fpc_mul_qword:=r;
- if overflowed then
- HandleErrorFrame(215,get_frame);
- end;
|