import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / i386 / gen / ldivide.s
blob60fd7216eac7fd99bab2c82dd0f2f7b01f0ec470
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 .file "ldivide.s"
29 / Double long divide routine.
31 #include "SYS.h"
33 .set lop,16
34 .set rop,24
35 .set ans,0
37 ENTRY(ldivide)
38 popl %eax
39 xchgl %eax,0(%esp)
40 pushl %eax
42 pushl %esi
43 pushl %edi
45 movl lop(%esp),%eax
46 movl lop+4(%esp),%edx
48 / the following code is only for compatibility with original ldivide code
49 orl %edx,%edx / force numerator positive
50 jns .ldiv1
51 notl %edx
52 negl %eax
53 sbbl $0xffffffff,%edx
54 .ldiv1:
55 testl $0x80000000,rop+4(%esp)
56 jz .ldiv2
57 notl rop+4(%esp) / force denominator positive
58 negl rop(%esp)
59 sbbl $0xffffffff,rop+4(%esp)
60 .ldiv2:
61 / end of compatibility code
63 xorl %esi,%esi / initialize remainder to 0
64 movl %esi,%edi
65 movl $64,%ecx / initialize counter for 64-bits
66 .div_mod_loop:
67 shll $1,%edi
68 rcll $1,%esi / remainder * 2
69 shll $1,%eax
70 rcll $1,%edx / numerator * 2 (also quotient)
71 adcl $0,%edi / add in any carry from the shift
72 subl rop(%esp),%edi / subtract denominator from remainder
73 sbbl rop+4(%esp),%esi
74 incl %eax / turn on quotient bit for now
75 jnc .inc_remainder / inc didn't affect carry flag
76 / can't subtract the denominator from the remainder, add it back
77 addl rop(%esp),%edi
78 adcl rop+4(%esp),%esi
79 decl %eax / turn quotient bit off
80 .inc_remainder:
81 loop .div_mod_loop
83 / at this point, %edx:%eax has the quotient and %edi:%esi has the remainder
84 popl %edi
85 popl %esi
86 movl %eax,%ecx
87 popl %eax
88 movl %ecx,ans(%eax)
89 movl %edx,ans+4(%eax)
90 ret
91 SET_SIZE(ldivide)