153430Sbostic /*- 253430Sbostic * Copyright (c) 1992 The Regents of the University of California. 353430Sbostic * All rights reserved. 453430Sbostic * 553430Sbostic * %sccs.include.redist.c% 653430Sbostic */ 753430Sbostic 853430Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*53459Sbostic static char sccsid[] = "@(#)qdivrem.c 5.5 (Berkeley) 05/12/92"; 1053430Sbostic #endif /* LIBC_SCCS and not lint */ 1153430Sbostic 12*53459Sbostic /* Copyright (C) 1989, 1992 Free Software Foundation, Inc. 13*53459Sbostic 14*53459Sbostic This file is part of GNU CC. 15*53459Sbostic 16*53459Sbostic GNU CC is free software; you can redistribute it and/or modify 17*53459Sbostic it under the terms of the GNU General Public License as published by 18*53459Sbostic the Free Software Foundation; either version 2, or (at your option) 19*53459Sbostic any later version. 20*53459Sbostic 21*53459Sbostic GNU CC is distributed in the hope that it will be useful, 22*53459Sbostic but WITHOUT ANY WARRANTY; without even the implied warranty of 23*53459Sbostic MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24*53459Sbostic GNU General Public License for more details. 25*53459Sbostic 26*53459Sbostic You should have received a copy of the GNU General Public License 27*53459Sbostic along with GNU CC; see the file COPYING. If not, write to 28*53459Sbostic the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 29*53459Sbostic 30*53459Sbostic /* As a special exception, if you link this library with files 31*53459Sbostic compiled with GCC to produce an executable, this does not cause 32*53459Sbostic the resulting executable to be covered by the GNU General Public License. 33*53459Sbostic This exception does not however invalidate any other reasons why 34*53459Sbostic the executable file might be covered by the GNU General Public License. */ 35*53459Sbostic 3653455Sbostic #include <unistd.h> 3753455Sbostic 3851748Smckusick #include "longlong.h" 3951748Smckusick 4051748Smckusick static int bshift (); 4151748Smckusick 4251748Smckusick /* Divide a by b, producing quotient q and remainder r. 4351748Smckusick 4451748Smckusick sizeof a is m 4551748Smckusick sizeof b is n 4651748Smckusick sizeof q is m - n 4751748Smckusick sizeof r is n 4851748Smckusick 4951748Smckusick The quotient must fit in m - n bytes, i.e., the most significant 5051748Smckusick n digits of a must be less than b, and m must be greater than n. */ 5151748Smckusick 5251748Smckusick /* The name of this used to be __div_internal, 5351748Smckusick but that is too long for SYSV. */ 5451748Smckusick 5551748Smckusick void 5651748Smckusick __bdiv (a, b, q, r, m, n) 5751748Smckusick unsigned short *a, *b, *q, *r; 5853455Sbostic unsigned long m, n; 5951748Smckusick { 6051748Smckusick unsigned long qhat, rhat; 6151748Smckusick unsigned long acc; 6253455Sbostic unsigned short array[12]; 6353455Sbostic unsigned short *u, *v, *u0, *u1, *u2; 6451748Smckusick unsigned short *v0; 6551748Smckusick int d, qn; 6651748Smckusick int i, j; 6751748Smckusick 6853455Sbostic if (m > 16 || n > 8) { 6953455Sbostic #ifdef KERNEL 7053455Sbostic panic("bdiv: out of space"); 7153455Sbostic #else 7253455Sbostic #define EMSG "bdiv: out of space." 7353455Sbostic (void)write(STDERR_FILENO, EMSG, sizeof(EMSG) - 1); 7453455Sbostic abort(); 7553455Sbostic #endif 7653455Sbostic } 7753455Sbostic u = &array[0]; 7853455Sbostic v = &array[m / sizeof(unsigned short)]; 7951748Smckusick m /= sizeof *a; 8051748Smckusick n /= sizeof *b; 8151748Smckusick qn = m - n; 8251748Smckusick 8351748Smckusick /* Remove leading zero digits from divisor, and the same number of 8451748Smckusick digits (which must be zero) from dividend. */ 8551748Smckusick 8651748Smckusick while (b[big_end (n)] == 0) 8751748Smckusick { 8851748Smckusick r[big_end (n)] = 0; 8951748Smckusick 9051748Smckusick a += little_end (2); 9151748Smckusick b += little_end (2); 9251748Smckusick r += little_end (2); 9351748Smckusick m--; 9451748Smckusick n--; 9551748Smckusick 9651748Smckusick /* Check for zero divisor. */ 9751748Smckusick if (n == 0) 9851750Smckusick { 9951750Smckusick *r /= n; /* force a divide-by-zero trap */ 10051750Smckusick return; 10151750Smckusick } 10251748Smckusick } 10351748Smckusick 10451748Smckusick /* If divisor is a single digit, do short division. */ 10551748Smckusick 10651748Smckusick if (n == 1) 10751748Smckusick { 10851748Smckusick acc = a[big_end (m)]; 10951748Smckusick a += little_end (2); 11051748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 11151748Smckusick { 11251748Smckusick acc = (acc << 16) | a[j]; 11351748Smckusick q[j] = acc / *b; 11451748Smckusick acc = acc % *b; 11551748Smckusick } 11651748Smckusick *r = acc; 11751748Smckusick return; 11851748Smckusick } 11951748Smckusick 12051748Smckusick /* No such luck, must do long division. Shift divisor and dividend 12151748Smckusick left until the high bit of the divisor is 1. */ 12251748Smckusick 12351748Smckusick for (d = 0; d < 16; d++) 12451748Smckusick if (b[big_end (n)] & (1 << (16 - 1 - d))) 12551748Smckusick break; 12651748Smckusick 12751748Smckusick bshift (a, d, u, 0, m); 12851748Smckusick bshift (b, d, v, 0, n); 12951748Smckusick 13051748Smckusick /* Get pointers to the high dividend and divisor digits. */ 13151748Smckusick 13251748Smckusick u0 = u + big_end (m) - big_end (qn); 13351748Smckusick u1 = next_lsd (u0); 13451748Smckusick u2 = next_lsd (u1); 13551748Smckusick u += little_end (2); 13651748Smckusick 13751748Smckusick v0 = v + big_end (n); 13851748Smckusick 13951748Smckusick /* Main loop: find a quotient digit, multiply it by the divisor, 14051748Smckusick and subtract that from the dividend, shifted over the right amount. */ 14151748Smckusick 14251748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 14351748Smckusick { 14451748Smckusick /* Quotient digit initial guess: high 2 dividend digits over high 14551748Smckusick divisor digit. */ 14651748Smckusick 14751748Smckusick if (u0[j] == *v0) 14851748Smckusick { 14951748Smckusick qhat = B - 1; 15051748Smckusick rhat = (unsigned long) *v0 + u1[j]; 15151748Smckusick } 15251748Smckusick else 15351748Smckusick { 15451748Smckusick unsigned long numerator = ((unsigned long) u0[j] << 16) | u1[j]; 15551748Smckusick qhat = numerator / *v0; 15651748Smckusick rhat = numerator % *v0; 15751748Smckusick } 15851748Smckusick 15951748Smckusick /* Now get the quotient right for high 3 dividend digits over 16051748Smckusick high 2 divisor digits. */ 16151748Smckusick 16251748Smckusick while (rhat < B && qhat * *next_lsd (v0) > ((rhat << 16) | u2[j])) 16351748Smckusick { 16451748Smckusick qhat -= 1; 16551748Smckusick rhat += *v0; 16651748Smckusick } 16751748Smckusick 16851748Smckusick /* Multiply quotient by divisor, subtract from dividend. */ 16951748Smckusick 17051748Smckusick acc = 0; 17151748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 17251748Smckusick { 17351748Smckusick acc += (unsigned long) (u + j)[i] - v[i] * qhat; 17451748Smckusick (u + j)[i] = acc & low16; 17551748Smckusick if (acc < B) 17651748Smckusick acc = 0; 17751748Smckusick else 17851748Smckusick acc = (acc >> 16) | -B; 17951748Smckusick } 18051748Smckusick 18151748Smckusick q[j] = qhat; 18251748Smckusick 18351748Smckusick /* Quotient may have been too high by 1. If dividend went negative, 18451748Smckusick decrement the quotient by 1 and add the divisor back. */ 18551748Smckusick 18651748Smckusick if ((signed long) (acc + u0[j]) < 0) 18751748Smckusick { 18851748Smckusick q[j] -= 1; 18951748Smckusick acc = 0; 19051748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 19151748Smckusick { 19251748Smckusick acc += (unsigned long) (u + j)[i] + v[i]; 19351748Smckusick (u + j)[i] = acc & low16; 19451748Smckusick acc = acc >> 16; 19551748Smckusick } 19651748Smckusick } 19751748Smckusick } 19851748Smckusick 19951748Smckusick /* Now the remainder is what's left of the dividend, shifted right 20051748Smckusick by the amount of the normalizing left shift at the top. */ 20151748Smckusick 20251748Smckusick r[big_end (n)] = bshift (u + 1 + little_end (j - 1), 20351748Smckusick 16 - d, 20451748Smckusick r + little_end (2), 20551748Smckusick u[little_end (m - 1)] >> d, 20651748Smckusick n - 1); 20751748Smckusick } 20851748Smckusick 20951748Smckusick /* Left shift U by K giving W; fill the introduced low-order bits with 21051748Smckusick CARRY_IN. Length of U and W is N. Return carry out. K must be 21151748Smckusick in 0 .. 16. */ 21251748Smckusick 21351748Smckusick static int 21451748Smckusick bshift (u, k, w, carry_in, n) 21551748Smckusick unsigned short *u, *w, carry_in; 21651748Smckusick int k, n; 21751748Smckusick { 21851748Smckusick unsigned long acc; 21951748Smckusick int i; 22051748Smckusick 22151748Smckusick if (k == 0) 22251748Smckusick { 22351750Smckusick while (n-- > 0) 22451750Smckusick *w++ = *u++; 22551748Smckusick return 0; 22651748Smckusick } 22751748Smckusick 22851748Smckusick acc = carry_in; 22951748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 23051748Smckusick { 23151748Smckusick acc |= (unsigned long) u[i] << k; 23251748Smckusick w[i] = acc & low16; 23351748Smckusick acc = acc >> 16; 23451748Smckusick } 23551748Smckusick return acc; 23651748Smckusick } 237