10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * 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. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate/* 220Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 26*7298SMark.J.Nelson@Sun.COM .file "_div64.s" 270Sstevel@tonic-gate 280Sstevel@tonic-gate#include "SYS.h" 290Sstevel@tonic-gate 300Sstevel@tonic-gate/* 310Sstevel@tonic-gate * C support for 64-bit modulo and division. 320Sstevel@tonic-gate * Hand-customized compiler output - see comments for details. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate/* 360Sstevel@tonic-gate * int32_t/int64_t division/manipulation 370Sstevel@tonic-gate * 380Sstevel@tonic-gate * Hand-customized compiler output: the non-GCC entry points depart from 390Sstevel@tonic-gate * the SYS V ABI by requiring their arguments to be popped, and in the 400Sstevel@tonic-gate * [u]divrem64 cases returning the remainder in %ecx:%esi. Note the 410Sstevel@tonic-gate * compiler-generated use of %edx:%eax for the first argument of 420Sstevel@tonic-gate * internal entry points. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * Inlines for speed: 450Sstevel@tonic-gate * - counting the number of leading zeros in a word 460Sstevel@tonic-gate * - multiplying two 32-bit numbers giving a 64-bit result 470Sstevel@tonic-gate * - dividing a 64-bit number by a 32-bit number, giving both quotient 480Sstevel@tonic-gate * and remainder 490Sstevel@tonic-gate * - subtracting two 64-bit results 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate/ #define LO(X) ((uint32_t)(X) & 0xffffffff) 520Sstevel@tonic-gate/ #define HI(X) ((uint32_t)((X) >> 32) & 0xffffffff) 530Sstevel@tonic-gate/ #define HILO(H, L) (((uint64_t)(H) << 32) + (L)) 540Sstevel@tonic-gate/ 550Sstevel@tonic-gate/ /* give index of highest bit */ 560Sstevel@tonic-gate/ #define HIBIT(a, r) \ 570Sstevel@tonic-gate/ asm("bsrl %1,%0": "=r"((uint32_t)(r)) : "g" (a)) 580Sstevel@tonic-gate/ 590Sstevel@tonic-gate/ /* multiply two uint32_ts resulting in a uint64_t */ 600Sstevel@tonic-gate/ #define A_MUL32(a, b, lo, hi) \ 610Sstevel@tonic-gate/ asm("mull %2" \ 620Sstevel@tonic-gate/ : "=a"((uint32_t)(lo)), "=d"((uint32_t)(hi)) : "g" (b), "0"(a)) 630Sstevel@tonic-gate/ 640Sstevel@tonic-gate/ /* divide a uint64_t by a uint32_t */ 650Sstevel@tonic-gate/ #define A_DIV32(lo, hi, b, q, r) \ 660Sstevel@tonic-gate/ asm("divl %2" \ 670Sstevel@tonic-gate/ : "=a"((uint32_t)(q)), "=d"((uint32_t)(r)) \ 680Sstevel@tonic-gate/ : "g" (b), "0"((uint32_t)(lo)), "1"((uint32_t)hi)) 690Sstevel@tonic-gate/ 700Sstevel@tonic-gate/ /* subtract two uint64_ts (with borrow) */ 710Sstevel@tonic-gate/ #define A_SUB2(bl, bh, al, ah) \ 720Sstevel@tonic-gate/ asm("subl %4,%0\n\tsbbl %5,%1" \ 730Sstevel@tonic-gate/ : "=&r"((uint32_t)(al)), "=r"((uint32_t)(ah)) \ 740Sstevel@tonic-gate/ : "0"((uint32_t)(al)), "1"((uint32_t)(ah)), "g"((uint32_t)(bl)), \ 750Sstevel@tonic-gate/ "g"((uint32_t)(bh))) 760Sstevel@tonic-gate/ 770Sstevel@tonic-gate/ /* 780Sstevel@tonic-gate/ * Unsigned division with remainder. 790Sstevel@tonic-gate/ * Divide two uint64_ts, and calculate remainder. 800Sstevel@tonic-gate/ */ 810Sstevel@tonic-gate/ uint64_t 820Sstevel@tonic-gate/ UDivRem(uint64_t x, uint64_t y, uint64_t * pmod) 830Sstevel@tonic-gate/ { 840Sstevel@tonic-gate/ /* simple cases: y is a single uint32_t */ 850Sstevel@tonic-gate/ if (HI(y) == 0) { 860Sstevel@tonic-gate/ uint32_t div_hi, div_rem; 870Sstevel@tonic-gate/ uint32_t q0, q1; 880Sstevel@tonic-gate/ 890Sstevel@tonic-gate/ /* calculate q1 */ 900Sstevel@tonic-gate/ if (HI(x) < LO(y)) { 910Sstevel@tonic-gate/ /* result is a single uint32_t, use one division */ 920Sstevel@tonic-gate/ q1 = 0; 930Sstevel@tonic-gate/ div_hi = HI(x); 940Sstevel@tonic-gate/ } else { 950Sstevel@tonic-gate/ /* result is a double uint32_t, use two divisions */ 960Sstevel@tonic-gate/ A_DIV32(HI(x), 0, LO(y), q1, div_hi); 970Sstevel@tonic-gate/ } 980Sstevel@tonic-gate/ 990Sstevel@tonic-gate/ /* calculate q0 and remainder */ 1000Sstevel@tonic-gate/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); 1010Sstevel@tonic-gate/ 1020Sstevel@tonic-gate/ /* return remainder */ 1030Sstevel@tonic-gate/ *pmod = div_rem; 1040Sstevel@tonic-gate/ 1050Sstevel@tonic-gate/ /* return result */ 1060Sstevel@tonic-gate/ return (HILO(q1, q0)); 1070Sstevel@tonic-gate/ 1080Sstevel@tonic-gate/ } else if (HI(x) < HI(y)) { 1090Sstevel@tonic-gate/ /* HI(x) < HI(y) => x < y => result is 0 */ 1100Sstevel@tonic-gate/ 1110Sstevel@tonic-gate/ /* return remainder */ 1120Sstevel@tonic-gate/ *pmod = x; 1130Sstevel@tonic-gate/ 1140Sstevel@tonic-gate/ /* return result */ 1150Sstevel@tonic-gate/ return (0); 1160Sstevel@tonic-gate/ 1170Sstevel@tonic-gate/ } else { 1180Sstevel@tonic-gate/ /* 1190Sstevel@tonic-gate/ * uint64_t by uint64_t division, resulting in a one-uint32_t 1200Sstevel@tonic-gate/ * result 1210Sstevel@tonic-gate/ */ 1220Sstevel@tonic-gate/ uint32_t y0, y1; 1230Sstevel@tonic-gate/ uint32_t x1, x0; 1240Sstevel@tonic-gate/ uint32_t q0; 1250Sstevel@tonic-gate/ uint32_t normshift; 1260Sstevel@tonic-gate/ 1270Sstevel@tonic-gate/ /* normalize by shifting x and y so MSB(y) == 1 */ 1280Sstevel@tonic-gate/ HIBIT(HI(y), normshift); /* index of highest 1 bit */ 1290Sstevel@tonic-gate/ normshift = 31 - normshift; 1300Sstevel@tonic-gate/ 1310Sstevel@tonic-gate/ if (normshift == 0) { 1320Sstevel@tonic-gate/ /* no shifting needed, and x < 2*y so q <= 1 */ 1330Sstevel@tonic-gate/ y1 = HI(y); 1340Sstevel@tonic-gate/ y0 = LO(y); 1350Sstevel@tonic-gate/ x1 = HI(x); 1360Sstevel@tonic-gate/ x0 = LO(x); 1370Sstevel@tonic-gate/ 1380Sstevel@tonic-gate/ /* if x >= y then q = 1 (note x1 >= y1) */ 1390Sstevel@tonic-gate/ if (x1 > y1 || x0 >= y0) { 1400Sstevel@tonic-gate/ q0 = 1; 1410Sstevel@tonic-gate/ /* subtract y from x to get remainder */ 1420Sstevel@tonic-gate/ A_SUB2(y0, y1, x0, x1); 1430Sstevel@tonic-gate/ } else { 1440Sstevel@tonic-gate/ q0 = 0; 1450Sstevel@tonic-gate/ } 1460Sstevel@tonic-gate/ 1470Sstevel@tonic-gate/ /* return remainder */ 1480Sstevel@tonic-gate/ *pmod = HILO(x1, x0); 1490Sstevel@tonic-gate/ 1500Sstevel@tonic-gate/ /* return result */ 1510Sstevel@tonic-gate/ return (q0); 1520Sstevel@tonic-gate/ 1530Sstevel@tonic-gate/ } else { 1540Sstevel@tonic-gate/ /* 1550Sstevel@tonic-gate/ * the last case: result is one uint32_t, but we need to 1560Sstevel@tonic-gate/ * normalize 1570Sstevel@tonic-gate/ */ 1580Sstevel@tonic-gate/ uint64_t dt; 1590Sstevel@tonic-gate/ uint32_t t0, t1, x2; 1600Sstevel@tonic-gate/ 1610Sstevel@tonic-gate/ /* normalize y */ 1620Sstevel@tonic-gate/ dt = (y << normshift); 1630Sstevel@tonic-gate/ y1 = HI(dt); 1640Sstevel@tonic-gate/ y0 = LO(dt); 1650Sstevel@tonic-gate/ 1660Sstevel@tonic-gate/ /* normalize x (we need 3 uint32_ts!!!) */ 1670Sstevel@tonic-gate/ x2 = (HI(x) >> (32 - normshift)); 1680Sstevel@tonic-gate/ dt = (x << normshift); 1690Sstevel@tonic-gate/ x1 = HI(dt); 1700Sstevel@tonic-gate/ x0 = LO(dt); 1710Sstevel@tonic-gate/ 1720Sstevel@tonic-gate/ /* estimate q0, and reduce x to a two uint32_t value */ 1730Sstevel@tonic-gate/ A_DIV32(x1, x2, y1, q0, x1); 1740Sstevel@tonic-gate/ 1750Sstevel@tonic-gate/ /* adjust q0 down if too high */ 1760Sstevel@tonic-gate/ /* 1770Sstevel@tonic-gate/ * because of the limited range of x2 we can only be 1780Sstevel@tonic-gate/ * one off 1790Sstevel@tonic-gate/ */ 1800Sstevel@tonic-gate/ A_MUL32(y0, q0, t0, t1); 1810Sstevel@tonic-gate/ if (t1 > x1 || (t1 == x1 && t0 > x0)) { 1820Sstevel@tonic-gate/ q0--; 1830Sstevel@tonic-gate/ A_SUB2(y0, y1, t0, t1); 1840Sstevel@tonic-gate/ } 1850Sstevel@tonic-gate/ /* return remainder */ 1860Sstevel@tonic-gate/ /* subtract product from x to get remainder */ 1870Sstevel@tonic-gate/ A_SUB2(t0, t1, x0, x1); 1880Sstevel@tonic-gate/ *pmod = (HILO(x1, x0) >> normshift); 1890Sstevel@tonic-gate/ 1900Sstevel@tonic-gate/ /* return result */ 1910Sstevel@tonic-gate/ return (q0); 1920Sstevel@tonic-gate/ } 1930Sstevel@tonic-gate/ } 1940Sstevel@tonic-gate/ } 1950Sstevel@tonic-gate ENTRY(UDivRem) 1960Sstevel@tonic-gate pushl %ebp 1970Sstevel@tonic-gate pushl %edi 1980Sstevel@tonic-gate pushl %esi 1990Sstevel@tonic-gate subl $48, %esp 2000Sstevel@tonic-gate movl 68(%esp), %edi / y, 2010Sstevel@tonic-gate testl %edi, %edi / tmp63 2020Sstevel@tonic-gate movl %eax, 40(%esp) / x, x 2030Sstevel@tonic-gate movl %edx, 44(%esp) / x, x 2040Sstevel@tonic-gate movl %edi, %esi /, tmp62 2050Sstevel@tonic-gate movl %edi, %ecx / tmp62, tmp63 2060Sstevel@tonic-gate jne .LL2 2070Sstevel@tonic-gate movl %edx, %eax /, tmp68 2080Sstevel@tonic-gate cmpl 64(%esp), %eax / y, tmp68 2090Sstevel@tonic-gate jae .LL21 2100Sstevel@tonic-gate.LL4: 2110Sstevel@tonic-gate movl 72(%esp), %ebp / pmod, 2120Sstevel@tonic-gate xorl %esi, %esi / <result> 2130Sstevel@tonic-gate movl 40(%esp), %eax / x, q0 2140Sstevel@tonic-gate movl %ecx, %edi / <result>, <result> 2150Sstevel@tonic-gate divl 64(%esp) / y 2160Sstevel@tonic-gate movl %edx, (%ebp) / div_rem, 2170Sstevel@tonic-gate xorl %edx, %edx / q0 2180Sstevel@tonic-gate addl %eax, %esi / q0, <result> 2190Sstevel@tonic-gate movl $0, 4(%ebp) 2200Sstevel@tonic-gate adcl %edx, %edi / q0, <result> 2210Sstevel@tonic-gate addl $48, %esp 2220Sstevel@tonic-gate movl %esi, %eax / <result>, <result> 2230Sstevel@tonic-gate popl %esi 2240Sstevel@tonic-gate movl %edi, %edx / <result>, <result> 2250Sstevel@tonic-gate popl %edi 2260Sstevel@tonic-gate popl %ebp 2270Sstevel@tonic-gate ret 2280Sstevel@tonic-gate .align 16 2290Sstevel@tonic-gate.LL2: 2300Sstevel@tonic-gate movl 44(%esp), %eax / x, 2310Sstevel@tonic-gate xorl %edx, %edx 2320Sstevel@tonic-gate cmpl %esi, %eax / tmp62, tmp5 2330Sstevel@tonic-gate movl %eax, 32(%esp) / tmp5, 2340Sstevel@tonic-gate movl %edx, 36(%esp) 2350Sstevel@tonic-gate jae .LL6 2360Sstevel@tonic-gate movl 72(%esp), %esi / pmod, 2370Sstevel@tonic-gate movl 40(%esp), %ebp / x, 2380Sstevel@tonic-gate movl 44(%esp), %ecx / x, 2390Sstevel@tonic-gate movl %ebp, (%esi) 2400Sstevel@tonic-gate movl %ecx, 4(%esi) 2410Sstevel@tonic-gate xorl %edi, %edi / <result> 2420Sstevel@tonic-gate xorl %esi, %esi / <result> 2430Sstevel@tonic-gate.LL22: 2440Sstevel@tonic-gate addl $48, %esp 2450Sstevel@tonic-gate movl %esi, %eax / <result>, <result> 2460Sstevel@tonic-gate popl %esi 2470Sstevel@tonic-gate movl %edi, %edx / <result>, <result> 2480Sstevel@tonic-gate popl %edi 2490Sstevel@tonic-gate popl %ebp 2500Sstevel@tonic-gate ret 2510Sstevel@tonic-gate .align 16 2520Sstevel@tonic-gate.LL21: 2530Sstevel@tonic-gate movl %edi, %edx / tmp63, div_hi 2540Sstevel@tonic-gate divl 64(%esp) / y 2550Sstevel@tonic-gate movl %eax, %ecx /, q1 2560Sstevel@tonic-gate jmp .LL4 2570Sstevel@tonic-gate .align 16 2580Sstevel@tonic-gate.LL6: 2590Sstevel@tonic-gate movl $31, %edi /, tmp87 2600Sstevel@tonic-gate bsrl %esi,%edx / tmp62, normshift 2610Sstevel@tonic-gate subl %edx, %edi / normshift, tmp87 2620Sstevel@tonic-gate movl %edi, 28(%esp) / tmp87, 2630Sstevel@tonic-gate jne .LL8 2640Sstevel@tonic-gate movl 32(%esp), %edx /, x1 2650Sstevel@tonic-gate cmpl %ecx, %edx / y1, x1 2660Sstevel@tonic-gate movl 64(%esp), %edi / y, y0 2670Sstevel@tonic-gate movl 40(%esp), %esi / x, x0 2680Sstevel@tonic-gate ja .LL10 2690Sstevel@tonic-gate xorl %ebp, %ebp / q0 2700Sstevel@tonic-gate cmpl %edi, %esi / y0, x0 2710Sstevel@tonic-gate jb .LL11 2720Sstevel@tonic-gate.LL10: 2730Sstevel@tonic-gate movl $1, %ebp /, q0 2740Sstevel@tonic-gate subl %edi,%esi / y0, x0 2750Sstevel@tonic-gate sbbl %ecx,%edx / tmp63, x1 2760Sstevel@tonic-gate.LL11: 2770Sstevel@tonic-gate movl %edx, %ecx / x1, x1 2780Sstevel@tonic-gate xorl %edx, %edx / x1 2790Sstevel@tonic-gate xorl %edi, %edi / x0 2800Sstevel@tonic-gate addl %esi, %edx / x0, x1 2810Sstevel@tonic-gate adcl %edi, %ecx / x0, x1 2820Sstevel@tonic-gate movl 72(%esp), %esi / pmod, 2830Sstevel@tonic-gate movl %edx, (%esi) / x1, 2840Sstevel@tonic-gate movl %ecx, 4(%esi) / x1, 2850Sstevel@tonic-gate xorl %edi, %edi / <result> 2860Sstevel@tonic-gate movl %ebp, %esi / q0, <result> 2870Sstevel@tonic-gate jmp .LL22 2880Sstevel@tonic-gate .align 16 2890Sstevel@tonic-gate.LL8: 2900Sstevel@tonic-gate movb 28(%esp), %cl 2910Sstevel@tonic-gate movl 64(%esp), %esi / y, dt 2920Sstevel@tonic-gate movl 68(%esp), %edi / y, dt 2930Sstevel@tonic-gate shldl %esi, %edi /, dt, dt 2940Sstevel@tonic-gate sall %cl, %esi /, dt 2950Sstevel@tonic-gate andl $32, %ecx 2960Sstevel@tonic-gate jne .LL23 2970Sstevel@tonic-gate.LL17: 2980Sstevel@tonic-gate movl $32, %ecx /, tmp102 2990Sstevel@tonic-gate subl 28(%esp), %ecx /, tmp102 3000Sstevel@tonic-gate movl %esi, %ebp / dt, y0 3010Sstevel@tonic-gate movl 32(%esp), %esi 3020Sstevel@tonic-gate shrl %cl, %esi / tmp102, 3030Sstevel@tonic-gate movl %edi, 24(%esp) / tmp99, 3040Sstevel@tonic-gate movb 28(%esp), %cl 3050Sstevel@tonic-gate movl %esi, 12(%esp) /, x2 3060Sstevel@tonic-gate movl 44(%esp), %edi / x, dt 3070Sstevel@tonic-gate movl 40(%esp), %esi / x, dt 3080Sstevel@tonic-gate shldl %esi, %edi /, dt, dt 3090Sstevel@tonic-gate sall %cl, %esi /, dt 3100Sstevel@tonic-gate andl $32, %ecx 3110Sstevel@tonic-gate je .LL18 3120Sstevel@tonic-gate movl %esi, %edi / dt, dt 3130Sstevel@tonic-gate xorl %esi, %esi / dt 3140Sstevel@tonic-gate.LL18: 3150Sstevel@tonic-gate movl %edi, %ecx / dt, 3160Sstevel@tonic-gate movl %edi, %eax / tmp2, 3170Sstevel@tonic-gate movl %ecx, (%esp) 3180Sstevel@tonic-gate movl 12(%esp), %edx / x2, 3190Sstevel@tonic-gate divl 24(%esp) 3200Sstevel@tonic-gate movl %edx, %ecx /, x1 3210Sstevel@tonic-gate xorl %edi, %edi 3220Sstevel@tonic-gate movl %eax, 20(%esp) 3230Sstevel@tonic-gate movl %ebp, %eax / y0, t0 3240Sstevel@tonic-gate mull 20(%esp) 3250Sstevel@tonic-gate cmpl %ecx, %edx / x1, t1 3260Sstevel@tonic-gate movl %edi, 4(%esp) 3270Sstevel@tonic-gate ja .LL14 3280Sstevel@tonic-gate je .LL24 3290Sstevel@tonic-gate.LL15: 3300Sstevel@tonic-gate movl %ecx, %edi / x1, 3310Sstevel@tonic-gate subl %eax,%esi / t0, x0 3320Sstevel@tonic-gate sbbl %edx,%edi / t1, 3330Sstevel@tonic-gate movl %edi, %eax /, x1 3340Sstevel@tonic-gate movl %eax, %edx / x1, x1 3350Sstevel@tonic-gate xorl %eax, %eax / x1 3360Sstevel@tonic-gate xorl %ebp, %ebp / x0 3370Sstevel@tonic-gate addl %esi, %eax / x0, x1 3380Sstevel@tonic-gate adcl %ebp, %edx / x0, x1 3390Sstevel@tonic-gate movb 28(%esp), %cl 3400Sstevel@tonic-gate shrdl %edx, %eax /, x1, x1 3410Sstevel@tonic-gate shrl %cl, %edx /, x1 3420Sstevel@tonic-gate andl $32, %ecx 3430Sstevel@tonic-gate je .LL16 3440Sstevel@tonic-gate movl %edx, %eax / x1, x1 3450Sstevel@tonic-gate xorl %edx, %edx / x1 3460Sstevel@tonic-gate.LL16: 3470Sstevel@tonic-gate movl 72(%esp), %ecx / pmod, 3480Sstevel@tonic-gate movl 20(%esp), %esi /, <result> 3490Sstevel@tonic-gate xorl %edi, %edi / <result> 3500Sstevel@tonic-gate movl %eax, (%ecx) / x1, 3510Sstevel@tonic-gate movl %edx, 4(%ecx) / x1, 3520Sstevel@tonic-gate jmp .LL22 3530Sstevel@tonic-gate .align 16 3540Sstevel@tonic-gate.LL24: 3550Sstevel@tonic-gate cmpl %esi, %eax / x0, t0 3560Sstevel@tonic-gate jbe .LL15 3570Sstevel@tonic-gate.LL14: 3580Sstevel@tonic-gate decl 20(%esp) 3590Sstevel@tonic-gate subl %ebp,%eax / y0, t0 3600Sstevel@tonic-gate sbbl 24(%esp),%edx /, t1 3610Sstevel@tonic-gate jmp .LL15 3620Sstevel@tonic-gate.LL23: 3630Sstevel@tonic-gate movl %esi, %edi / dt, dt 3640Sstevel@tonic-gate xorl %esi, %esi / dt 3650Sstevel@tonic-gate jmp .LL17 3660Sstevel@tonic-gate SET_SIZE(UDivRem) 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate/* 3690Sstevel@tonic-gate * Unsigned division without remainder. 3700Sstevel@tonic-gate */ 3710Sstevel@tonic-gate/ uint64_t 3720Sstevel@tonic-gate/ UDiv(uint64_t x, uint64_t y) 3730Sstevel@tonic-gate/ { 3740Sstevel@tonic-gate/ if (HI(y) == 0) { 3750Sstevel@tonic-gate/ /* simple cases: y is a single uint32_t */ 3760Sstevel@tonic-gate/ uint32_t div_hi, div_rem; 3770Sstevel@tonic-gate/ uint32_t q0, q1; 3780Sstevel@tonic-gate/ 3790Sstevel@tonic-gate/ /* calculate q1 */ 3800Sstevel@tonic-gate/ if (HI(x) < LO(y)) { 3810Sstevel@tonic-gate/ /* result is a single uint32_t, use one division */ 3820Sstevel@tonic-gate/ q1 = 0; 3830Sstevel@tonic-gate/ div_hi = HI(x); 3840Sstevel@tonic-gate/ } else { 3850Sstevel@tonic-gate/ /* result is a double uint32_t, use two divisions */ 3860Sstevel@tonic-gate/ A_DIV32(HI(x), 0, LO(y), q1, div_hi); 3870Sstevel@tonic-gate/ } 3880Sstevel@tonic-gate/ 3890Sstevel@tonic-gate/ /* calculate q0 and remainder */ 3900Sstevel@tonic-gate/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); 3910Sstevel@tonic-gate/ 3920Sstevel@tonic-gate/ /* return result */ 3930Sstevel@tonic-gate/ return (HILO(q1, q0)); 3940Sstevel@tonic-gate/ 3950Sstevel@tonic-gate/ } else if (HI(x) < HI(y)) { 3960Sstevel@tonic-gate/ /* HI(x) < HI(y) => x < y => result is 0 */ 3970Sstevel@tonic-gate/ 3980Sstevel@tonic-gate/ /* return result */ 3990Sstevel@tonic-gate/ return (0); 4000Sstevel@tonic-gate/ 4010Sstevel@tonic-gate/ } else { 4020Sstevel@tonic-gate/ /* 4030Sstevel@tonic-gate/ * uint64_t by uint64_t division, resulting in a one-uint32_t 4040Sstevel@tonic-gate/ * result 4050Sstevel@tonic-gate/ */ 4060Sstevel@tonic-gate/ uint32_t y0, y1; 4070Sstevel@tonic-gate/ uint32_t x1, x0; 4080Sstevel@tonic-gate/ uint32_t q0; 4090Sstevel@tonic-gate/ unsigned normshift; 4100Sstevel@tonic-gate/ 4110Sstevel@tonic-gate/ /* normalize by shifting x and y so MSB(y) == 1 */ 4120Sstevel@tonic-gate/ HIBIT(HI(y), normshift); /* index of highest 1 bit */ 4130Sstevel@tonic-gate/ normshift = 31 - normshift; 4140Sstevel@tonic-gate/ 4150Sstevel@tonic-gate/ if (normshift == 0) { 4160Sstevel@tonic-gate/ /* no shifting needed, and x < 2*y so q <= 1 */ 4170Sstevel@tonic-gate/ y1 = HI(y); 4180Sstevel@tonic-gate/ y0 = LO(y); 4190Sstevel@tonic-gate/ x1 = HI(x); 4200Sstevel@tonic-gate/ x0 = LO(x); 4210Sstevel@tonic-gate/ 4220Sstevel@tonic-gate/ /* if x >= y then q = 1 (note x1 >= y1) */ 4230Sstevel@tonic-gate/ if (x1 > y1 || x0 >= y0) { 4240Sstevel@tonic-gate/ q0 = 1; 4250Sstevel@tonic-gate/ /* subtract y from x to get remainder */ 4260Sstevel@tonic-gate/ /* A_SUB2(y0, y1, x0, x1); */ 4270Sstevel@tonic-gate/ } else { 4280Sstevel@tonic-gate/ q0 = 0; 4290Sstevel@tonic-gate/ } 4300Sstevel@tonic-gate/ 4310Sstevel@tonic-gate/ /* return result */ 4320Sstevel@tonic-gate/ return (q0); 4330Sstevel@tonic-gate/ 4340Sstevel@tonic-gate/ } else { 4350Sstevel@tonic-gate/ /* 4360Sstevel@tonic-gate/ * the last case: result is one uint32_t, but we need to 4370Sstevel@tonic-gate/ * normalize 4380Sstevel@tonic-gate/ */ 4390Sstevel@tonic-gate/ uint64_t dt; 4400Sstevel@tonic-gate/ uint32_t t0, t1, x2; 4410Sstevel@tonic-gate/ 4420Sstevel@tonic-gate/ /* normalize y */ 4430Sstevel@tonic-gate/ dt = (y << normshift); 4440Sstevel@tonic-gate/ y1 = HI(dt); 4450Sstevel@tonic-gate/ y0 = LO(dt); 4460Sstevel@tonic-gate/ 4470Sstevel@tonic-gate/ /* normalize x (we need 3 uint32_ts!!!) */ 4480Sstevel@tonic-gate/ x2 = (HI(x) >> (32 - normshift)); 4490Sstevel@tonic-gate/ dt = (x << normshift); 4500Sstevel@tonic-gate/ x1 = HI(dt); 4510Sstevel@tonic-gate/ x0 = LO(dt); 4520Sstevel@tonic-gate/ 4530Sstevel@tonic-gate/ /* estimate q0, and reduce x to a two uint32_t value */ 4540Sstevel@tonic-gate/ A_DIV32(x1, x2, y1, q0, x1); 4550Sstevel@tonic-gate/ 4560Sstevel@tonic-gate/ /* adjust q0 down if too high */ 4570Sstevel@tonic-gate/ /* 4580Sstevel@tonic-gate/ * because of the limited range of x2 we can only be 4590Sstevel@tonic-gate/ * one off 4600Sstevel@tonic-gate/ */ 4610Sstevel@tonic-gate/ A_MUL32(y0, q0, t0, t1); 4620Sstevel@tonic-gate/ if (t1 > x1 || (t1 == x1 && t0 > x0)) { 4630Sstevel@tonic-gate/ q0--; 4640Sstevel@tonic-gate/ } 4650Sstevel@tonic-gate/ /* return result */ 4660Sstevel@tonic-gate/ return (q0); 4670Sstevel@tonic-gate/ } 4680Sstevel@tonic-gate/ } 4690Sstevel@tonic-gate/ } 4700Sstevel@tonic-gate ENTRY(UDiv) 4710Sstevel@tonic-gate pushl %ebp 4720Sstevel@tonic-gate pushl %edi 4730Sstevel@tonic-gate pushl %esi 4740Sstevel@tonic-gate subl $40, %esp 4750Sstevel@tonic-gate movl %edx, 36(%esp) / x, x 4760Sstevel@tonic-gate movl 60(%esp), %edx / y, 4770Sstevel@tonic-gate testl %edx, %edx / tmp62 4780Sstevel@tonic-gate movl %eax, 32(%esp) / x, x 4790Sstevel@tonic-gate movl %edx, %ecx / tmp61, tmp62 4800Sstevel@tonic-gate movl %edx, %eax /, tmp61 4810Sstevel@tonic-gate jne .LL26 4820Sstevel@tonic-gate movl 36(%esp), %esi / x, 4830Sstevel@tonic-gate cmpl 56(%esp), %esi / y, tmp67 4840Sstevel@tonic-gate movl %esi, %eax /, tmp67 4850Sstevel@tonic-gate movl %esi, %edx / tmp67, div_hi 4860Sstevel@tonic-gate jb .LL28 4870Sstevel@tonic-gate movl %ecx, %edx / tmp62, div_hi 4880Sstevel@tonic-gate divl 56(%esp) / y 4890Sstevel@tonic-gate movl %eax, %ecx /, q1 4900Sstevel@tonic-gate.LL28: 4910Sstevel@tonic-gate xorl %esi, %esi / <result> 4920Sstevel@tonic-gate movl %ecx, %edi / <result>, <result> 4930Sstevel@tonic-gate movl 32(%esp), %eax / x, q0 4940Sstevel@tonic-gate xorl %ecx, %ecx / q0 4950Sstevel@tonic-gate divl 56(%esp) / y 4960Sstevel@tonic-gate addl %eax, %esi / q0, <result> 4970Sstevel@tonic-gate adcl %ecx, %edi / q0, <result> 4980Sstevel@tonic-gate.LL25: 4990Sstevel@tonic-gate addl $40, %esp 5000Sstevel@tonic-gate movl %esi, %eax / <result>, <result> 5010Sstevel@tonic-gate popl %esi 5020Sstevel@tonic-gate movl %edi, %edx / <result>, <result> 5030Sstevel@tonic-gate popl %edi 5040Sstevel@tonic-gate popl %ebp 5050Sstevel@tonic-gate ret 5060Sstevel@tonic-gate .align 16 5070Sstevel@tonic-gate.LL26: 5080Sstevel@tonic-gate movl 36(%esp), %esi / x, 5090Sstevel@tonic-gate xorl %edi, %edi 5100Sstevel@tonic-gate movl %esi, 24(%esp) / tmp1, 5110Sstevel@tonic-gate movl %edi, 28(%esp) 5120Sstevel@tonic-gate xorl %esi, %esi / <result> 5130Sstevel@tonic-gate xorl %edi, %edi / <result> 5140Sstevel@tonic-gate cmpl %eax, 24(%esp) / tmp61, 5150Sstevel@tonic-gate jb .LL25 5160Sstevel@tonic-gate bsrl %eax,%ebp / tmp61, normshift 5170Sstevel@tonic-gate movl $31, %eax /, tmp85 5180Sstevel@tonic-gate subl %ebp, %eax / normshift, normshift 5190Sstevel@tonic-gate jne .LL32 5200Sstevel@tonic-gate movl 24(%esp), %eax /, x1 5210Sstevel@tonic-gate cmpl %ecx, %eax / tmp62, x1 5220Sstevel@tonic-gate movl 56(%esp), %esi / y, y0 5230Sstevel@tonic-gate movl 32(%esp), %edx / x, x0 5240Sstevel@tonic-gate ja .LL34 5250Sstevel@tonic-gate xorl %eax, %eax / q0 5260Sstevel@tonic-gate cmpl %esi, %edx / y0, x0 5270Sstevel@tonic-gate jb .LL35 5280Sstevel@tonic-gate.LL34: 5290Sstevel@tonic-gate movl $1, %eax /, q0 5300Sstevel@tonic-gate.LL35: 5310Sstevel@tonic-gate movl %eax, %esi / q0, <result> 5320Sstevel@tonic-gate xorl %edi, %edi / <result> 5330Sstevel@tonic-gate.LL45: 5340Sstevel@tonic-gate addl $40, %esp 5350Sstevel@tonic-gate movl %esi, %eax / <result>, <result> 5360Sstevel@tonic-gate popl %esi 5370Sstevel@tonic-gate movl %edi, %edx / <result>, <result> 5380Sstevel@tonic-gate popl %edi 5390Sstevel@tonic-gate popl %ebp 5400Sstevel@tonic-gate ret 5410Sstevel@tonic-gate .align 16 5420Sstevel@tonic-gate.LL32: 5430Sstevel@tonic-gate movb %al, %cl 5440Sstevel@tonic-gate movl 56(%esp), %esi / y, 5450Sstevel@tonic-gate movl 60(%esp), %edi / y, 5460Sstevel@tonic-gate shldl %esi, %edi 5470Sstevel@tonic-gate sall %cl, %esi 5480Sstevel@tonic-gate andl $32, %ecx 5490Sstevel@tonic-gate jne .LL43 5500Sstevel@tonic-gate.LL40: 5510Sstevel@tonic-gate movl $32, %ecx /, tmp96 5520Sstevel@tonic-gate subl %eax, %ecx / normshift, tmp96 5530Sstevel@tonic-gate movl %edi, %edx 5540Sstevel@tonic-gate movl %edi, 20(%esp) /, dt 5550Sstevel@tonic-gate movl 24(%esp), %ebp /, x2 5560Sstevel@tonic-gate xorl %edi, %edi 5570Sstevel@tonic-gate shrl %cl, %ebp / tmp96, x2 5580Sstevel@tonic-gate movl %esi, 16(%esp) /, dt 5590Sstevel@tonic-gate movb %al, %cl 5600Sstevel@tonic-gate movl 32(%esp), %esi / x, dt 5610Sstevel@tonic-gate movl %edi, 12(%esp) 5620Sstevel@tonic-gate movl 36(%esp), %edi / x, dt 5630Sstevel@tonic-gate shldl %esi, %edi /, dt, dt 5640Sstevel@tonic-gate sall %cl, %esi /, dt 5650Sstevel@tonic-gate andl $32, %ecx 5660Sstevel@tonic-gate movl %edx, 8(%esp) 5670Sstevel@tonic-gate je .LL41 5680Sstevel@tonic-gate movl %esi, %edi / dt, dt 5690Sstevel@tonic-gate xorl %esi, %esi / dt 5700Sstevel@tonic-gate.LL41: 5710Sstevel@tonic-gate xorl %ecx, %ecx 5720Sstevel@tonic-gate movl %edi, %eax / tmp1, 5730Sstevel@tonic-gate movl %ebp, %edx / x2, 5740Sstevel@tonic-gate divl 8(%esp) 5750Sstevel@tonic-gate movl %edx, %ebp /, x1 5760Sstevel@tonic-gate movl %ecx, 4(%esp) 5770Sstevel@tonic-gate movl %eax, %ecx /, q0 5780Sstevel@tonic-gate movl 16(%esp), %eax / dt, 5790Sstevel@tonic-gate mull %ecx / q0 5800Sstevel@tonic-gate cmpl %ebp, %edx / x1, t1 5810Sstevel@tonic-gate movl %edi, (%esp) 5820Sstevel@tonic-gate movl %esi, %edi / dt, x0 5830Sstevel@tonic-gate ja .LL38 5840Sstevel@tonic-gate je .LL44 5850Sstevel@tonic-gate.LL39: 5860Sstevel@tonic-gate movl %ecx, %esi / q0, <result> 5870Sstevel@tonic-gate.LL46: 5880Sstevel@tonic-gate xorl %edi, %edi / <result> 5890Sstevel@tonic-gate jmp .LL45 5900Sstevel@tonic-gate.LL44: 5910Sstevel@tonic-gate cmpl %edi, %eax / x0, t0 5920Sstevel@tonic-gate jbe .LL39 5930Sstevel@tonic-gate.LL38: 5940Sstevel@tonic-gate decl %ecx / q0 5950Sstevel@tonic-gate movl %ecx, %esi / q0, <result> 5960Sstevel@tonic-gate jmp .LL46 5970Sstevel@tonic-gate.LL43: 5980Sstevel@tonic-gate movl %esi, %edi 5990Sstevel@tonic-gate xorl %esi, %esi 6000Sstevel@tonic-gate jmp .LL40 6010Sstevel@tonic-gate SET_SIZE(UDiv) 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate/* 6040Sstevel@tonic-gate * __udiv64 6050Sstevel@tonic-gate * 6060Sstevel@tonic-gate * Perform division of two unsigned 64-bit quantities, returning the 6070Sstevel@tonic-gate * quotient in %edx:%eax. __udiv64 pops the arguments on return, 6080Sstevel@tonic-gate */ 6090Sstevel@tonic-gate ENTRY(__udiv64) 6100Sstevel@tonic-gate movl 4(%esp), %eax / x, x 6110Sstevel@tonic-gate movl 8(%esp), %edx / x, x 6120Sstevel@tonic-gate pushl 16(%esp) / y 6130Sstevel@tonic-gate pushl 16(%esp) 6140Sstevel@tonic-gate call UDiv 6150Sstevel@tonic-gate addl $8, %esp 6160Sstevel@tonic-gate ret $16 6170Sstevel@tonic-gate SET_SIZE(__udiv64) 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate/* 6200Sstevel@tonic-gate * __urem64 6210Sstevel@tonic-gate * 6220Sstevel@tonic-gate * Perform division of two unsigned 64-bit quantities, returning the 6230Sstevel@tonic-gate * remainder in %edx:%eax. __urem64 pops the arguments on return 6240Sstevel@tonic-gate */ 6250Sstevel@tonic-gate ENTRY(__urem64) 6260Sstevel@tonic-gate subl $12, %esp 6270Sstevel@tonic-gate movl %esp, %ecx /, tmp65 6280Sstevel@tonic-gate movl 16(%esp), %eax / x, x 6290Sstevel@tonic-gate movl 20(%esp), %edx / x, x 6300Sstevel@tonic-gate pushl %ecx / tmp65 6310Sstevel@tonic-gate pushl 32(%esp) / y 6320Sstevel@tonic-gate pushl 32(%esp) 6330Sstevel@tonic-gate call UDivRem 6340Sstevel@tonic-gate movl 12(%esp), %eax / rem, rem 6350Sstevel@tonic-gate movl 16(%esp), %edx / rem, rem 6360Sstevel@tonic-gate addl $24, %esp 6370Sstevel@tonic-gate ret $16 6380Sstevel@tonic-gate SET_SIZE(__urem64) 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate/* 6410Sstevel@tonic-gate * __div64 6420Sstevel@tonic-gate * 6430Sstevel@tonic-gate * Perform division of two signed 64-bit quantities, returning the 6440Sstevel@tonic-gate * quotient in %edx:%eax. __div64 pops the arguments on return. 6450Sstevel@tonic-gate */ 6460Sstevel@tonic-gate/ int64_t 6470Sstevel@tonic-gate/ __div64(int64_t x, int64_t y) 6480Sstevel@tonic-gate/ { 6490Sstevel@tonic-gate/ int negative; 6500Sstevel@tonic-gate/ uint64_t xt, yt, r; 6510Sstevel@tonic-gate/ 6520Sstevel@tonic-gate/ if (x < 0) { 6530Sstevel@tonic-gate/ xt = -(uint64_t) x; 6540Sstevel@tonic-gate/ negative = 1; 6550Sstevel@tonic-gate/ } else { 6560Sstevel@tonic-gate/ xt = x; 6570Sstevel@tonic-gate/ negative = 0; 6580Sstevel@tonic-gate/ } 6590Sstevel@tonic-gate/ if (y < 0) { 6600Sstevel@tonic-gate/ yt = -(uint64_t) y; 6610Sstevel@tonic-gate/ negative ^= 1; 6620Sstevel@tonic-gate/ } else { 6630Sstevel@tonic-gate/ yt = y; 6640Sstevel@tonic-gate/ } 6650Sstevel@tonic-gate/ r = UDiv(xt, yt); 6660Sstevel@tonic-gate/ return (negative ? (int64_t) - r : r); 6670Sstevel@tonic-gate/ } 6680Sstevel@tonic-gate ENTRY(__div64) 6690Sstevel@tonic-gate pushl %ebp 6700Sstevel@tonic-gate pushl %edi 6710Sstevel@tonic-gate pushl %esi 6720Sstevel@tonic-gate subl $8, %esp 6730Sstevel@tonic-gate movl 28(%esp), %edx / x, x 6740Sstevel@tonic-gate testl %edx, %edx / x 6750Sstevel@tonic-gate movl 24(%esp), %eax / x, x 6760Sstevel@tonic-gate movl 32(%esp), %esi / y, y 6770Sstevel@tonic-gate movl 36(%esp), %edi / y, y 6780Sstevel@tonic-gate js .LL84 6790Sstevel@tonic-gate xorl %ebp, %ebp / negative 6800Sstevel@tonic-gate testl %edi, %edi / y 6810Sstevel@tonic-gate movl %eax, (%esp) / x, xt 6820Sstevel@tonic-gate movl %edx, 4(%esp) / x, xt 6830Sstevel@tonic-gate movl %esi, %eax / y, yt 6840Sstevel@tonic-gate movl %edi, %edx / y, yt 6850Sstevel@tonic-gate js .LL85 6860Sstevel@tonic-gate.LL82: 6870Sstevel@tonic-gate pushl %edx / yt 6880Sstevel@tonic-gate pushl %eax / yt 6890Sstevel@tonic-gate movl 8(%esp), %eax / xt, xt 6900Sstevel@tonic-gate movl 12(%esp), %edx / xt, xt 6910Sstevel@tonic-gate call UDiv 6920Sstevel@tonic-gate popl %ecx 6930Sstevel@tonic-gate testl %ebp, %ebp / negative 6940Sstevel@tonic-gate popl %esi 6950Sstevel@tonic-gate je .LL83 6960Sstevel@tonic-gate negl %eax / r 6970Sstevel@tonic-gate adcl $0, %edx /, r 6980Sstevel@tonic-gate negl %edx / r 6990Sstevel@tonic-gate.LL83: 7000Sstevel@tonic-gate addl $8, %esp 7010Sstevel@tonic-gate popl %esi 7020Sstevel@tonic-gate popl %edi 7030Sstevel@tonic-gate popl %ebp 7040Sstevel@tonic-gate ret $16 7050Sstevel@tonic-gate .align 16 7060Sstevel@tonic-gate.LL84: 7070Sstevel@tonic-gate negl %eax / x 7080Sstevel@tonic-gate adcl $0, %edx /, x 7090Sstevel@tonic-gate negl %edx / x 7100Sstevel@tonic-gate testl %edi, %edi / y 7110Sstevel@tonic-gate movl %eax, (%esp) / x, xt 7120Sstevel@tonic-gate movl %edx, 4(%esp) / x, xt 7130Sstevel@tonic-gate movl $1, %ebp /, negative 7140Sstevel@tonic-gate movl %esi, %eax / y, yt 7150Sstevel@tonic-gate movl %edi, %edx / y, yt 7160Sstevel@tonic-gate jns .LL82 7170Sstevel@tonic-gate .align 16 7180Sstevel@tonic-gate.LL85: 7190Sstevel@tonic-gate negl %eax / yt 7200Sstevel@tonic-gate adcl $0, %edx /, yt 7210Sstevel@tonic-gate negl %edx / yt 7220Sstevel@tonic-gate xorl $1, %ebp /, negative 7230Sstevel@tonic-gate jmp .LL82 7240Sstevel@tonic-gate SET_SIZE(__div64) 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate/* 7270Sstevel@tonic-gate * __rem64 7280Sstevel@tonic-gate * 7290Sstevel@tonic-gate * Perform division of two signed 64-bit quantities, returning the 7300Sstevel@tonic-gate * remainder in %edx:%eax. __rem64 pops the arguments on return. 7310Sstevel@tonic-gate */ 7320Sstevel@tonic-gate/ int64_t 7330Sstevel@tonic-gate/ __rem64(int64_t x, int64_t y) 7340Sstevel@tonic-gate/ { 7350Sstevel@tonic-gate/ uint64_t xt, yt, rem; 7360Sstevel@tonic-gate/ 7370Sstevel@tonic-gate/ if (x < 0) { 7380Sstevel@tonic-gate/ xt = -(uint64_t) x; 7390Sstevel@tonic-gate/ } else { 7400Sstevel@tonic-gate/ xt = x; 7410Sstevel@tonic-gate/ } 7420Sstevel@tonic-gate/ if (y < 0) { 7430Sstevel@tonic-gate/ yt = -(uint64_t) y; 7440Sstevel@tonic-gate/ } else { 7450Sstevel@tonic-gate/ yt = y; 7460Sstevel@tonic-gate/ } 7470Sstevel@tonic-gate/ (void) UDivRem(xt, yt, &rem); 7480Sstevel@tonic-gate/ return (x < 0 ? (int64_t) - rem : rem); 7490Sstevel@tonic-gate/ } 7500Sstevel@tonic-gate ENTRY(__rem64) 7510Sstevel@tonic-gate pushl %edi 7520Sstevel@tonic-gate pushl %esi 7530Sstevel@tonic-gate subl $20, %esp 7540Sstevel@tonic-gate movl 36(%esp), %ecx / x, 7550Sstevel@tonic-gate movl 32(%esp), %esi / x, 7560Sstevel@tonic-gate movl 36(%esp), %edi / x, 7570Sstevel@tonic-gate testl %ecx, %ecx 7580Sstevel@tonic-gate movl 40(%esp), %eax / y, y 7590Sstevel@tonic-gate movl 44(%esp), %edx / y, y 7600Sstevel@tonic-gate movl %esi, (%esp) /, xt 7610Sstevel@tonic-gate movl %edi, 4(%esp) /, xt 7620Sstevel@tonic-gate js .LL92 7630Sstevel@tonic-gate testl %edx, %edx / y 7640Sstevel@tonic-gate movl %eax, %esi / y, yt 7650Sstevel@tonic-gate movl %edx, %edi / y, yt 7660Sstevel@tonic-gate js .LL93 7670Sstevel@tonic-gate.LL90: 7680Sstevel@tonic-gate leal 8(%esp), %eax /, tmp66 7690Sstevel@tonic-gate pushl %eax / tmp66 7700Sstevel@tonic-gate pushl %edi / yt 7710Sstevel@tonic-gate pushl %esi / yt 7720Sstevel@tonic-gate movl 12(%esp), %eax / xt, xt 7730Sstevel@tonic-gate movl 16(%esp), %edx / xt, xt 7740Sstevel@tonic-gate call UDivRem 7750Sstevel@tonic-gate addl $12, %esp 7760Sstevel@tonic-gate movl 36(%esp), %edi / x, 7770Sstevel@tonic-gate testl %edi, %edi 7780Sstevel@tonic-gate movl 8(%esp), %eax / rem, rem 7790Sstevel@tonic-gate movl 12(%esp), %edx / rem, rem 7800Sstevel@tonic-gate js .LL94 7810Sstevel@tonic-gate addl $20, %esp 7820Sstevel@tonic-gate popl %esi 7830Sstevel@tonic-gate popl %edi 7840Sstevel@tonic-gate ret $16 7850Sstevel@tonic-gate .align 16 7860Sstevel@tonic-gate.LL92: 7870Sstevel@tonic-gate negl %esi 7880Sstevel@tonic-gate adcl $0, %edi 7890Sstevel@tonic-gate negl %edi 7900Sstevel@tonic-gate testl %edx, %edx / y 7910Sstevel@tonic-gate movl %esi, (%esp) /, xt 7920Sstevel@tonic-gate movl %edi, 4(%esp) /, xt 7930Sstevel@tonic-gate movl %eax, %esi / y, yt 7940Sstevel@tonic-gate movl %edx, %edi / y, yt 7950Sstevel@tonic-gate jns .LL90 7960Sstevel@tonic-gate .align 16 7970Sstevel@tonic-gate.LL93: 7980Sstevel@tonic-gate negl %esi / yt 7990Sstevel@tonic-gate adcl $0, %edi /, yt 8000Sstevel@tonic-gate negl %edi / yt 8010Sstevel@tonic-gate jmp .LL90 8020Sstevel@tonic-gate .align 16 8030Sstevel@tonic-gate.LL94: 8040Sstevel@tonic-gate negl %eax / rem 8050Sstevel@tonic-gate adcl $0, %edx /, rem 8060Sstevel@tonic-gate addl $20, %esp 8070Sstevel@tonic-gate popl %esi 8080Sstevel@tonic-gate negl %edx / rem 8090Sstevel@tonic-gate popl %edi 8100Sstevel@tonic-gate ret $16 8110Sstevel@tonic-gate SET_SIZE(__rem64) 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate/* 8140Sstevel@tonic-gate * __udivrem64 8150Sstevel@tonic-gate * 8160Sstevel@tonic-gate * Perform division of two unsigned 64-bit quantities, returning the 8170Sstevel@tonic-gate * quotient in %edx:%eax, and the remainder in %ecx:%esi. __udivrem64 8180Sstevel@tonic-gate * pops the arguments on return. 8190Sstevel@tonic-gate */ 8200Sstevel@tonic-gate ENTRY(__udivrem64) 8210Sstevel@tonic-gate subl $12, %esp 8220Sstevel@tonic-gate movl %esp, %ecx /, tmp64 8230Sstevel@tonic-gate movl 16(%esp), %eax / x, x 8240Sstevel@tonic-gate movl 20(%esp), %edx / x, x 8250Sstevel@tonic-gate pushl %ecx / tmp64 8260Sstevel@tonic-gate pushl 32(%esp) / y 8270Sstevel@tonic-gate pushl 32(%esp) 8280Sstevel@tonic-gate call UDivRem 8290Sstevel@tonic-gate movl 16(%esp), %ecx / rem, tmp63 8300Sstevel@tonic-gate movl 12(%esp), %esi / rem 8310Sstevel@tonic-gate addl $24, %esp 8320Sstevel@tonic-gate ret $16 8330Sstevel@tonic-gate SET_SIZE(__udivrem64) 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate/* 8360Sstevel@tonic-gate * Signed division with remainder. 8370Sstevel@tonic-gate */ 8380Sstevel@tonic-gate/ int64_t 8390Sstevel@tonic-gate/ SDivRem(int64_t x, int64_t y, int64_t * pmod) 8400Sstevel@tonic-gate/ { 8410Sstevel@tonic-gate/ int negative; 8420Sstevel@tonic-gate/ uint64_t xt, yt, r, rem; 8430Sstevel@tonic-gate/ 8440Sstevel@tonic-gate/ if (x < 0) { 8450Sstevel@tonic-gate/ xt = -(uint64_t) x; 8460Sstevel@tonic-gate/ negative = 1; 8470Sstevel@tonic-gate/ } else { 8480Sstevel@tonic-gate/ xt = x; 8490Sstevel@tonic-gate/ negative = 0; 8500Sstevel@tonic-gate/ } 8510Sstevel@tonic-gate/ if (y < 0) { 8520Sstevel@tonic-gate/ yt = -(uint64_t) y; 8530Sstevel@tonic-gate/ negative ^= 1; 8540Sstevel@tonic-gate/ } else { 8550Sstevel@tonic-gate/ yt = y; 8560Sstevel@tonic-gate/ } 8570Sstevel@tonic-gate/ r = UDivRem(xt, yt, &rem); 8580Sstevel@tonic-gate/ *pmod = (x < 0 ? (int64_t) - rem : rem); 8590Sstevel@tonic-gate/ return (negative ? (int64_t) - r : r); 8600Sstevel@tonic-gate/ } 8610Sstevel@tonic-gate ENTRY(SDivRem) 8620Sstevel@tonic-gate pushl %ebp 8630Sstevel@tonic-gate pushl %edi 8640Sstevel@tonic-gate pushl %esi 8650Sstevel@tonic-gate subl $24, %esp 8660Sstevel@tonic-gate testl %edx, %edx / x 8670Sstevel@tonic-gate movl %edx, %edi / x, x 8680Sstevel@tonic-gate js .LL73 8690Sstevel@tonic-gate movl 44(%esp), %esi / y, 8700Sstevel@tonic-gate xorl %ebp, %ebp / negative 8710Sstevel@tonic-gate testl %esi, %esi 8720Sstevel@tonic-gate movl %edx, 12(%esp) / x, xt 8730Sstevel@tonic-gate movl %eax, 8(%esp) / x, xt 8740Sstevel@tonic-gate movl 40(%esp), %edx / y, yt 8750Sstevel@tonic-gate movl 44(%esp), %ecx / y, yt 8760Sstevel@tonic-gate js .LL74 8770Sstevel@tonic-gate.LL70: 8780Sstevel@tonic-gate leal 16(%esp), %eax /, tmp70 8790Sstevel@tonic-gate pushl %eax / tmp70 8800Sstevel@tonic-gate pushl %ecx / yt 8810Sstevel@tonic-gate pushl %edx / yt 8820Sstevel@tonic-gate movl 20(%esp), %eax / xt, xt 8830Sstevel@tonic-gate movl 24(%esp), %edx / xt, xt 8840Sstevel@tonic-gate call UDivRem 8850Sstevel@tonic-gate movl %edx, 16(%esp) /, r 8860Sstevel@tonic-gate movl %eax, 12(%esp) /, r 8870Sstevel@tonic-gate addl $12, %esp 8880Sstevel@tonic-gate testl %edi, %edi / x 8890Sstevel@tonic-gate movl 16(%esp), %edx / rem, rem 8900Sstevel@tonic-gate movl 20(%esp), %ecx / rem, rem 8910Sstevel@tonic-gate js .LL75 8920Sstevel@tonic-gate.LL71: 8930Sstevel@tonic-gate movl 48(%esp), %edi / pmod, pmod 8940Sstevel@tonic-gate testl %ebp, %ebp / negative 8950Sstevel@tonic-gate movl %edx, (%edi) / rem,* pmod 8960Sstevel@tonic-gate movl %ecx, 4(%edi) / rem, 8970Sstevel@tonic-gate movl (%esp), %eax / r, r 8980Sstevel@tonic-gate movl 4(%esp), %edx / r, r 8990Sstevel@tonic-gate je .LL72 9000Sstevel@tonic-gate negl %eax / r 9010Sstevel@tonic-gate adcl $0, %edx /, r 9020Sstevel@tonic-gate negl %edx / r 9030Sstevel@tonic-gate.LL72: 9040Sstevel@tonic-gate addl $24, %esp 9050Sstevel@tonic-gate popl %esi 9060Sstevel@tonic-gate popl %edi 9070Sstevel@tonic-gate popl %ebp 9080Sstevel@tonic-gate ret 9090Sstevel@tonic-gate .align 16 9100Sstevel@tonic-gate.LL73: 9110Sstevel@tonic-gate negl %eax 9120Sstevel@tonic-gate adcl $0, %edx 9130Sstevel@tonic-gate movl 44(%esp), %esi / y, 9140Sstevel@tonic-gate negl %edx 9150Sstevel@tonic-gate testl %esi, %esi 9160Sstevel@tonic-gate movl %edx, 12(%esp) /, xt 9170Sstevel@tonic-gate movl %eax, 8(%esp) /, xt 9180Sstevel@tonic-gate movl $1, %ebp /, negative 9190Sstevel@tonic-gate movl 40(%esp), %edx / y, yt 9200Sstevel@tonic-gate movl 44(%esp), %ecx / y, yt 9210Sstevel@tonic-gate jns .LL70 9220Sstevel@tonic-gate .align 16 9230Sstevel@tonic-gate.LL74: 9240Sstevel@tonic-gate negl %edx / yt 9250Sstevel@tonic-gate adcl $0, %ecx /, yt 9260Sstevel@tonic-gate negl %ecx / yt 9270Sstevel@tonic-gate xorl $1, %ebp /, negative 9280Sstevel@tonic-gate jmp .LL70 9290Sstevel@tonic-gate .align 16 9300Sstevel@tonic-gate.LL75: 9310Sstevel@tonic-gate negl %edx / rem 9320Sstevel@tonic-gate adcl $0, %ecx /, rem 9330Sstevel@tonic-gate negl %ecx / rem 9340Sstevel@tonic-gate jmp .LL71 9350Sstevel@tonic-gate SET_SIZE(SDivRem) 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate/* 9380Sstevel@tonic-gate * __divrem64 9390Sstevel@tonic-gate * 9400Sstevel@tonic-gate * Perform division of two signed 64-bit quantities, returning the 9410Sstevel@tonic-gate * quotient in %edx:%eax, and the remainder in %ecx:%esi. __divrem64 9420Sstevel@tonic-gate * pops the arguments on return. 9430Sstevel@tonic-gate */ 9440Sstevel@tonic-gate ENTRY(__divrem64) 9450Sstevel@tonic-gate subl $20, %esp 9460Sstevel@tonic-gate movl %esp, %ecx /, tmp64 9470Sstevel@tonic-gate movl 24(%esp), %eax / x, x 9480Sstevel@tonic-gate movl 28(%esp), %edx / x, x 9490Sstevel@tonic-gate pushl %ecx / tmp64 9500Sstevel@tonic-gate pushl 40(%esp) / y 9510Sstevel@tonic-gate pushl 40(%esp) 9520Sstevel@tonic-gate call SDivRem 9530Sstevel@tonic-gate movl 16(%esp), %ecx 9540Sstevel@tonic-gate movl 12(%esp),%esi / rem 9550Sstevel@tonic-gate addl $32, %esp 9560Sstevel@tonic-gate ret $16 9570Sstevel@tonic-gate SET_SIZE(__divrem64) 958