2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A .file "ldivide.s"
2N/A
2N/A/ Double long divide routine.
2N/A
2N/A#include "SYS.h"
2N/A
2N/A .set lop,16
2N/A .set rop,24
2N/A .set ans,0
2N/A
2N/A ENTRY(ldivide)
2N/A popl %eax
2N/A xchgl %eax,0(%esp)
2N/A pushl %eax
2N/A
2N/A pushl %esi
2N/A pushl %edi
2N/A
2N/A movl lop(%esp),%eax
2N/A movl lop+4(%esp),%edx
2N/A
2N/A/ the following code is only for compatibility with original ldivide code
2N/A orl %edx,%edx / force numerator positive
2N/A jns .ldiv1
2N/A notl %edx
2N/A negl %eax
2N/A sbbl $0xffffffff,%edx
2N/A.ldiv1:
2N/A testl $0x80000000,rop+4(%esp)
2N/A jz .ldiv2
2N/A notl rop+4(%esp) / force denominator positive
2N/A negl rop(%esp)
2N/A sbbl $0xffffffff,rop+4(%esp)
2N/A.ldiv2:
2N/A/ end of compatibility code
2N/A
2N/A xorl %esi,%esi / initialize remainder to 0
2N/A movl %esi,%edi
2N/A movl $64,%ecx / initialize counter for 64-bits
2N/A.div_mod_loop:
2N/A shll $1,%edi
2N/A rcll $1,%esi / remainder * 2
2N/A shll $1,%eax
2N/A rcll $1,%edx / numerator * 2 (also quotient)
2N/A adcl $0,%edi / add in any carry from the shift
2N/A subl rop(%esp),%edi / subtract denominator from remainder
2N/A sbbl rop+4(%esp),%esi
2N/A incl %eax / turn on quotient bit for now
2N/A jnc .inc_remainder / inc didn't affect carry flag
2N/A/ can't subtract the denominator from the remainder, add it back
2N/A addl rop(%esp),%edi
2N/A adcl rop+4(%esp),%esi
2N/A decl %eax / turn quotient bit off
2N/A.inc_remainder:
2N/A loop .div_mod_loop
2N/A
2N/A/ at this point, %edx:%eax has the quotient and %edi:%esi has the remainder
2N/A popl %edi
2N/A popl %esi
2N/A movl %eax,%ecx
2N/A popl %eax
2N/A movl %ecx,ans(%eax)
2N/A movl %edx,ans+4(%eax)
2N/A ret
2N/A SET_SIZE(ldivide)