11016Sraf/* 21016Sraf * CDDL HEADER START 31016Sraf * 41016Sraf * The contents of this file are subject to the terms of the 5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License"). 6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License. 71016Sraf * 81016Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91016Sraf * or http://www.opensolaris.org/os/licensing. 101016Sraf * See the License for the specific language governing permissions 111016Sraf * and limitations under the License. 121016Sraf * 131016Sraf * When distributing Covered Code, include this CDDL HEADER in each 141016Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151016Sraf * If applicable, add the following below this CDDL HEADER, with the 161016Sraf * fields enclosed by brackets "[]" replaced with your own identifying 171016Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 181016Sraf * 191016Sraf * CDDL HEADER END 201016Sraf */ 211016Sraf 221016Sraf/* 231016Sraf * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 241016Sraf * Use is subject to license terms. 251016Sraf */ 261016Sraf 27*7298SMark.J.Nelson@Sun.COM .file "_divdi3.s" 281016Sraf 291016Sraf#include <SYS.h> 301016Sraf 311016Sraf/* 321016Sraf * C support for 64-bit modulo and division. 331016Sraf * GNU routines callable from C (though generated by the compiler). 341016Sraf * Hand-customized compiler output - see comments for details. 351016Sraf */ 361016Sraf 371016Sraf#if defined(__lint) 381016Sraf 391016Sraf/*ARGSUSED*/ 401016Srafuint64_t 411016Sraf__udivdi3(uint64_t a, uint64_t b) 421016Sraf{ return (0); } 431016Sraf 441016Sraf/*ARGSUSED*/ 451016Srafuint64_t 461016Sraf__umoddi3(uint64_t a, uint64_t b) 471016Sraf{ return (0); } 481016Sraf 491016Sraf/*ARGSUSED*/ 501016Srafint64_t 511016Sraf__divdi3(int64_t a, int64_t b) 521016Sraf{ return (0); } 531016Sraf 541016Sraf/*ARGSUSED*/ 551016Srafint64_t 561016Sraf__moddi3(int64_t a, int64_t b) 571016Sraf{ return (0); } 581016Sraf 591016Sraf#else 601016Sraf 611016Sraf/* 621016Sraf * __udivdi3 631016Sraf * 641016Sraf * Perform division of two unsigned 64-bit quantities, returning the 651016Sraf * quotient in %edx:%eax. 661016Sraf */ 671016Sraf ENTRY(__udivdi3) 681016Sraf movl 4(%esp), %eax / x, x 691016Sraf movl 8(%esp), %edx / x, x 701016Sraf pushl 16(%esp) / y 711016Sraf pushl 16(%esp) 721016Sraf call UDiv 731016Sraf addl $8, %esp 741016Sraf ret 751016Sraf SET_SIZE(__udivdi3) 761016Sraf 771016Sraf/* 781016Sraf * __umoddi3 791016Sraf * 801016Sraf * Perform division of two unsigned 64-bit quantities, returning the 811016Sraf * remainder in %edx:%eax. 821016Sraf */ 831016Sraf ENTRY(__umoddi3) 841016Sraf subl $12, %esp 851016Sraf movl %esp, %ecx /, tmp65 861016Sraf movl 16(%esp), %eax / x, x 871016Sraf movl 20(%esp), %edx / x, x 881016Sraf pushl %ecx / tmp65 891016Sraf pushl 32(%esp) / y 901016Sraf pushl 32(%esp) 911016Sraf call UDivRem 921016Sraf movl 12(%esp), %eax / rem, rem 931016Sraf movl 16(%esp), %edx / rem, rem 941016Sraf addl $24, %esp 951016Sraf ret 961016Sraf SET_SIZE(__umoddi3) 971016Sraf 981016Sraf/* 991016Sraf * __divdi3 1001016Sraf * 1011016Sraf * Perform division of two signed 64-bit quantities, returning the 1021016Sraf * quotient in %edx:%eax. 1031016Sraf */ 1041016Sraf/ int64_t 1051016Sraf/ __divdi3(int64_t x, int64_t y) 1061016Sraf/ { 1071016Sraf/ int negative; 1081016Sraf/ uint64_t xt, yt, r; 1091016Sraf/ 1101016Sraf/ if (x < 0) { 1111016Sraf/ xt = -(uint64_t) x; 1121016Sraf/ negative = 1; 1131016Sraf/ } else { 1141016Sraf/ xt = x; 1151016Sraf/ negative = 0; 1161016Sraf/ } 1171016Sraf/ if (y < 0) { 1181016Sraf/ yt = -(uint64_t) y; 1191016Sraf/ negative ^= 1; 1201016Sraf/ } else { 1211016Sraf/ yt = y; 1221016Sraf/ } 1231016Sraf/ r = UDiv(xt, yt); 1241016Sraf/ return (negative ? (int64_t) - r : r); 1251016Sraf/ } 1261016Sraf ENTRY(__divdi3) 1271016Sraf pushl %ebp 1281016Sraf pushl %edi 1291016Sraf pushl %esi 1301016Sraf subl $8, %esp 1311016Sraf movl 28(%esp), %edx / x, x 1321016Sraf testl %edx, %edx / x 1331016Sraf movl 24(%esp), %eax / x, x 1341016Sraf movl 32(%esp), %esi / y, y 1351016Sraf movl 36(%esp), %edi / y, y 1361016Sraf js .LL55 1371016Sraf xorl %ebp, %ebp / negative 1381016Sraf testl %edi, %edi / y 1391016Sraf movl %eax, (%esp) / x, xt 1401016Sraf movl %edx, 4(%esp) / x, xt 1411016Sraf movl %esi, %eax / y, yt 1421016Sraf movl %edi, %edx / y, yt 1431016Sraf js .LL56 1441016Sraf.LL53: 1451016Sraf pushl %edx / yt 1461016Sraf pushl %eax / yt 1471016Sraf movl 8(%esp), %eax / xt, xt 1481016Sraf movl 12(%esp), %edx / xt, xt 1491016Sraf call UDiv 1501016Sraf popl %ecx 1511016Sraf testl %ebp, %ebp / negative 1521016Sraf popl %esi 1531016Sraf je .LL54 1541016Sraf negl %eax / r 1551016Sraf adcl $0, %edx /, r 1561016Sraf negl %edx / r 1571016Sraf.LL54: 1581016Sraf addl $8, %esp 1591016Sraf popl %esi 1601016Sraf popl %edi 1611016Sraf popl %ebp 1621016Sraf ret 1631016Sraf .align 16 1641016Sraf.LL55: 1651016Sraf negl %eax / x 1661016Sraf adcl $0, %edx /, x 1671016Sraf negl %edx / x 1681016Sraf testl %edi, %edi / y 1691016Sraf movl %eax, (%esp) / x, xt 1701016Sraf movl %edx, 4(%esp) / x, xt 1711016Sraf movl $1, %ebp /, negative 1721016Sraf movl %esi, %eax / y, yt 1731016Sraf movl %edi, %edx / y, yt 1741016Sraf jns .LL53 1751016Sraf .align 16 1761016Sraf.LL56: 1771016Sraf negl %eax / yt 1781016Sraf adcl $0, %edx /, yt 1791016Sraf negl %edx / yt 1801016Sraf xorl $1, %ebp /, negative 1811016Sraf jmp .LL53 1821016Sraf SET_SIZE(__divdi3) 1831016Sraf 1841016Sraf/* 1851016Sraf * __moddi3 1861016Sraf * 1871016Sraf * Perform division of two signed 64-bit quantities, returning the 1881016Sraf * quotient in %edx:%eax. 1891016Sraf */ 1901016Sraf/ int64_t 1911016Sraf/ __moddi3(int64_t x, int64_t y) 1921016Sraf/ { 1931016Sraf/ uint64_t xt, yt, rem; 1941016Sraf/ 1951016Sraf/ if (x < 0) { 1961016Sraf/ xt = -(uint64_t) x; 1971016Sraf/ } else { 1981016Sraf/ xt = x; 1991016Sraf/ } 2001016Sraf/ if (y < 0) { 2011016Sraf/ yt = -(uint64_t) y; 2021016Sraf/ } else { 2031016Sraf/ yt = y; 2041016Sraf/ } 2051016Sraf/ (void) UDivRem(xt, yt, &rem); 2061016Sraf/ return (x < 0 ? (int64_t) - rem : rem); 2071016Sraf/ } 2081016Sraf ENTRY(__moddi3) 2091016Sraf pushl %edi 2101016Sraf pushl %esi 2111016Sraf subl $20, %esp 2121016Sraf movl 36(%esp), %ecx / x, 2131016Sraf movl 32(%esp), %esi / x, 2141016Sraf movl 36(%esp), %edi / x, 2151016Sraf testl %ecx, %ecx 2161016Sraf movl 40(%esp), %eax / y, y 2171016Sraf movl 44(%esp), %edx / y, y 2181016Sraf movl %esi, (%esp) /, xt 2191016Sraf movl %edi, 4(%esp) /, xt 2201016Sraf js .LL63 2211016Sraf testl %edx, %edx / y 2221016Sraf movl %eax, %esi / y, yt 2231016Sraf movl %edx, %edi / y, yt 2241016Sraf js .LL64 2251016Sraf.LL61: 2261016Sraf leal 8(%esp), %eax /, tmp66 2271016Sraf pushl %eax / tmp66 2281016Sraf pushl %edi / yt 2291016Sraf pushl %esi / yt 2301016Sraf movl 12(%esp), %eax / xt, xt 2311016Sraf movl 16(%esp), %edx / xt, xt 2321016Sraf call UDivRem 2331016Sraf addl $12, %esp 2341016Sraf movl 36(%esp), %edi / x, 2351016Sraf testl %edi, %edi 2361016Sraf movl 8(%esp), %eax / rem, rem 2371016Sraf movl 12(%esp), %edx / rem, rem 2381016Sraf js .LL65 2391016Sraf addl $20, %esp 2401016Sraf popl %esi 2411016Sraf popl %edi 2421016Sraf ret 2431016Sraf .align 16 2441016Sraf.LL63: 2451016Sraf negl %esi 2461016Sraf adcl $0, %edi 2471016Sraf negl %edi 2481016Sraf testl %edx, %edx / y 2491016Sraf movl %esi, (%esp) /, xt 2501016Sraf movl %edi, 4(%esp) /, xt 2511016Sraf movl %eax, %esi / y, yt 2521016Sraf movl %edx, %edi / y, yt 2531016Sraf jns .LL61 2541016Sraf .align 16 2551016Sraf.LL64: 2561016Sraf negl %esi / yt 2571016Sraf adcl $0, %edi /, yt 2581016Sraf negl %edi / yt 2591016Sraf jmp .LL61 2601016Sraf .align 16 2611016Sraf.LL65: 2621016Sraf negl %eax / rem 2631016Sraf adcl $0, %edx /, rem 2641016Sraf addl $20, %esp 2651016Sraf popl %esi 2661016Sraf negl %edx / rem 2671016Sraf popl %edi 2681016Sraf ret 2691016Sraf SET_SIZE(__moddi3) 2701016Sraf 2711016Sraf#endif /* __lint */ 272