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