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 2005 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A .file "_divdi3.s"
2N/A
2N/A#include <SYS.h>
2N/A
2N/A/*
2N/A * C support for 64-bit modulo and division.
2N/A * GNU routines callable from C (though generated by the compiler).
2N/A * Hand-customized compiler output - see comments for details.
2N/A */
2N/A
2N/A#if defined(__lint)
2N/A
2N/A/*ARGSUSED*/
2N/Auint64_t
2N/A__udivdi3(uint64_t a, uint64_t b)
2N/A{ return (0); }
2N/A
2N/A/*ARGSUSED*/
2N/Auint64_t
2N/A__umoddi3(uint64_t a, uint64_t b)
2N/A{ return (0); }
2N/A
2N/A/*ARGSUSED*/
2N/Aint64_t
2N/A__divdi3(int64_t a, int64_t b)
2N/A{ return (0); }
2N/A
2N/A/*ARGSUSED*/
2N/Aint64_t
2N/A__moddi3(int64_t a, int64_t b)
2N/A{ return (0); }
2N/A
2N/A#else
2N/A
2N/A/*
2N/A * __udivdi3
2N/A *
2N/A * Perform division of two unsigned 64-bit quantities, returning the
2N/A * quotient in %edx:%eax.
2N/A */
2N/A ENTRY(__udivdi3)
2N/A movl 4(%esp), %eax / x, x
2N/A movl 8(%esp), %edx / x, x
2N/A pushl 16(%esp) / y
2N/A pushl 16(%esp)
2N/A call UDiv
2N/A addl $8, %esp
2N/A ret
2N/A SET_SIZE(__udivdi3)
2N/A
2N/A/*
2N/A * __umoddi3
2N/A *
2N/A * Perform division of two unsigned 64-bit quantities, returning the
2N/A * remainder in %edx:%eax.
2N/A */
2N/A ENTRY(__umoddi3)
2N/A subl $12, %esp
2N/A movl %esp, %ecx /, tmp65
2N/A movl 16(%esp), %eax / x, x
2N/A movl 20(%esp), %edx / x, x
2N/A pushl %ecx / tmp65
2N/A pushl 32(%esp) / y
2N/A pushl 32(%esp)
2N/A call UDivRem
2N/A movl 12(%esp), %eax / rem, rem
2N/A movl 16(%esp), %edx / rem, rem
2N/A addl $24, %esp
2N/A ret
2N/A SET_SIZE(__umoddi3)
2N/A
2N/A/*
2N/A * __divdi3
2N/A *
2N/A * Perform division of two signed 64-bit quantities, returning the
2N/A * quotient in %edx:%eax.
2N/A */
2N/A/ int64_t
2N/A/ __divdi3(int64_t x, int64_t y)
2N/A/ {
2N/A/ int negative;
2N/A/ uint64_t xt, yt, r;
2N/A/
2N/A/ if (x < 0) {
2N/A/ xt = -(uint64_t) x;
2N/A/ negative = 1;
2N/A/ } else {
2N/A/ xt = x;
2N/A/ negative = 0;
2N/A/ }
2N/A/ if (y < 0) {
2N/A/ yt = -(uint64_t) y;
2N/A/ negative ^= 1;
2N/A/ } else {
2N/A/ yt = y;
2N/A/ }
2N/A/ r = UDiv(xt, yt);
2N/A/ return (negative ? (int64_t) - r : r);
2N/A/ }
2N/A ENTRY(__divdi3)
2N/A pushl %ebp
2N/A pushl %edi
2N/A pushl %esi
2N/A subl $8, %esp
2N/A movl 28(%esp), %edx / x, x
2N/A testl %edx, %edx / x
2N/A movl 24(%esp), %eax / x, x
2N/A movl 32(%esp), %esi / y, y
2N/A movl 36(%esp), %edi / y, y
2N/A js .LL55
2N/A xorl %ebp, %ebp / negative
2N/A testl %edi, %edi / y
2N/A movl %eax, (%esp) / x, xt
2N/A movl %edx, 4(%esp) / x, xt
2N/A movl %esi, %eax / y, yt
2N/A movl %edi, %edx / y, yt
2N/A js .LL56
2N/A.LL53:
2N/A pushl %edx / yt
2N/A pushl %eax / yt
2N/A movl 8(%esp), %eax / xt, xt
2N/A movl 12(%esp), %edx / xt, xt
2N/A call UDiv
2N/A popl %ecx
2N/A testl %ebp, %ebp / negative
2N/A popl %esi
2N/A je .LL54
2N/A negl %eax / r
2N/A adcl $0, %edx /, r
2N/A negl %edx / r
2N/A.LL54:
2N/A addl $8, %esp
2N/A popl %esi
2N/A popl %edi
2N/A popl %ebp
2N/A ret
2N/A .align 16
2N/A.LL55:
2N/A negl %eax / x
2N/A adcl $0, %edx /, x
2N/A negl %edx / x
2N/A testl %edi, %edi / y
2N/A movl %eax, (%esp) / x, xt
2N/A movl %edx, 4(%esp) / x, xt
2N/A movl $1, %ebp /, negative
2N/A movl %esi, %eax / y, yt
2N/A movl %edi, %edx / y, yt
2N/A jns .LL53
2N/A .align 16
2N/A.LL56:
2N/A negl %eax / yt
2N/A adcl $0, %edx /, yt
2N/A negl %edx / yt
2N/A xorl $1, %ebp /, negative
2N/A jmp .LL53
2N/A SET_SIZE(__divdi3)
2N/A
2N/A/*
2N/A * __moddi3
2N/A *
2N/A * Perform division of two signed 64-bit quantities, returning the
2N/A * quotient in %edx:%eax.
2N/A */
2N/A/ int64_t
2N/A/ __moddi3(int64_t x, int64_t y)
2N/A/ {
2N/A/ uint64_t xt, yt, rem;
2N/A/
2N/A/ if (x < 0) {
2N/A/ xt = -(uint64_t) x;
2N/A/ } else {
2N/A/ xt = x;
2N/A/ }
2N/A/ if (y < 0) {
2N/A/ yt = -(uint64_t) y;
2N/A/ } else {
2N/A/ yt = y;
2N/A/ }
2N/A/ (void) UDivRem(xt, yt, &rem);
2N/A/ return (x < 0 ? (int64_t) - rem : rem);
2N/A/ }
2N/A ENTRY(__moddi3)
2N/A pushl %edi
2N/A pushl %esi
2N/A subl $20, %esp
2N/A movl 36(%esp), %ecx / x,
2N/A movl 32(%esp), %esi / x,
2N/A movl 36(%esp), %edi / x,
2N/A testl %ecx, %ecx
2N/A movl 40(%esp), %eax / y, y
2N/A movl 44(%esp), %edx / y, y
2N/A movl %esi, (%esp) /, xt
2N/A movl %edi, 4(%esp) /, xt
2N/A js .LL63
2N/A testl %edx, %edx / y
2N/A movl %eax, %esi / y, yt
2N/A movl %edx, %edi / y, yt
2N/A js .LL64
2N/A.LL61:
2N/A leal 8(%esp), %eax /, tmp66
2N/A pushl %eax / tmp66
2N/A pushl %edi / yt
2N/A pushl %esi / yt
2N/A movl 12(%esp), %eax / xt, xt
2N/A movl 16(%esp), %edx / xt, xt
2N/A call UDivRem
2N/A addl $12, %esp
2N/A movl 36(%esp), %edi / x,
2N/A testl %edi, %edi
2N/A movl 8(%esp), %eax / rem, rem
2N/A movl 12(%esp), %edx / rem, rem
2N/A js .LL65
2N/A addl $20, %esp
2N/A popl %esi
2N/A popl %edi
2N/A ret
2N/A .align 16
2N/A.LL63:
2N/A negl %esi
2N/A adcl $0, %edi
2N/A negl %edi
2N/A testl %edx, %edx / y
2N/A movl %esi, (%esp) /, xt
2N/A movl %edi, 4(%esp) /, xt
2N/A movl %eax, %esi / y, yt
2N/A movl %edx, %edi / y, yt
2N/A jns .LL61
2N/A .align 16
2N/A.LL64:
2N/A negl %esi / yt
2N/A adcl $0, %edi /, yt
2N/A negl %edi / yt
2N/A jmp .LL61
2N/A .align 16
2N/A.LL65:
2N/A negl %eax / rem
2N/A adcl $0, %edx /, rem
2N/A addl $20, %esp
2N/A popl %esi
2N/A negl %edx / rem
2N/A popl %edi
2N/A ret
2N/A SET_SIZE(__moddi3)
2N/A
2N/A#endif /* __lint */