|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 8989 (0x231d) Types: TextFile Names: »gnulib2.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦d53cfc7b2⟧ »./gcc-1.35.tar.Z« └─⟦90f628c1d⟧ └─⟦this⟧ »gcc-1.35/gnulib2.c«
/* More subroutines needed by GCC output code on some machines. */ /* Compile this one with gcc. */ #include "config.h" #include <stddef.h> /* long long ints are pairs of long ints in the order determined by WORDS_BIG_ENDIAN. */ #ifdef WORDS_BIG_ENDIAN struct longlong {long high, low;}; #else struct longlong {long low, high;}; #endif /* Internally, long long ints are strings of unsigned shorts in the order determined by BYTES_BIG_ENDIAN. */ #define B 0x10000 #define low16 (B - 1) #ifdef BYTES_BIG_ENDIAN #define HIGH 0 #define LOW 1 #define big_end(n) 0 #define little_end(n) ((n) - 1) #define next_msd(i) ((i) - 1) #define next_lsd(i) ((i) + 1) #define is_not_msd(i,n) ((i) >= 0) #define is_not_lsd(i,n) ((i) < (n)) #else #define LOW 0 #define HIGH 1 #define big_end(n) ((n) - 1) #define little_end(n) 0 #define next_msd(i) ((i) + 1) #define next_lsd(i) ((i) - 1) #define is_not_msd(i,n) ((i) < (n)) #define is_not_lsd(i,n) ((i) >= 0) #endif /* These algorithms are all straight out of Knuth, vol. 2, sec. 4.3.1. */ #define bdiv __div_internal static int badd (); static int bsub (); static void bmul (); static void bdiv (); static int bneg (); static int bshift (); #ifdef L_adddi3 struct longlong __adddi3 (u, v) struct longlong u, v; { long a[2], b[2], c[2]; struct longlong w; a[HIGH] = u.high; a[LOW] = u.low; b[HIGH] = v.high; b[LOW] = v.low; badd (a, b, c, sizeof c); w.high = c[HIGH]; w.low = c[LOW]; return w; } static int badd (a, b, c, n) unsigned short *a, *b, *c; size_t n; { unsigned long acc; int i; n /= sizeof *c; acc = 0; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc += a[i] + b[i]; c[i] = acc & low16; acc = acc >> 16; } return acc; } #endif #ifdef L_subdi3 struct longlong __subdi3 (u, v) struct longlong u, v; { long a[2], b[2], c[2]; struct longlong w; a[HIGH] = u.high; a[LOW] = u.low; b[HIGH] = v.high; b[LOW] = v.low; bsub (a, b, c, sizeof c); w.high = c[HIGH]; w.low = c[LOW]; return w; } static int bsub (a, b, c, n) unsigned short *a, *b, *c; size_t n; { signed long acc; int i; n /= sizeof *c; acc = 0; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc += a[i] - b[i]; c[i] = acc & low16; acc = acc >> 16; } return acc; } #endif #ifdef L_muldi3 struct longlong __muldi3 (u, v) struct longlong u, v; { long a[2], b[2], c[2][2]; struct longlong w; a[HIGH] = u.high; a[LOW] = u.low; b[HIGH] = v.high; b[LOW] = v.low; bmul (a, b, c, sizeof a, sizeof b); w.high = c[LOW][HIGH]; w.low = c[LOW][LOW]; return w; } static void bmul (a, b, c, m, n) unsigned short *a, *b, *c; size_t m, n; { int i, j; unsigned long acc; bzero (c, m + n); m /= sizeof *a; n /= sizeof *b; for (j = little_end (n); is_not_msd (j, n); j = next_msd (j)) { acc = 0; for (i = little_end (m); is_not_msd (i, m); i = next_msd (i)) { acc += a[i] * b[j] + (c + next_lsd (j))[i]; (c + next_lsd (j))[i] = acc & low16; acc = acc >> 16; } c[j] = acc; } } #endif #ifdef L_divdi3 long long __divdi3 (u, v) long long u, v; { if (u < 0) if (v < 0) return (unsigned long long) -u / (unsigned long long) -v; else return - ((unsigned long long) -u / (unsigned long long) v); else if (v < 0) return - ((unsigned long long) u / (unsigned long long) -v); else return (unsigned long long) u / (unsigned long long) v; } #endif #ifdef L_moddi3 long long __moddi3 (u, v) long long u, v; { if (u < 0) if (v < 0) return - ((unsigned long long) -u % (unsigned long long) -v); else return - ((unsigned long long) -u % (unsigned long long) v); else if (v < 0) return (unsigned long long) u % (unsigned long long) -v; else return (unsigned long long) u % (unsigned long long) v; } #endif #ifdef L_udivdi3 struct longlong __udivdi3 (u, v) struct longlong u, v; { unsigned long a[2][2], b[2], q[2], r[2]; struct longlong w; a[HIGH][HIGH] = 0; a[HIGH][LOW] = 0; a[LOW][HIGH] = u.high; a[LOW][LOW] = u.low; b[HIGH] = v.high; b[LOW] = v.low; bdiv (a, b, q, r, sizeof a, sizeof b); w.high = q[HIGH]; w.low = q[LOW]; return w; } #endif #ifdef L_umoddi3 struct longlong __umoddi3 (u, v) struct longlong u, v; { unsigned long a[2][2], b[2], q[2], r[2]; struct longlong w; a[HIGH][HIGH] = 0; a[HIGH][LOW] = 0; a[LOW][HIGH] = u.high; a[LOW][LOW] = u.low; b[HIGH] = v.high; b[LOW] = v.low; bdiv (a, b, q, r, sizeof a, sizeof b); w.high = r[HIGH]; w.low = r[LOW]; return w; } #endif #ifdef L_negdi2 struct longlong __negdi2 (u) struct longlong u; { unsigned long a[2], b[2]; struct longlong w; a[HIGH] = u.high; a[LOW] = u.low; bneg (a, b, sizeof b); w.high = b[HIGH]; w.low = b[LOW]; return w; } static int bneg (a, b, n) unsigned short *a, *b; size_t n; { signed long acc; int i; n /= sizeof (short); acc = 0; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc -= a[i]; b[i] = acc & low16; acc = acc >> 16; } return acc; } #endif /* Divide a by b, producing quotient q and remainder r. sizeof a is m sizeof b is n sizeof q is m - n sizeof r is n The quotient must fit in m - n bytes, i.e., the most significant n digits of a must be less than b, and m must be greater than n. */ #ifdef L_div_internal void bdiv (a, b, q, r, m, n) unsigned short *a, *b, *q, *r; size_t m, n; { unsigned long qhat, rhat; unsigned long acc; unsigned short *u = (unsigned short *) alloca (m); unsigned short *v = (unsigned short *) alloca (n); unsigned short *u1 = next_lsd (u); unsigned short *u2 = next_lsd (u1); unsigned short *vn; int d, qn; int i, j; m /= sizeof *a; n /= sizeof *b; qn = m - n; /* Shift divisor and dividend left until the high bit of the divisor is 1. */ while (b[big_end (n)] == 0) { r[big_end (n)] = 0; a += little_end (2); b += little_end (2); r += little_end (2); m--; n--; /* Check for zero divisor. */ if (n == 0) abort (); } for (d = 0; d < 16; d++) if (b[big_end (n)] & (1 << (16 - 1 - d))) break; bshift (a, d, u, 0, m); bshift (b, d, v, 0, n); /* Get a pointer to the high divisor digit (so some of the upcoming code fits on a line). Provide the divisor with a trailing zero digit if it is only one digit long. */ vn = v + big_end (n); if (n == 1) *next_lsd (vn) = 0; /* Main loop: find a quotient digit, multiply it by the divisor, and subtract that from the dividend, shifted over the right amount. */ for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) { /* Quotient digit initial guess: high 2 dividend digits over high divisor digit. */ if (u[j] == *vn) { qhat = B - 1; rhat = *vn + u1[j]; } else { unsigned long numerator = u[j] << 16 | u1[j]; qhat = numerator / *vn; rhat = numerator % *vn; } /* Now get the quotient right for high 3 dividend digits over high 2 divisor digits. */ while (rhat < B && qhat * *next_lsd (vn) > (rhat << 16 | u2[j])) { qhat -= 1; rhat += *vn; } /* Multiply quotient by divisor, subtract from dividend. */ acc = 0; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc += (u1 + j)[i] - v[i] * qhat; (u1 + j)[i] = acc & low16; if (acc < B) acc = 0; else acc = acc >> 16 | -B; } q[j] = qhat; /* Quotient may have been too high by 1. If dividend went negative, decrement the quotient by 1 and add the divisor back. */ if ((signed long) (acc + u[j]) < 0) { q[j] -= 1; acc = 0; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc += (u1 + j)[i] + v[i]; (u1 + j)[i] = acc & low16; acc = acc >> 16; } } } /* Now the remainder is what's left of the dividend, shifted right by the amount of the normalizing left shift at the top. */ if (d == 0) bshift (&u[j], d, r, 0, n); else r[big_end (n)] = bshift (&u[j], 16 - d, &r[next_lsd (big_end (n))], u[little_end (m)] >> d, n - 1); } /* Left shift U by K giving W; fill the introduced low-order bits with CARRY_IN. Length of U and W is N. Return carry out. K must be in 0 .. 16. */ static int bshift (u, k, w, carry_in, n) unsigned short *u, *w, carry_in; int k, n; { unsigned long acc; int i; if (k == 0) { bcopy (u, w, n * sizeof *u); return 0; } acc = carry_in; for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) { acc |= u[i] << k; w[i] = acc & low16; acc = acc >> 16; } return acc; } #endif