/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ .file "_divdi3.s" #include /* * C support for 64-bit modulo and division. * GNU routines callable from C (though generated by the compiler). * Hand-customized compiler output - see comments for details. */ #if defined(__lint) /*ARGSUSED*/ uint64_t __udivdi3(uint64_t a, uint64_t b) { return (0); } /*ARGSUSED*/ uint64_t __umoddi3(uint64_t a, uint64_t b) { return (0); } /*ARGSUSED*/ int64_t __divdi3(int64_t a, int64_t b) { return (0); } /*ARGSUSED*/ int64_t __moddi3(int64_t a, int64_t b) { return (0); } #else /* * __udivdi3 * * Perform division of two unsigned 64-bit quantities, returning the * quotient in %edx:%eax. */ ENTRY(__udivdi3) movl 4(%esp), %eax / x, x movl 8(%esp), %edx / x, x pushl 16(%esp) / y pushl 16(%esp) call UDiv addl $8, %esp ret SET_SIZE(__udivdi3) /* * __umoddi3 * * Perform division of two unsigned 64-bit quantities, returning the * remainder in %edx:%eax. */ ENTRY(__umoddi3) subl $12, %esp movl %esp, %ecx /, tmp65 movl 16(%esp), %eax / x, x movl 20(%esp), %edx / x, x pushl %ecx / tmp65 pushl 32(%esp) / y pushl 32(%esp) call UDivRem movl 12(%esp), %eax / rem, rem movl 16(%esp), %edx / rem, rem addl $24, %esp ret SET_SIZE(__umoddi3) /* * __divdi3 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax. */ / int64_t / __divdi3(int64_t x, int64_t y) / { / int negative; / uint64_t xt, yt, r; / / if (x < 0) { / xt = -(uint64_t) x; / negative = 1; / } else { / xt = x; / negative = 0; / } / if (y < 0) { / yt = -(uint64_t) y; / negative ^= 1; / } else { / yt = y; / } / r = UDiv(xt, yt); / return (negative ? (int64_t) - r : r); / } ENTRY(__divdi3) pushl %ebp pushl %edi pushl %esi subl $8, %esp movl 28(%esp), %edx / x, x testl %edx, %edx / x movl 24(%esp), %eax / x, x movl 32(%esp), %esi / y, y movl 36(%esp), %edi / y, y js .LL55 xorl %ebp, %ebp / negative testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl %esi, %eax / y, yt movl %edi, %edx / y, yt js .LL56 .LL53: pushl %edx / yt pushl %eax / yt movl 8(%esp), %eax / xt, xt movl 12(%esp), %edx / xt, xt call UDiv popl %ecx testl %ebp, %ebp / negative popl %esi je .LL54 negl %eax / r adcl $0, %edx /, r negl %edx / r .LL54: addl $8, %esp popl %esi popl %edi popl %ebp ret .align 16 .LL55: negl %eax / x adcl $0, %edx /, x negl %edx / x testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl $1, %ebp /, negative movl %esi, %eax / y, yt movl %edi, %edx / y, yt jns .LL53 .align 16 .LL56: negl %eax / yt adcl $0, %edx /, yt negl %edx / yt xorl $1, %ebp /, negative jmp .LL53 SET_SIZE(__divdi3) /* * __moddi3 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax. */ / int64_t / __moddi3(int64_t x, int64_t y) / { / uint64_t xt, yt, rem; / / if (x < 0) { / xt = -(uint64_t) x; / } else { / xt = x; / } / if (y < 0) { / yt = -(uint64_t) y; / } else { / yt = y; / } / (void) UDivRem(xt, yt, &rem); / return (x < 0 ? (int64_t) - rem : rem); / } ENTRY(__moddi3) pushl %edi pushl %esi subl $20, %esp movl 36(%esp), %ecx / x, movl 32(%esp), %esi / x, movl 36(%esp), %edi / x, testl %ecx, %ecx movl 40(%esp), %eax / y, y movl 44(%esp), %edx / y, y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt js .LL63 testl %edx, %edx / y movl %eax, %esi / y, yt movl %edx, %edi / y, yt js .LL64 .LL61: leal 8(%esp), %eax /, tmp66 pushl %eax / tmp66 pushl %edi / yt pushl %esi / yt movl 12(%esp), %eax / xt, xt movl 16(%esp), %edx / xt, xt call UDivRem addl $12, %esp movl 36(%esp), %edi / x, testl %edi, %edi movl 8(%esp), %eax / rem, rem movl 12(%esp), %edx / rem, rem js .LL65 addl $20, %esp popl %esi popl %edi ret .align 16 .LL63: negl %esi adcl $0, %edi negl %edi testl %edx, %edx / y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt movl %eax, %esi / y, yt movl %edx, %edi / y, yt jns .LL61 .align 16 .LL64: negl %esi / yt adcl $0, %edi /, yt negl %edi / yt jmp .LL61 .align 16 .LL65: negl %eax / rem adcl $0, %edx /, rem addl $20, %esp popl %esi negl %edx / rem popl %edi ret SET_SIZE(__moddi3) #endif /* __lint */