📄 divdi3.c
字号:
/* 64-bit multiplication and division Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *///#include <stdlib.h>//#include <bits/wordsize.h>#include "db.h"//#include "longlong.h"#define __BITS4 (W_TYPE_SIZE / 4)#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))#ifndef W_TYPE_SIZE#define W_TYPE_SIZE 32#define UWtype USItype#define UHWtype USItype#define UDWtype UDItype#endif/* Define auxiliary asm macros. 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype word product in HIGH_PROD and LOW_PROD. 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a UDWtype product. This is just a variant of umul_ppmm. 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator) divides a UDWtype, composed by the UWtype integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less than DENOMINATOR for correct operation. If, in addition, the most significant bit of DENOMINATOR must be 1, then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator). Like udiv_qrnnd but the numbers are signed. The quotient is rounded towards 0. 5) count_leading_zeros(count, x) counts the number of zero-bits from the msb to the first nonzero bit in the UWtype X. This is the number of steps X needs to be shifted left to set the msb. Undefined for X == 0, unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts from the least significant end. 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, high_addend_2, low_addend_2) adds two UWtype integers, composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is lost. 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, and is lost. If any of these macros are left undefined for a particular CPU, C macros are used. *//* The CPUs come in alphabetical order below. Please add support for more CPUs here, or improve the current support for the CPUs below! (E.g. WE32100, IBM360.) */#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl %5,%1\n\tadcl %3,%0" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "%0" ((USItype) (ah)), \ "g" ((USItype) (bh)), \ "%1" ((USItype) (al)), \ "g" ((USItype) (bl)))#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "0" ((USItype) (ah)), \ "g" ((USItype) (bh)), \ "1" ((USItype) (al)), \ "g" ((USItype) (bl)))#define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ : "=a" ((USItype) (w0)), \ "=d" ((USItype) (w1)) \ : "%0" ((USItype) (u)), \ "rm" ((USItype) (v)))#define udiv_qrnnd(q, r, n1, n0, dv) \ __asm__ ("divl %4" \ : "=a" ((USItype) (q)), \ "=d" ((USItype) (r)) \ : "0" ((USItype) (n0)), \ "1" ((USItype) (n1)), \ "rm" ((USItype) (dv)))#define count_leading_zeros(count, x) \ do { \ USItype __cbtmp; \ __asm__ ("bsrl %1,%0" \ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ (count) = __cbtmp ^ 31; \ } while (0)#define count_trailing_zeros(count, x) \ __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))#define UMUL_TIME 40#define UDIV_TIME 40#endif /* 80x86 */#ifndef UDIV_NEEDS_NORMALIZATION#define UDIV_NEEDS_NORMALIZATION 0#endifstatic UDWtype__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp){ DWunion ww; DWunion nn, dd; DWunion rr; unsigned int d0, d1, n0, n1, n2; UWtype q0, q1; UWtype b, bm; nn.ll = n; dd.ll = d; d0 = dd.s.low; d1 = dd.s.high; n0 = nn.s.low; n1 = nn.s.high;#if !UDIV_NEEDS_NORMALIZATION if (d1 == 0) { if (d0 > n1) { /* 0q = nn / 0D */ udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ udiv_qrnnd (q1, n1, 0, n1, d0); udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0. */ } if (rp != 0) { rr.s.low = n0; rr.s.high = 0; *rp = rr.ll; } }#else /* UDIV_NEEDS_NORMALIZATION */ if (d1 == 0) { if (d0 > n1) { /* 0q = nn / 0D */ count_leading_zeros (bm, d0); if (bm != 0) { /* Normalize, i.e. make the most significant bit of the denominator set. */ d0 = d0 << bm; n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); n0 = n0 << bm; } udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0 >> bm. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ count_leading_zeros (bm, d0); if (bm == 0) { /* From (n1 >= d0) /\ (the most significant bit of d0 is set), conclude (the most significant bit of n1 is set) /\ (the leading quotient digit q1 = 1). This special case is necessary, not an optimization. (Shifts counts of W_TYPE_SIZE are undefined.) */ n1 -= d0; q1 = 1; } else { /* Normalize. */ b = W_TYPE_SIZE - bm; d0 = d0 << bm; n2 = n1 >> b; n1 = (n1 << bm) | (n0 >> b); n0 = n0 << bm; udiv_qrnnd (q1, n1, n2, n1, d0); } /* n1 != d0... */ udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0 >> bm. */ } if (rp != 0) { rr.s.low = n0 >> bm; rr.s.high = 0; *rp = rr.ll; } }#endif /* UDIV_NEEDS_NORMALIZATION */ else { if (d1 > n1) { /* 00 = nn / DD */ q0 = 0; q1 = 0; /* Remainder in n1n0. */ if (rp != 0) { rr.s.low = n0; rr.s.high = n1; *rp = rr.ll; } } else { /* 0q = NN / dd */ count_leading_zeros (bm, d1); if (bm == 0) { /* From (n1 >= d1) /\ (the most significant bit of d1 is set), conclude (the most significant bit of n1 is set) /\ (the quotient digit q0 = 0 or 1). This special case is necessary, not an optimization. */ /* The condition on the next line takes advantage of that n1 >= d1 (true due to program flow). */ if (n1 > d1 || n0 >= d0) { q0 = 1; sub_ddmmss (n1, n0, n1, n0, d1, d0); } else q0 = 0; q1 = 0; if (rp != 0) { rr.s.low = n0; rr.s.high = n1; *rp = rr.ll; } } else { UWtype m1, m0; /* Normalize. */ b = W_TYPE_SIZE - bm; d1 = (d1 << bm) | (d0 >> b); d0 = d0 << bm; n2 = n1 >> b; n1 = (n1 << bm) | (n0 >> b); n0 = n0 << bm; udiv_qrnnd (q0, n1, n2, n1, d1); umul_ppmm (m1, m0, q0, d0); if (m1 > n1 || (m1 == n1 && m0 > n0)) { q0--; sub_ddmmss (m1, m0, m1, m0, d1, d0); } q1 = 0; /* Remainder in (n1n0 - m1m0) >> bm. */ if (rp != 0) { sub_ddmmss (n1, n0, n1, n0, m1, m0); rr.s.low = (n1 << b) | (n0 >> bm); rr.s.high = n1 >> bm; *rp = rr.ll; } } } } ww.s.low = q0; ww.s.high = q1; return ww.ll;}DWtype__divdi3 (DWtype u, DWtype v){ Wtype c = 0; DWtype w; if (u < 0) { c = ~c; u = -u; } if (v < 0) { c = ~c; v = -v; } w = __udivmoddi4 (u, v, NULL); if (c) w = -w; return w;}DWtype__moddi3 (DWtype u, DWtype v){ Wtype c = 0; DWtype w; if (u < 0) { c = ~c; u = -u; } if (v < 0) v = -v; __udivmoddi4 (u, v, &w); if (c) w = -w; return w;}UDWtype__udivdi3 (UDWtype u, UDWtype v){ return __udivmoddi4 (u, v, NULL);}UDWtype__umoddi3 (UDWtype u, UDWtype v){ UDWtype w; __udivmoddi4 (u, v, &w); return w;}/* We declare these with compat_symbol so that they are not visible at link time. Programs must use the functions from libgcc. */#if defined HAVE_ELF && defined SHARED && defined DO_VERSIONING# include <shlib-compat.h>compat_symbol (libc, __divdi3, __divdi3, GLIBC_2_0);compat_symbol (libc, __moddi3, __moddi3, GLIBC_2_0);compat_symbol (libc, __udivdi3, __udivdi3, GLIBC_2_0);compat_symbol (libc, __umoddi3, __umoddi3, GLIBC_2_0);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -