123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- {
- 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_INT64}
- function fpc_div_int64(n,z : int64) : int64;assembler;[public,alias: 'FPC_DIV_INT64']; compilerproc;
- var
- saveebx,saveedi,saveesi : longint;
- asm
- movl %ebx,saveebx
- movl %esi,saveesi
- 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
- movl %ebp,%edx
- movl $200,%eax
- call HandleErrorFrame
- jmp .Lexit
- .Lnodivzero:
- movl z+4,%edx
- movl z,%eax
- movl %ecx,%esi
- xorl %edx,%esi
- sarl $31,%esi
- movl %edx,%edi
- sarl $31,%edi
- xorl %edi,%eax
- xorl %edi,%edx
- subl %edi,%eax
- sbbl %edi,%edx
- movl %ecx,%edi
- sarl $31,%edi
- xorl %edi,%ebx
- xorl %edi,%ecx
- subl %edi,%ebx
- sbbl %edi,%ecx
- jnz .Lbigdivisor
- cmpl %ebx,%edx
- jae .Ltwo_divs
- divl %ebx
- movl %ecx,%edx
- xorl %esi,%eax
- xorl %esi,%edx
- subl %esi,%eax
- sbbl %esi,%edx
- jmp .Lexit
- .Ltwo_divs:
- movl %eax,%ecx
- movl %edx,%eax
- xorl %edx,%edx
- divl %ebx
- xchgl %ecx,%eax
- divl %ebx
- movl %ecx,%edx
- jmp .Lmake_sign
- .Lbigdivisor:
- subl $12,%esp
- movl %eax,(%esp)
- movl %ebx,4(%esp)
- movl %edx,8(%esp)
- 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 (%esp),%ebx
- movl %eax,%ecx
- imull %eax,%edi
- mull 4(%esp)
- addl %edi,%edx
- subl %eax,%ebx
- movl %ecx,%eax
- movl 8(%esp),%ecx
- sbbl %edx,%ecx
- sbbl $0,%eax
- xorl %edx,%edx
- addl $12,%esp
- .Lmake_sign:
- xorl %esi,%eax
- xorl %esi,%edx
- subl %esi,%eax
- sbbl %esi,%edx
- .Lexit:
- movl saveebx,%ebx
- movl saveesi,%esi
- movl saveedi,%edi
- end;
- {$define FPC_SYSTEM_HAS_MOD_INT64}
- function fpc_mod_int64(n,z : int64) : int64;assembler;[public,alias: 'FPC_MOD_INT64']; compilerproc;
- var
- saveebx,saveedi,saveesi : longint;
- asm
- movl %ebx,saveebx
- movl %esi,saveesi
- 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
- movl %ebp,%edx
- movl $200,%eax
- call HandleErrorFrame
- jmp .Lexit
- .Lnodivzero:
- movl z+4,%edx
- movl z,%eax
- movl %edx,%esi
- sarl $31,%esi
- movl %edx,%edi
- sarl $31,%edi
- xorl %edi,%eax
- xorl %edi,%edx
- subl %edi,%eax
- sbbl %edi,%edx
- movl %ecx,%edi
- sarl $31,%edi
- xorl %edi,%ebx
- xorl %edi,%ecx
- subl %edi,%ebx
- sbbl %edi,%ecx
- jnz .Lbig_divisor
- cmpl %ebx,%edx
- jae .Ltwo_divs
- divl %ebx
- movl %edx,%eax
- movl %ecx,%edx
- xorl %esi,%eax
- xorl %esi,%edx
- subl %esi,%eax
- sbbl %esi,%edx
- jmp .Lexit
- .Ltwo_divs:
- movl %eax,%ecx
- movl %edx,%eax
- xorl %edx,%edx
- divl %ebx
- movl %ecx,%eax
- divl %ebx
- movl %edx,%eax
- xorl %edx,%edx
- jmp .Lmake_sign
- .Lbig_divisor:
- subl $16,%esp
- movl %eax,(%esp)
- movl %ebx,4(%esp)
- movl %edx,8(%esp)
- movl %ecx,12(%esp)
- 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 (%esp),%ebx
- movl %eax,%ecx
- imull %eax,%edi
- mull 4(%esp)
- addl %edi,%edx
- subl %eax,%ebx
- movl 8(%esp),%ecx
- sbbl %edx,%ecx
- sbbl %eax,%eax
- movl 12(%esp),%edx
- andl %eax,%edx
- andl 4(%esp),%eax
- addl %ebx,%eax
- adcl %ecx,%edx
- addl $16,%esp
- .Lmake_sign:
- xorl %esi,%eax
- xorl %esi,%edx
- subl %esi,%eax
- sbbl %esi,%edx
- .Lexit:
- movl saveebx,%ebx
- movl saveesi,%esi
- movl saveedi,%edi
- end;
- {$define FPC_SYSTEM_HAS_DIV_QWORD}
- function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
- var
- saveebx,saveedi,saveesi : longint;
- asm
- movl %ebx,saveebx
- movl %esi,saveesi
- 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
- movl %ebp,%edx
- movl $200,%eax
- 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,%esi // save quotient to esi
- imull %eax,%edi
- mull n
- addl %edi,%edx
- setcb %cl // cl:edx:eax = 65 bits quotient*divisor
- movl z+4,%edi // edi:ebx = dividend
- subl %eax,%ebx
- movb $0,%al
- sbbl %edx,%edi
- sbbb %cl,%al
- sbbl $0,%esi
- xorl %edx,%edx
- movl %esi,%eax
- .Lexit:
- movl saveebx,%ebx
- movl saveesi,%esi
- 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
- 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
- movl %ebp,%edx
- movl $200,%eax
- 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
- imull %eax,%edi
- mull n
- addl %edi,%edx
- setcb %cl // cl:edx:eax = 65 bits quotient*divisor
- movl z+4,%edi
- subl %eax,%ebx // subtract (quotient*divisor) from dividend
- movb $0,%al
- sbbl %edx,%edi
- sbbb %cl,%al // if carry is set now, the quotient was off by 1,
- // and we need to add divisor to result
- movl n,%eax
- sbbl %edx,%edx
- andl %edx,%eax
- andl n+4,%edx
- addl %ebx,%eax
- adcl %edi,%edx
- .Lexit:
- movl saveebx,%ebx
- movl saveedi,%edi
- end;
- {$ifndef VER3_0}
- {$define FPC_SYSTEM_HAS_MUL_QWORD}
- function fpc_mul_qword(f1,f2 : qword) : qword;[public,alias: 'FPC_MUL_QWORD']; compilerproc;
- begin
- { 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
- orl %ecx,%edx
- movl f2,%edx
- movl f1,%eax
- jnz .Lqwordmultwomul
- { if both upper dwords are =0 then it cannot overflow }
- mull %edx
- jmp .Lqwordmulready
- .Lqwordmultwomul:
- imul f1+4,%edx
- imul %eax,%ecx
- addl %edx,%ecx
- mull f2
- add %ecx,%edx
- .Lqwordmulready:
- movl %eax,__RESULT
- movl %edx,__RESULT+4
- .Lend:
- end [ 'eax','edx','ecx'];
- end;
-
- function fpc_mul_qword_checkoverflow(f1,f2 : qword) : qword;[public,alias: 'FPC_MUL_QWORD_CHECKOVERFLOW']; compilerproc;
- var
- 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
- orl %ecx,%edx
- movl f2,%edx
- movl f1,%eax
- jnz .Loverflowchecked
- { if both upper dwords are =0 then it cannot overflow }
- mull %edx
- movl %eax,__RESULT
- movl %edx,__RESULT+4
- jmp .Lend
- .Loverflowchecked:
- { if both upper dwords are <>0 then it overflows always }
- or %ecx,%ecx
- jz .Loverok1
- cmpl $0,f1+4
- jnz .Loverflowed
- .Loverok1:
- { overflow checked code }
- movl f1+4,%eax
- mull f2
- movl %eax,%ecx
- jc .Loverflowed
- movl f1,%eax
- mull f2+4
- jc .Loverflowed
- addl %eax,%ecx
- jc .Loverflowed
- movl f2,%eax
- mull f1
- addl %ecx,%edx
- movl %eax,__RESULT
- movl %edx,__RESULT+4
- jnc .Lend
- .Loverflowed:
- movb $1,overflowed
- .Lend:
- end [ 'eax','edx','ecx'];
- if overflowed then
- HandleErrorFrame(215,get_frame);
- end;
- {$endif VER3_0}
|