10ec57554Sraf/* 20ec57554Sraf * CDDL HEADER START 30ec57554Sraf * 40ec57554Sraf * The contents of this file are subject to the terms of the 5*9a70fc3bSMark J. Nelson * Common Development and Distribution License (the "License"). 6*9a70fc3bSMark J. Nelson * You may not use this file except in compliance with the License. 70ec57554Sraf * 80ec57554Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90ec57554Sraf * or http://www.opensolaris.org/os/licensing. 100ec57554Sraf * See the License for the specific language governing permissions 110ec57554Sraf * and limitations under the License. 120ec57554Sraf * 130ec57554Sraf * When distributing Covered Code, include this CDDL HEADER in each 140ec57554Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150ec57554Sraf * If applicable, add the following below this CDDL HEADER, with the 160ec57554Sraf * fields enclosed by brackets "[]" replaced with your own identifying 170ec57554Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 180ec57554Sraf * 190ec57554Sraf * CDDL HEADER END 200ec57554Sraf */ 210ec57554Sraf 220ec57554Sraf/* 230ec57554Sraf * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240ec57554Sraf * Use is subject to license terms. 250ec57554Sraf */ 260ec57554Sraf 27*9a70fc3bSMark J. Nelson .file "_divdi3.s" 280ec57554Sraf 290ec57554Sraf#include <SYS.h> 300ec57554Sraf 310ec57554Sraf/* 320ec57554Sraf * C support for 64-bit modulo and division. 330ec57554Sraf * GNU routines callable from C (though generated by the compiler). 340ec57554Sraf * Hand-customized compiler output - see comments for details. 350ec57554Sraf */ 360ec57554Sraf 370ec57554Sraf#if defined(__lint) 380ec57554Sraf 390ec57554Sraf/*ARGSUSED*/ 400ec57554Srafuint64_t 410ec57554Sraf__udivdi3(uint64_t a, uint64_t b) 420ec57554Sraf{ return (0); } 430ec57554Sraf 440ec57554Sraf/*ARGSUSED*/ 450ec57554Srafuint64_t 460ec57554Sraf__umoddi3(uint64_t a, uint64_t b) 470ec57554Sraf{ return (0); } 480ec57554Sraf 490ec57554Sraf/*ARGSUSED*/ 500ec57554Srafint64_t 510ec57554Sraf__divdi3(int64_t a, int64_t b) 520ec57554Sraf{ return (0); } 530ec57554Sraf 540ec57554Sraf/*ARGSUSED*/ 550ec57554Srafint64_t 560ec57554Sraf__moddi3(int64_t a, int64_t b) 570ec57554Sraf{ return (0); } 580ec57554Sraf 590ec57554Sraf#else 600ec57554Sraf 610ec57554Sraf/* 620ec57554Sraf * __udivdi3 630ec57554Sraf * 640ec57554Sraf * Perform division of two unsigned 64-bit quantities, returning the 650ec57554Sraf * quotient in %edx:%eax. 660ec57554Sraf */ 670ec57554Sraf ENTRY(__udivdi3) 680ec57554Sraf movl 4(%esp), %eax / x, x 690ec57554Sraf movl 8(%esp), %edx / x, x 700ec57554Sraf pushl 16(%esp) / y 710ec57554Sraf pushl 16(%esp) 720ec57554Sraf call UDiv 730ec57554Sraf addl $8, %esp 740ec57554Sraf ret 750ec57554Sraf SET_SIZE(__udivdi3) 760ec57554Sraf 770ec57554Sraf/* 780ec57554Sraf * __umoddi3 790ec57554Sraf * 800ec57554Sraf * Perform division of two unsigned 64-bit quantities, returning the 810ec57554Sraf * remainder in %edx:%eax. 820ec57554Sraf */ 830ec57554Sraf ENTRY(__umoddi3) 840ec57554Sraf subl $12, %esp 850ec57554Sraf movl %esp, %ecx /, tmp65 860ec57554Sraf movl 16(%esp), %eax / x, x 870ec57554Sraf movl 20(%esp), %edx / x, x 880ec57554Sraf pushl %ecx / tmp65 890ec57554Sraf pushl 32(%esp) / y 900ec57554Sraf pushl 32(%esp) 910ec57554Sraf call UDivRem 920ec57554Sraf movl 12(%esp), %eax / rem, rem 930ec57554Sraf movl 16(%esp), %edx / rem, rem 940ec57554Sraf addl $24, %esp 950ec57554Sraf ret 960ec57554Sraf SET_SIZE(__umoddi3) 970ec57554Sraf 980ec57554Sraf/* 990ec57554Sraf * __divdi3 1000ec57554Sraf * 1010ec57554Sraf * Perform division of two signed 64-bit quantities, returning the 1020ec57554Sraf * quotient in %edx:%eax. 1030ec57554Sraf */ 1040ec57554Sraf/ int64_t 1050ec57554Sraf/ __divdi3(int64_t x, int64_t y) 1060ec57554Sraf/ { 1070ec57554Sraf/ int negative; 1080ec57554Sraf/ uint64_t xt, yt, r; 1090ec57554Sraf/ 1100ec57554Sraf/ if (x < 0) { 1110ec57554Sraf/ xt = -(uint64_t) x; 1120ec57554Sraf/ negative = 1; 1130ec57554Sraf/ } else { 1140ec57554Sraf/ xt = x; 1150ec57554Sraf/ negative = 0; 1160ec57554Sraf/ } 1170ec57554Sraf/ if (y < 0) { 1180ec57554Sraf/ yt = -(uint64_t) y; 1190ec57554Sraf/ negative ^= 1; 1200ec57554Sraf/ } else { 1210ec57554Sraf/ yt = y; 1220ec57554Sraf/ } 1230ec57554Sraf/ r = UDiv(xt, yt); 1240ec57554Sraf/ return (negative ? (int64_t) - r : r); 1250ec57554Sraf/ } 1260ec57554Sraf ENTRY(__divdi3) 1270ec57554Sraf pushl %ebp 1280ec57554Sraf pushl %edi 1290ec57554Sraf pushl %esi 1300ec57554Sraf subl $8, %esp 1310ec57554Sraf movl 28(%esp), %edx / x, x 1320ec57554Sraf testl %edx, %edx / x 1330ec57554Sraf movl 24(%esp), %eax / x, x 1340ec57554Sraf movl 32(%esp), %esi / y, y 1350ec57554Sraf movl 36(%esp), %edi / y, y 1360ec57554Sraf js .LL55 1370ec57554Sraf xorl %ebp, %ebp / negative 1380ec57554Sraf testl %edi, %edi / y 1390ec57554Sraf movl %eax, (%esp) / x, xt 1400ec57554Sraf movl %edx, 4(%esp) / x, xt 1410ec57554Sraf movl %esi, %eax / y, yt 1420ec57554Sraf movl %edi, %edx / y, yt 1430ec57554Sraf js .LL56 1440ec57554Sraf.LL53: 1450ec57554Sraf pushl %edx / yt 1460ec57554Sraf pushl %eax / yt 1470ec57554Sraf movl 8(%esp), %eax / xt, xt 1480ec57554Sraf movl 12(%esp), %edx / xt, xt 1490ec57554Sraf call UDiv 1500ec57554Sraf popl %ecx 1510ec57554Sraf testl %ebp, %ebp / negative 1520ec57554Sraf popl %esi 1530ec57554Sraf je .LL54 1540ec57554Sraf negl %eax / r 1550ec57554Sraf adcl $0, %edx /, r 1560ec57554Sraf negl %edx / r 1570ec57554Sraf.LL54: 1580ec57554Sraf addl $8, %esp 1590ec57554Sraf popl %esi 1600ec57554Sraf popl %edi 1610ec57554Sraf popl %ebp 1620ec57554Sraf ret 1630ec57554Sraf .align 16 1640ec57554Sraf.LL55: 1650ec57554Sraf negl %eax / x 1660ec57554Sraf adcl $0, %edx /, x 1670ec57554Sraf negl %edx / x 1680ec57554Sraf testl %edi, %edi / y 1690ec57554Sraf movl %eax, (%esp) / x, xt 1700ec57554Sraf movl %edx, 4(%esp) / x, xt 1710ec57554Sraf movl $1, %ebp /, negative 1720ec57554Sraf movl %esi, %eax / y, yt 1730ec57554Sraf movl %edi, %edx / y, yt 1740ec57554Sraf jns .LL53 1750ec57554Sraf .align 16 1760ec57554Sraf.LL56: 1770ec57554Sraf negl %eax / yt 1780ec57554Sraf adcl $0, %edx /, yt 1790ec57554Sraf negl %edx / yt 1800ec57554Sraf xorl $1, %ebp /, negative 1810ec57554Sraf jmp .LL53 1820ec57554Sraf SET_SIZE(__divdi3) 1830ec57554Sraf 1840ec57554Sraf/* 1850ec57554Sraf * __moddi3 1860ec57554Sraf * 1870ec57554Sraf * Perform division of two signed 64-bit quantities, returning the 1880ec57554Sraf * quotient in %edx:%eax. 1890ec57554Sraf */ 1900ec57554Sraf/ int64_t 1910ec57554Sraf/ __moddi3(int64_t x, int64_t y) 1920ec57554Sraf/ { 1930ec57554Sraf/ uint64_t xt, yt, rem; 1940ec57554Sraf/ 1950ec57554Sraf/ if (x < 0) { 1960ec57554Sraf/ xt = -(uint64_t) x; 1970ec57554Sraf/ } else { 1980ec57554Sraf/ xt = x; 1990ec57554Sraf/ } 2000ec57554Sraf/ if (y < 0) { 2010ec57554Sraf/ yt = -(uint64_t) y; 2020ec57554Sraf/ } else { 2030ec57554Sraf/ yt = y; 2040ec57554Sraf/ } 2050ec57554Sraf/ (void) UDivRem(xt, yt, &rem); 2060ec57554Sraf/ return (x < 0 ? (int64_t) - rem : rem); 2070ec57554Sraf/ } 2080ec57554Sraf ENTRY(__moddi3) 2090ec57554Sraf pushl %edi 2100ec57554Sraf pushl %esi 2110ec57554Sraf subl $20, %esp 2120ec57554Sraf movl 36(%esp), %ecx / x, 2130ec57554Sraf movl 32(%esp), %esi / x, 2140ec57554Sraf movl 36(%esp), %edi / x, 2150ec57554Sraf testl %ecx, %ecx 2160ec57554Sraf movl 40(%esp), %eax / y, y 2170ec57554Sraf movl 44(%esp), %edx / y, y 2180ec57554Sraf movl %esi, (%esp) /, xt 2190ec57554Sraf movl %edi, 4(%esp) /, xt 2200ec57554Sraf js .LL63 2210ec57554Sraf testl %edx, %edx / y 2220ec57554Sraf movl %eax, %esi / y, yt 2230ec57554Sraf movl %edx, %edi / y, yt 2240ec57554Sraf js .LL64 2250ec57554Sraf.LL61: 2260ec57554Sraf leal 8(%esp), %eax /, tmp66 2270ec57554Sraf pushl %eax / tmp66 2280ec57554Sraf pushl %edi / yt 2290ec57554Sraf pushl %esi / yt 2300ec57554Sraf movl 12(%esp), %eax / xt, xt 2310ec57554Sraf movl 16(%esp), %edx / xt, xt 2320ec57554Sraf call UDivRem 2330ec57554Sraf addl $12, %esp 2340ec57554Sraf movl 36(%esp), %edi / x, 2350ec57554Sraf testl %edi, %edi 2360ec57554Sraf movl 8(%esp), %eax / rem, rem 2370ec57554Sraf movl 12(%esp), %edx / rem, rem 2380ec57554Sraf js .LL65 2390ec57554Sraf addl $20, %esp 2400ec57554Sraf popl %esi 2410ec57554Sraf popl %edi 2420ec57554Sraf ret 2430ec57554Sraf .align 16 2440ec57554Sraf.LL63: 2450ec57554Sraf negl %esi 2460ec57554Sraf adcl $0, %edi 2470ec57554Sraf negl %edi 2480ec57554Sraf testl %edx, %edx / y 2490ec57554Sraf movl %esi, (%esp) /, xt 2500ec57554Sraf movl %edi, 4(%esp) /, xt 2510ec57554Sraf movl %eax, %esi / y, yt 2520ec57554Sraf movl %edx, %edi / y, yt 2530ec57554Sraf jns .LL61 2540ec57554Sraf .align 16 2550ec57554Sraf.LL64: 2560ec57554Sraf negl %esi / yt 2570ec57554Sraf adcl $0, %edi /, yt 2580ec57554Sraf negl %edi / yt 2590ec57554Sraf jmp .LL61 2600ec57554Sraf .align 16 2610ec57554Sraf.LL65: 2620ec57554Sraf negl %eax / rem 2630ec57554Sraf adcl $0, %edx /, rem 2640ec57554Sraf addl $20, %esp 2650ec57554Sraf popl %esi 2660ec57554Sraf negl %edx / rem 2670ec57554Sraf popl %edi 2680ec57554Sraf ret 2690ec57554Sraf SET_SIZE(__moddi3) 2700ec57554Sraf 2710ec57554Sraf#endif /* __lint */ 272