15803Srrh /*
2*19836Sdist * Copyright (c) 1982 Regents of the University of California.
3*19836Sdist * All rights reserved. The Berkeley software License Agreement
4*19836Sdist * specifies the terms and conditions for redistribution.
55803Srrh */
6*19836Sdist
75803Srrh #ifndef lint
8*19836Sdist static char sccsid[] = "@(#)bignum2.c 5.1 (Berkeley) 04/30/85";
95803Srrh #endif not lint
105803Srrh
115803Srrh #include <stdio.h>
125803Srrh #include "as.h"
135803Srrh Bignum Znumber; /* zero reference */
145803Srrh #define MINEXP -32768 /* never generate; reserved for id 0 */
155803Srrh
intconvert(number,convto)165803Srrh Bignum intconvert(number, convto)
175803Srrh Bignum number;
185803Srrh int convto;
195803Srrh {
205803Srrh reg int i;
215803Srrh if (number.num_tag == convto)
225803Srrh return(number);
235803Srrh if (ty_nbyte[number.num_tag] > ty_nbyte[convto] && (passno == 2)){
245803Srrh yywarning("Conversion between %s and %s looses significance",
255803Srrh ty_string[number.num_tag],
265803Srrh ty_string[convto]);
275803Srrh }
285803Srrh for (i = ty_nbyte[convto]; i < ty_nbyte[TYPO]; i++)
295803Srrh number.num_uchar[i] = 0;
305803Srrh return(number);
315803Srrh }
325803Srrh
335803Srrh #define CONV(src, dst) (((src) << TYPLG) + (dst))
345803Srrh
floatconvert(number,convto)355803Srrh Bignum floatconvert(number, convto)
365803Srrh Bignum number;
375803Srrh int convto;
385803Srrh {
395803Srrh reg u_int *bp; /* r11 */
405803Srrh int loss = 0;
415803Srrh int gain = 0;
425803Srrh int mixs = 0;
435803Srrh Ovf ovf;
445803Srrh
455803Srrh if (number.num_tag == convto)
465803Srrh return(number);
475803Srrh bp = &number.num_uint[0];
485803Srrh #ifdef lint
495803Srrh *bp = *bp;
505803Srrh #endif lint
515803Srrh
525803Srrh switch(CONV(number.num_tag, convto)){
535803Srrh
545803Srrh case CONV(TYPF, TYPD): asm("cvtfd (r11), (r11)"); break;
555803Srrh case CONV(TYPF, TYPG): mixs++; break;
565803Srrh case CONV(TYPF, TYPH): mixs++; break;
575803Srrh
585803Srrh case CONV(TYPD, TYPF): asm("cvtdf (r11), (r11)"); break;
595803Srrh case CONV(TYPD, TYPG): mixs++; break;
605803Srrh case CONV(TYPD, TYPH): mixs++; break;
615803Srrh
625803Srrh case CONV(TYPG, TYPF): mixs++; break;
635803Srrh case CONV(TYPG, TYPD): mixs++; break;
645803Srrh case CONV(TYPG, TYPH): mixs++; break;
655803Srrh
665803Srrh case CONV(TYPH, TYPF): mixs++; break;
675803Srrh case CONV(TYPH, TYPD): mixs++; break;
685803Srrh case CONV(TYPH, TYPG): mixs++; break;
695803Srrh default: panic("Bad floating point conversion?");
705803Srrh }
715803Srrh if ((gain || mixs || loss) && (passno == 2)){
725803Srrh yywarning("Converting from %s to %s: %s ",
735803Srrh ty_string[number.num_tag],
745803Srrh ty_string[convto],
755803Srrh gain ? "gains significance" :
765803Srrh (loss ? "looses significance" : "mixs exponent formats")
775803Srrh );
785803Srrh }
795803Srrh if (mixs){
805803Srrh number = bignumconvert(number, convto, &ovf);
815803Srrh if (ovf && passno == 2){
825803Srrh yywarning("Floating conversion over/underflowed\n");
835803Srrh }
845803Srrh } else {
855803Srrh number.num_tag = convto;
865803Srrh }
875803Srrh return(number);
885803Srrh }
895803Srrh
905803Srrh /*
915803Srrh * Convert a big number between various representations
925803Srrh */
bignumconvert(number,toconv,ovfp)935803Srrh Bignum bignumconvert(number, toconv, ovfp)
945803Srrh Bignum number;
955803Srrh int toconv;
965803Srrh Ovf *ovfp;
975803Srrh {
985803Srrh int tag;
995803Srrh
1005803Srrh *ovfp = 0;
1015803Srrh tag = number.num_tag;
1025803Srrh if (tag == toconv)
1035803Srrh return(number);
1045803Srrh if (tag == TYPUNPACKED){
1055803Srrh return(bignumpack(number, toconv, ovfp));
1065803Srrh }
1075803Srrh if (toconv == TYPUNPACKED){
1085803Srrh return(bignumunpack(number, ovfp));
1095803Srrh }
1105803Srrh return(bignumpack(bignumunpack(number, ovfp), toconv, ovfp));
1115803Srrh }
1125803Srrh
bignumunpack(Packed,ovfp)1135803Srrh Bignum bignumunpack(Packed, ovfp)
1145803Srrh Bignum Packed;
1155803Srrh Ovf *ovfp;
1165803Srrh {
1175803Srrh Bignum Mantissa;
1185803Srrh Bignum Enumber;
1195803Srrh reg int i;
1205803Srrh int j;
1215803Srrh int k;
1225803Srrh reg struct ty_bigdesc *p;
1235803Srrh reg chptr packed;
1245803Srrh reg chptr mantissa;
1255803Srrh reg chptr enumber;
1265803Srrh u_short exponent;
1275803Srrh int sign;
1285803Srrh int mask;
1295803Srrh
1305803Srrh p = &ty_bigdesc[Packed.num_tag];
1315803Srrh
1325803Srrh *ovfp = 0;
1335803Srrh Mantissa = Znumber;
1345803Srrh sign = 0;
1355803Srrh exponent = 0;
1365803Srrh mantissa = CH_FIELD(Mantissa);
1375803Srrh enumber = CH_FIELD(Enumber);
1385803Srrh packed = CH_FIELD(Packed);
1395803Srrh
1405803Srrh if (isclear(packed)){
1415803Srrh Mantissa.num_tag = TYPUNPACKED;
1425803Srrh Mantissa.num_exponent = MINEXP;
1435803Srrh return(Mantissa);
1445803Srrh }
1455803Srrh /*
1465803Srrh * map the packed number into the mantissa, using
1475803Srrh * the unpacking map
1485803Srrh */
1495803Srrh mapnumber(mantissa, packed, 16, p->b_upmmap);
1505803Srrh /*
1515803Srrh * perform the mantissa shifting.
1525803Srrh * This may appear to overflow; all that is lost
1535803Srrh * is low order bits of the exponent.
1545803Srrh */
1555803Srrh (void)numshift(p->b_mlshift, mantissa, mantissa);
1565803Srrh /*
1575803Srrh * handle sign and exponent
1585803Srrh */
1595803Srrh switch(Packed.num_tag){
1605803Srrh case TYPB:
1615803Srrh case TYPW:
1625803Srrh case TYPL:
1635803Srrh case TYPO:
1645803Srrh case TYPQ:
1655803Srrh sign = 0;
1665803Srrh exponent = p->b_eexcess;
1675803Srrh if (mantissa[HOC] & SIGNBIT){
1685803Srrh sign = -1;
1695803Srrh *ovfp |= numnegate(mantissa, mantissa);
1705803Srrh }
1715803Srrh /*
1725803Srrh * Normalize the packed by left shifting,
1735803Srrh * adjusting the exponent as we go.
1745803Srrh * Do a binary weighted left shift for some speed.
1755803Srrh */
1765803Srrh k = 0;
1775803Srrh for (j = 4; j >= 0; --j){
1785803Srrh i = 1 << j; /* 16, 8, 4, 2, 1 */
1795803Srrh while(1){
1805803Srrh if (k >= p->b_msigbits)
1815803Srrh break;
1825803Srrh mask = ONES(i) << (CH_BITS - i);
1835803Srrh if (mantissa[HOC] & mask)
1845803Srrh break;
1855803Srrh (void)numshift(i, mantissa, mantissa);
1865803Srrh k += i;
1875803Srrh exponent -= i;
1885803Srrh }
1895803Srrh }
1905803Srrh assert(mantissa[HOC] & SIGNBIT, "integer <<ing");
1915803Srrh /*
1925803Srrh * now, kick the most significant bit off the top
1935803Srrh */
1945803Srrh (void)numshift(1, mantissa, mantissa);
1955803Srrh break;
1965803Srrh default:
1975803Srrh /*
1985803Srrh * map the exponent into the local area.
1995803Srrh */
2005803Srrh Enumber = Znumber;
2015803Srrh mapnumber(enumber, packed, 2, p->b_upemap);
2025803Srrh /*
2035803Srrh * Extract the exponent, and get rid
2045803Srrh * of the sign bit
2055803Srrh */
2065803Srrh exponent = Enumber.num_ushort[0] & ONES(15);
2075803Srrh /*
2085803Srrh * shift the exponent, and get rid of high order
2095803Srrh * trash
2105803Srrh */
2115803Srrh exponent >>= p->b_ershift;
2125803Srrh exponent &= ONES(p->b_esigbits);
2135803Srrh /*
2145803Srrh * un excess the exponent
2155803Srrh */
2165803Srrh exponent -= p->b_eexcess;
2175803Srrh /*
2185803Srrh * extract and extend the sign bit
2195803Srrh */
2205803Srrh sign = (Enumber.num_ushort[0] & ~ONES(15)) ? -1 : 0;
2215803Srrh }
2225803Srrh /*
2235803Srrh * Assemble the pieces, and return the number
2245803Srrh */
2255803Srrh Mantissa.num_tag = TYPUNPACKED;
2265803Srrh Mantissa.num_sign = sign;
2275803Srrh Mantissa.num_exponent = exponent;
2285803Srrh return(Mantissa);
2295803Srrh }
2305803Srrh
bignumpack(Unpacked,toconv,ovfp)2315803Srrh Bignum bignumpack(Unpacked, toconv, ovfp)
2325803Srrh Bignum Unpacked;
2335803Srrh int toconv;
2345803Srrh Ovf *ovfp;
2355803Srrh {
2365803Srrh Bignum Back;
2375803Srrh Bignum Enumber;
2385803Srrh Bignum Temp;
2395803Srrh
2405803Srrh short exponent;
2415803Srrh char sign;
2425803Srrh reg struct ty_bigdesc *p;
2435803Srrh reg chptr back;
2445803Srrh reg chptr enumber;
2455803Srrh reg chptr temp;
2465803Srrh reg chptr unpacked;
2475803Srrh
2485803Srrh int i,j;
2495803Srrh
2505803Srrh if (Unpacked.num_tag != TYPUNPACKED)
2515803Srrh panic("Argument to bignumpack is not unpacked");
2525803Srrh
2535803Srrh *ovfp = 0;
2545803Srrh Back = Znumber;
2555803Srrh Temp = Znumber;
2565803Srrh Back.num_tag = toconv;
2575803Srrh
2585803Srrh back = CH_FIELD(Back);
2595803Srrh temp = CH_FIELD(Temp);
2605803Srrh enumber = CH_FIELD(Enumber);
2615803Srrh unpacked = CH_FIELD(Unpacked);
2625803Srrh p = &ty_bigdesc[toconv];
2635803Srrh
2645803Srrh exponent = Unpacked.num_exponent;
2655803Srrh sign = Unpacked.num_sign;
2665803Srrh if (exponent == MINEXP)
2675803Srrh return(Back); /* identically zero */
2685803Srrh
2695803Srrh switch(toconv){
2705803Srrh case TYPB:
2715803Srrh case TYPW:
2725803Srrh case TYPL:
2735803Srrh case TYPQ:
2745803Srrh case TYPO:
2755803Srrh /*
2765803Srrh * Put back in the assumed high order fraction
2775803Srrh * bit that is always a 1.
2785803Srrh */
2795803Srrh (void)numshift(-1, temp, unpacked);
2805803Srrh temp[HOC] |= SIGNBIT;
2815803Srrh if (exponent > p->b_eexcess){
2825803Srrh /*
2835803Srrh * Construct the largest positive integer
2845803Srrh */
2855803Srrh (void)numclear(temp);
2865803Srrh (void)num1comp(temp, temp);
2875803Srrh temp[HOC] &= ~SIGNBIT;
2885803Srrh sign = sign;
2895803Srrh *ovfp |= OVF_OVERFLOW;
2905803Srrh } else
2915803Srrh if (exponent <= 0){
2925803Srrh /*
2935803Srrh * chop the temp; underflow to integer 0
2945803Srrh */
2955803Srrh (void)numclear(temp);
2965803Srrh sign = 0;
2975803Srrh *ovfp |= OVF_UNDERFLOW;
2985803Srrh } else {
2995803Srrh /*
3005803Srrh * denormalize the temp.
3015803Srrh * This will again chop, by shifting
3025803Srrh * bits off the right end into oblivion.
3035803Srrh */
3045803Srrh for (j = 4; j >= 0; --j){
3055803Srrh i = 1 << j; /* 16, 8, 4, 2, 1 */
3065803Srrh while(exponent + i <= p->b_eexcess){
3075803Srrh numshift(-i, temp, temp);
3085803Srrh exponent += i;
3095803Srrh }
3105803Srrh }
3115803Srrh }
3125803Srrh /*
3135803Srrh * negate the temp if the sign is set
3145803Srrh */
3155803Srrh if (sign)
3165803Srrh *ovfp |= numnegate(temp, temp);
3175803Srrh /*
3185803Srrh * Stuff the temp number into the return area
3195803Srrh */
3205803Srrh mapnumber(back, temp, 16, p->b_pmmap);
3215803Srrh return(Back);
3225803Srrh default:
3235803Srrh /*
3245803Srrh * Shift the mantissa to the right, filling in zeroes on
3255803Srrh * the left. This aligns the least significant bit
3265803Srrh * on the bottom of a byte, something that upround
3275803Srrh * will use.
3285803Srrh * Put the result into a temporary.
3295803Srrh * Even though the shift may be zero, there
3305803Srrh * is still a copy involved here.
3315803Srrh */
3325803Srrh (void)numshift(-(p->b_mlshift), temp, unpacked);
3335803Srrh /*
3345803Srrh * Perform the rounding by adding in 0.5 ulp's
3355803Srrh */
3365803Srrh exponent = upround(&Temp, p, exponent);
3375803Srrh /*
3385803Srrh * Do a range check on the exponent, in preparation
3395803Srrh * to stuffing it in.
3405803Srrh */
3415803Srrh if ((short)(exponent + p->b_eexcess) == 0){
3425803Srrh /*
3435803Srrh * Sorry, no gradual underflow on the
3445803Srrh * VAX. Chop this beasty totally to zero
3455803Srrh */
3465803Srrh goto zeroret;
3475803Srrh } else
3485803Srrh if ((short)(exponent + p->b_eexcess) < 0){
3495803Srrh /*
3505803Srrh * True underflow will happen;
3515803Srrh * Chop everything to positive zero
3525803Srrh */
3535803Srrh zeroret:
3545803Srrh (void)numclear(temp);
3555803Srrh exponent = 0;
3565803Srrh sign = 0; /* avoid reserved operand! */
3575803Srrh *ovfp |= OVF_UNDERFLOW;
3585803Srrh } else
3595803Srrh if ((unsigned)(exponent + p->b_eexcess)
3605803Srrh >= (unsigned)(1 << p->b_esigbits)){
3615803Srrh /*
3625803Srrh * Construct the largest magnitude possible
3635803Srrh * floating point unpacked: 0.{1}111111111
3645803Srrh */
3655803Srrh (void)numclear(temp);
3665803Srrh (void)num1comp(temp, temp);
3675803Srrh exponent = ONES(p->b_esigbits);
3685803Srrh sign = sign;
3695803Srrh *ovfp |= OVF_OVERFLOW;
3705803Srrh } else {
3715803Srrh /*
3725803Srrh * The exponent will fit.
3735803Srrh * Bias it up, and the common code will stuff it.
3745803Srrh */
3755803Srrh exponent += p->b_eexcess;
3765803Srrh }
3775803Srrh exponent <<= p->b_ershift;
3785803Srrh /*
3795803Srrh * mask out trash for the sign, and put in the sign.
3805803Srrh */
3815803Srrh exponent &= ONES(15);
3825803Srrh if (sign)
3835803Srrh exponent |= ~ONES(15);
3845803Srrh Enumber.num_ushort[0] = exponent;
3855803Srrh /*
3865803Srrh * Map the unpacked exponent into the value going back
3875803Srrh */
3885803Srrh mapnumber(back, enumber, 2, p->b_pemap);
3895803Srrh /*
3905803Srrh * Stuff the unpacked mantissa into the return area
3915803Srrh */
3925803Srrh mapnumber(back, temp, 16, p->b_pmmap);
3935803Srrh return(Back);
3945803Srrh }
3955803Srrh /*NOTREACHED*/
3965803Srrh }
3975803Srrh
mapnumber(chp1,chp2,nbytes,themap)3985803Srrh mapnumber(chp1, chp2, nbytes, themap)
3995803Srrh chptr chp1, chp2;
4005803Srrh int nbytes;
4015803Srrh char *themap;
4025803Srrh {
4035803Srrh reg int i;
4045803Srrh reg u_char *p1, *p2;
4055803Srrh
4065803Srrh p1 = (u_char *)chp1;
4075803Srrh p2 = (u_char *)chp2;
4085803Srrh for (i = 0; i < nbytes; i++){
4095803Srrh switch(themap[i]){
4105803Srrh case NOTAKE:
4115803Srrh break;
4125803Srrh default:
4135803Srrh p1[themap[i]] |= p2[i];
4145803Srrh break;
4155803Srrh }
4165803Srrh }
4175803Srrh }
4185803Srrh
4195803Srrh #define UPSHIFT 2
4205803Srrh /*
4215803Srrh * round in 1/2 ulp in the number, possibly modifying
4225803Srrh * the binary exponent if there was total carry out.
4235803Srrh * Return the modified exponent
4245803Srrh */
upround(numberp,p,exponent)4255803Srrh int upround(numberp, p, exponent)
4265803Srrh reg Bignum *numberp;
4275803Srrh reg struct ty_bigdesc *p;
4285803Srrh int exponent;
4295803Srrh {
4305803Srrh reg u_char *bytep;
4315803Srrh int nbytes;
4325803Srrh int byteindex;
4335803Srrh int hofractionbit;
4345803Srrh int ovffractionbit;
4355803Srrh reg int ovfbitindex;
4365803Srrh reg chptr number;
4375803Srrh static Bignum ulp;
4385803Srrh
4395803Srrh /*
4405803Srrh * Find out the byte index of the byte containing the ulp
4415803Srrh */
4425803Srrh number = CH_FIELD(numberp[0]);
4435803Srrh bytep = numberp->num_uchar;
4445803Srrh
4455803Srrh nbytes = (p->b_msigbits - 1) + p->b_mlshift;
4465803Srrh assert((nbytes % 8) == 0, "mantissa sig bits");
4475803Srrh nbytes /= 8;
4485803Srrh byteindex = 15 - nbytes;
4495803Srrh assert(byteindex >= 0, "ulp in outer space");
4505803Srrh /*
4515803Srrh * Shift the number to the right by two places,
4525803Srrh * so that we can do full arithmetic without overflowing
4535803Srrh * to the left.
4545803Srrh */
4555803Srrh numshift(-UPSHIFT, number, number);
4565803Srrh /*
4575803Srrh * Construct the missing high order fraction bit
4585803Srrh */
4595803Srrh ovfbitindex = 8 - (p->b_mlshift + UPSHIFT);
4605803Srrh assert(ovfbitindex >= 0, "Shifted byte 15 into byte 14");
4615803Srrh hofractionbit = (0x01 << ovfbitindex);
4625803Srrh ovffractionbit = (0x02 << ovfbitindex);
4635803Srrh bytep[15] |= hofractionbit;
4645803Srrh /*
4655803Srrh * construct the unit in the last place, and it
4665803Srrh * to the fraction
4675803Srrh */
4685803Srrh ulp.num_uchar[byteindex] |= (0x80 >> UPSHIFT);
4695803Srrh numaddv(number, number, CH_FIELD(ulp));
4705803Srrh ulp.num_uchar[byteindex] &= ~(0x80 >> UPSHIFT);
4715803Srrh /*
4725803Srrh * Check if there was an overflow,
4735803Srrh * and adjust by shifting.
4745803Srrh * Also, bring the number back into canonical
4755803Srrh * unpacked form by left shifting by two to undeo
4765803Srrh * what we did before.
4775803Srrh */
4785803Srrh if (bytep[15] & ovffractionbit){
4795803Srrh exponent += 1;
4805803Srrh numshift(UPSHIFT - 1, number, number);
4815803Srrh } else {
4825803Srrh numshift(UPSHIFT, number, number);
4835803Srrh }
4845803Srrh /*
4855803Srrh * Clear off trash in the unused bits of the high
4865803Srrh * order byte of the number
4875803Srrh */
4885803Srrh bytep[15] &= ONES(8 - p->b_mlshift);
4895803Srrh return(exponent);
4905803Srrh }
4915803Srrh #ifdef DEBUG
bignumprint(number)4925803Srrh bignumprint(number)
4935803Srrh Bignum number;
4945803Srrh {
4955803Srrh printf("Bignum: %s (exp: %d, sign: %d) 0x%08x%08x%08x%08x",
4965803Srrh ty_string[number.num_tag],
4975803Srrh number.num_exponent,
4985803Srrh number.num_sign,
4995803Srrh number.num_uint[3],
5005803Srrh number.num_uint[2],
5015803Srrh number.num_uint[1],
5025803Srrh number.num_uint[0]);
5035803Srrh switch(number.num_tag){
5045803Srrh case TYPB:
5055803Srrh case TYPW:
5065803Srrh case TYPL:
5075803Srrh case TYPQ:
5085803Srrh case TYPO:
5095803Srrh case TYPUNPACKED:
5105803Srrh break;
5115803Srrh case TYPF:
5125803Srrh printf(" == %10.8e", number.num_num.numFf_float.Ff_value);
5135803Srrh break;
5145803Srrh case TYPD:
5155803Srrh printf(" == %20.17e", number.num_num.numFd_float.Fd_value);
5165803Srrh break;
5175803Srrh case TYPG:
5185803Srrh case TYPH:
5195803Srrh break;
5205803Srrh }
5215803Srrh }
5225803Srrh
numprintovf(ovf)5235803Srrh numprintovf(ovf)
5245803Srrh Ovf ovf;
5255803Srrh {
5265803Srrh int i;
5275803Srrh static struct ovftab{
5285803Srrh Ovf which;
5295803Srrh char *print;
5305803Srrh } ovftab[] = {
5315803Srrh OVF_POSOVF, "posovf",
5325803Srrh OVF_MAXINT, "maxint",
5335803Srrh OVF_ADDV, "addv",
5345803Srrh OVF_LSHIFT, "lshift",
5355803Srrh OVF_F, "F float",
5365803Srrh OVF_D, "D float",
5375803Srrh OVF_G, "G float",
5385803Srrh OVF_H, "H float",
5395803Srrh OVF_OVERFLOW, "cvt overflow",
5405803Srrh OVF_UNDERFLOW, "cvt underflow",
5415803Srrh 0, 0
5425803Srrh };
5435803Srrh for(i = 0; ovftab[i].which; i++){
5445803Srrh if (ovf & ovftab[i].which)
5455803Srrh printf("Overflow(%s) ", ovftab[i].print);
5465803Srrh }
5475803Srrh }
5485803Srrh #endif DEBUG
549