1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23/* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28#pragma ident "%Z%%M% %I% %E% SMI" 29 30 .file "%M%" 31 32#include <SYS.h> 33 34/* 35 * C support for 64-bit modulo and division. 36 * GNU routines callable from C (though generated by the compiler). 37 * Hand-customized compiler output - see comments for details. 38 */ 39 40#if defined(__lint) 41 42/*ARGSUSED*/ 43uint64_t 44__udivdi3(uint64_t a, uint64_t b) 45{ return (0); } 46 47/*ARGSUSED*/ 48uint64_t 49__umoddi3(uint64_t a, uint64_t b) 50{ return (0); } 51 52/*ARGSUSED*/ 53int64_t 54__divdi3(int64_t a, int64_t b) 55{ return (0); } 56 57/*ARGSUSED*/ 58int64_t 59__moddi3(int64_t a, int64_t b) 60{ return (0); } 61 62#else 63 64/* 65 * __udivdi3 66 * 67 * Perform division of two unsigned 64-bit quantities, returning the 68 * quotient in %edx:%eax. 69 */ 70 ENTRY(__udivdi3) 71 movl 4(%esp), %eax / x, x 72 movl 8(%esp), %edx / x, x 73 pushl 16(%esp) / y 74 pushl 16(%esp) 75 call UDiv 76 addl $8, %esp 77 ret 78 SET_SIZE(__udivdi3) 79 80/* 81 * __umoddi3 82 * 83 * Perform division of two unsigned 64-bit quantities, returning the 84 * remainder in %edx:%eax. 85 */ 86 ENTRY(__umoddi3) 87 subl $12, %esp 88 movl %esp, %ecx /, tmp65 89 movl 16(%esp), %eax / x, x 90 movl 20(%esp), %edx / x, x 91 pushl %ecx / tmp65 92 pushl 32(%esp) / y 93 pushl 32(%esp) 94 call UDivRem 95 movl 12(%esp), %eax / rem, rem 96 movl 16(%esp), %edx / rem, rem 97 addl $24, %esp 98 ret 99 SET_SIZE(__umoddi3) 100 101/* 102 * __divdi3 103 * 104 * Perform division of two signed 64-bit quantities, returning the 105 * quotient in %edx:%eax. 106 */ 107/ int64_t 108/ __divdi3(int64_t x, int64_t y) 109/ { 110/ int negative; 111/ uint64_t xt, yt, r; 112/ 113/ if (x < 0) { 114/ xt = -(uint64_t) x; 115/ negative = 1; 116/ } else { 117/ xt = x; 118/ negative = 0; 119/ } 120/ if (y < 0) { 121/ yt = -(uint64_t) y; 122/ negative ^= 1; 123/ } else { 124/ yt = y; 125/ } 126/ r = UDiv(xt, yt); 127/ return (negative ? (int64_t) - r : r); 128/ } 129 ENTRY(__divdi3) 130 pushl %ebp 131 pushl %edi 132 pushl %esi 133 subl $8, %esp 134 movl 28(%esp), %edx / x, x 135 testl %edx, %edx / x 136 movl 24(%esp), %eax / x, x 137 movl 32(%esp), %esi / y, y 138 movl 36(%esp), %edi / y, y 139 js .LL55 140 xorl %ebp, %ebp / negative 141 testl %edi, %edi / y 142 movl %eax, (%esp) / x, xt 143 movl %edx, 4(%esp) / x, xt 144 movl %esi, %eax / y, yt 145 movl %edi, %edx / y, yt 146 js .LL56 147.LL53: 148 pushl %edx / yt 149 pushl %eax / yt 150 movl 8(%esp), %eax / xt, xt 151 movl 12(%esp), %edx / xt, xt 152 call UDiv 153 popl %ecx 154 testl %ebp, %ebp / negative 155 popl %esi 156 je .LL54 157 negl %eax / r 158 adcl $0, %edx /, r 159 negl %edx / r 160.LL54: 161 addl $8, %esp 162 popl %esi 163 popl %edi 164 popl %ebp 165 ret 166 .align 16 167.LL55: 168 negl %eax / x 169 adcl $0, %edx /, x 170 negl %edx / x 171 testl %edi, %edi / y 172 movl %eax, (%esp) / x, xt 173 movl %edx, 4(%esp) / x, xt 174 movl $1, %ebp /, negative 175 movl %esi, %eax / y, yt 176 movl %edi, %edx / y, yt 177 jns .LL53 178 .align 16 179.LL56: 180 negl %eax / yt 181 adcl $0, %edx /, yt 182 negl %edx / yt 183 xorl $1, %ebp /, negative 184 jmp .LL53 185 SET_SIZE(__divdi3) 186 187/* 188 * __moddi3 189 * 190 * Perform division of two signed 64-bit quantities, returning the 191 * quotient in %edx:%eax. 192 */ 193/ int64_t 194/ __moddi3(int64_t x, int64_t y) 195/ { 196/ uint64_t xt, yt, rem; 197/ 198/ if (x < 0) { 199/ xt = -(uint64_t) x; 200/ } else { 201/ xt = x; 202/ } 203/ if (y < 0) { 204/ yt = -(uint64_t) y; 205/ } else { 206/ yt = y; 207/ } 208/ (void) UDivRem(xt, yt, &rem); 209/ return (x < 0 ? (int64_t) - rem : rem); 210/ } 211 ENTRY(__moddi3) 212 pushl %edi 213 pushl %esi 214 subl $20, %esp 215 movl 36(%esp), %ecx / x, 216 movl 32(%esp), %esi / x, 217 movl 36(%esp), %edi / x, 218 testl %ecx, %ecx 219 movl 40(%esp), %eax / y, y 220 movl 44(%esp), %edx / y, y 221 movl %esi, (%esp) /, xt 222 movl %edi, 4(%esp) /, xt 223 js .LL63 224 testl %edx, %edx / y 225 movl %eax, %esi / y, yt 226 movl %edx, %edi / y, yt 227 js .LL64 228.LL61: 229 leal 8(%esp), %eax /, tmp66 230 pushl %eax / tmp66 231 pushl %edi / yt 232 pushl %esi / yt 233 movl 12(%esp), %eax / xt, xt 234 movl 16(%esp), %edx / xt, xt 235 call UDivRem 236 addl $12, %esp 237 movl 36(%esp), %edi / x, 238 testl %edi, %edi 239 movl 8(%esp), %eax / rem, rem 240 movl 12(%esp), %edx / rem, rem 241 js .LL65 242 addl $20, %esp 243 popl %esi 244 popl %edi 245 ret 246 .align 16 247.LL63: 248 negl %esi 249 adcl $0, %edi 250 negl %edi 251 testl %edx, %edx / y 252 movl %esi, (%esp) /, xt 253 movl %edi, 4(%esp) /, xt 254 movl %eax, %esi / y, yt 255 movl %edx, %edi / y, yt 256 jns .LL61 257 .align 16 258.LL64: 259 negl %esi / yt 260 adcl $0, %edi /, yt 261 negl %edi / yt 262 jmp .LL61 263 .align 16 264.LL65: 265 negl %eax / rem 266 adcl $0, %edx /, rem 267 addl $20, %esp 268 popl %esi 269 negl %edx / rem 270 popl %edi 271 ret 272 SET_SIZE(__moddi3) 273 274#endif /* __lint */ 275