xref: /csrg-svn/old/as.vax/bignum1.c (revision 19835)
15802Srrh /*
2*19835Sdist  * Copyright (c) 1982 Regents of the University of California.
3*19835Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19835Sdist  * specifies the terms and conditions for redistribution.
55802Srrh  */
6*19835Sdist 
75802Srrh #ifndef lint
8*19835Sdist static char sccsid[] = "@(#)bignum1.c	5.1 (Berkeley) 04/30/85";
95802Srrh #endif not lint
105802Srrh 
115802Srrh #include <errno.h>
125802Srrh #include <stdio.h>
135802Srrh #include "as.h"
145802Srrh 
155802Srrh /*
165802Srrh  *	Construct a floating point number
175802Srrh  */
as_atof(numbuf,radix,ovfp)185802Srrh Bignum as_atof(numbuf, radix, ovfp)
195802Srrh 	char	*numbuf;
205802Srrh 	int	radix;
215802Srrh 	Ovf	*ovfp;
225802Srrh {
235802Srrh 	Bignum	number;
245802Srrh 	extern	int	errno;
255802Srrh 	double	atof();
265802Srrh 
275802Srrh 	number = Znumber;
285802Srrh 	errno = 0;
295802Srrh 	switch(radix){
305802Srrh 	case TYPF:
315802Srrh 	case TYPD:
325802Srrh 		number.num_tag = TYPD;
335802Srrh 		*ovfp = 0;
345802Srrh 		number.num_num.numFd_float.Fd_value = atof(numbuf);
355802Srrh 		break;
365802Srrh 	case TYPG:
375802Srrh 	case TYPH:
385802Srrh 		number = bigatof(numbuf, radix);
395802Srrh 		break;
405802Srrh 	}
415802Srrh 	if (errno == ERANGE && passno == 2){
425802Srrh 		yywarning("Floating conversion over/underflowed\n");
435802Srrh 	}
445802Srrh 	return(number);
455802Srrh }
465802Srrh 
475802Srrh /*
485802Srrh  *	Construct an integer.
495802Srrh  */
505802Srrh 
as_atoi(ccp,radix,ovfp)515802Srrh Bignum as_atoi(ccp, radix, ovfp)
525802Srrh 	reg	char	*ccp;		/* character cp */
535802Srrh 		int	radix;
545802Srrh 		Ovf	*ovfp;
555802Srrh {
565802Srrh 	reg	chptr	bcp;
575802Srrh 		chptr	tcp;
585802Srrh 	reg	int	i;
595802Srrh 		int	val;
605802Srrh 		Bignum	n_n;
615802Srrh 		Bignum	t_n;
625802Srrh 		int	sign;
635802Srrh 		Ovf	ovf;
645802Srrh 
655802Srrh 	ovf = 0;
665802Srrh 	sign = 0;
675802Srrh 	for (; *ccp; ccp++){
685802Srrh 		switch(*ccp){
695802Srrh 		case '0':
705802Srrh 		case '+':	continue;
715802Srrh 		case '-':	sign ^= 1;
725802Srrh 				continue;
735802Srrh 		}
745802Srrh 		break;
755802Srrh 	}
765802Srrh 
775802Srrh 	n_n = Znumber;
785802Srrh 	t_n = Znumber;
795802Srrh 	bcp = CH_FIELD(n_n); (void)numclear(bcp);
805802Srrh 	tcp = CH_FIELD(t_n); (void)numclear(tcp);
815802Srrh 	for (; *ccp; ccp++){
825802Srrh 		switch(*ccp){
835802Srrh 		case '8': case '9':
845802Srrh 			if (radix < 10)
855802Srrh 				goto done;
865802Srrh 			/*FALLTHROUGH*/
875802Srrh 		case '0': case '1': case '2': case '3': case '4':
885802Srrh 		case '5': case '6': case '7':
895802Srrh 			val = *ccp - '0';
905802Srrh 			break;
915802Srrh 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
925802Srrh 			if (radix < 16)
935802Srrh 				goto done;
945802Srrh 			val = *ccp - 'A' + 10;
955802Srrh 			break;
965802Srrh 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
975802Srrh 			if (radix < 16)
985802Srrh 				goto done;
995802Srrh 			val = *ccp - 'a' + 10;
1005802Srrh 			break;
1015802Srrh 		default:
1025802Srrh 			goto done;
1035802Srrh 		}
1045802Srrh 		switch(radix){
1055802Srrh 		case 8:
1065802Srrh 			ovf |= numshift(3, bcp, bcp);
1075802Srrh 			break;
1085802Srrh 		case 16:
1095802Srrh 			ovf |= numshift(4, bcp, bcp);
1105802Srrh 			break;
1115802Srrh 		case 10:
1125802Srrh 			ovf |= numshift(1, tcp, bcp);
1135802Srrh 			ovf |= numshift(3, bcp, bcp);
1145802Srrh 			ovf |= numaddv(bcp, tcp, bcp);
1155802Srrh 			break;
1165802Srrh 		}
1175802Srrh 		ovf |= numaddd(bcp, bcp, val);
1185802Srrh 	}
1195802Srrh   done: ;
1205802Srrh 	ovf |= posovf(bcp);
1215802Srrh 	if (sign){
1225802Srrh 		if (ovf & OVF_MAXINT) {
1235802Srrh 			ovf &= ~(OVF_MAXINT | OVF_POSOVF);
1245802Srrh 		} else {
1255802Srrh 			ovf |= numnegate(bcp, bcp);
1265802Srrh 		}
1275802Srrh 	}
1285802Srrh 	/*
1295802Srrh 	 *	find the highest set unit of the number
1305802Srrh 	 */
1315802Srrh 	val = sign ? -1 : 0;
1325802Srrh 	for (i = 0; i < CH_N; i++){
1335802Srrh 		if (bcp[i] == val)
1345802Srrh 			break;
1355802Srrh 	}
1365802Srrh 	{
1375802Srrh 		static u_char tagtab[4][16] = {
1385802Srrh 		{	TYPB,
1395802Srrh 			TYPW,
1405802Srrh 			TYPL, TYPL,
1415802Srrh 			TYPQ, TYPQ, TYPQ, TYPQ,
1425802Srrh 			TYPO, TYPO, TYPO, TYPO, TYPO, TYPO, TYPO, TYPO},
1435802Srrh 		{	TYPW,
1445802Srrh 			TYPL,
1455802Srrh 			TYPQ, TYPQ,
1465802Srrh 			TYPO, TYPO, TYPO, TYPO},
1475802Srrh 		{   0   },
1485802Srrh 		{	TYPL,
1495802Srrh 			TYPQ,
1505802Srrh 			TYPO, TYPO }
1515802Srrh 		};
1525802Srrh 		/*
1535802Srrh 		 *	i indexes to the null chunk; make it point to the
1545802Srrh 		 *	last non null chunk
1555802Srrh 		 */
1565802Srrh 		i -= 1;
1575802Srrh 		if (i < 0)
1585802Srrh 			i = 0;
1595802Srrh 		n_n.num_tag = tagtab[HOC][i];
1605802Srrh 		assert(n_n.num_tag != 0, "Botch width computation");
1615802Srrh 	}
1625802Srrh 	*ovfp = ovf;
1635802Srrh 	return(n_n);
1645802Srrh }
1655802Srrh 
posovf(src)1665802Srrh Ovf posovf(src)
1675802Srrh 	reg	chptr	src;
1685802Srrh {
1695802Srrh 	reg	int	i;
1705802Srrh 	Ovf	overflow = 0;
1715802Srrh 
1725802Srrh 	if (src[HOC] & SIGNBIT)
1735802Srrh 		overflow = OVF_POSOVF;
1745802Srrh 	if (src[HOC] == SIGNBIT){
1755802Srrh 		for (i = HOC - 1; i >= 0; --i){
1765802Srrh 			if (src[i] != 0)
1775802Srrh 				return(overflow);
1785802Srrh 		}
1795802Srrh 		overflow |= OVF_MAXINT;
1805802Srrh 	}
1815802Srrh 	return(overflow);
1825802Srrh }
1835802Srrh 
1845802Srrh /*
1855802Srrh  *	check if the number is clear
1865802Srrh  */
isclear(dst)1875802Srrh int isclear(dst)
1885802Srrh 	reg	chptr	dst;
1895802Srrh {
1905802Srrh 	return(!isunequal(dst, CH_FIELD(Znumber)));
1915802Srrh }
1925802Srrh 
isunequal(src1,src2)1935802Srrh int isunequal(src1, src2)
1945802Srrh 	reg	chptr	src1, src2;
1955802Srrh {
1965802Srrh 	reg	int	i;
1975802Srrh 
1985802Srrh 	i = CH_N;
1995802Srrh 	do{
2005802Srrh 		if (*src1++ != *src2++)
2015802Srrh 			return(i);
2025802Srrh 	}while(--i);
2035802Srrh 	return(0);
2045802Srrh }
2055802Srrh 
numclear(dst)2065802Srrh Ovf numclear(dst)
2075802Srrh 	reg	chptr	dst;
2085802Srrh {
2095802Srrh 	reg	int	i;
2105802Srrh 	i = CH_N;
2115802Srrh 	do{
2125802Srrh 		*dst++ = 0;
2135802Srrh 	}while(--i);
2145802Srrh 	return(0);
2155802Srrh }
2165802Srrh 
numshift(n,dst,src)2175802Srrh Ovf numshift(n, dst, src)
2185802Srrh 		int	n;
2195802Srrh 	reg	chptr	dst, src;
2205802Srrh {
2215802Srrh 	reg	int	i;
2225802Srrh 	reg	u_int	carryi, carryo;
2235802Srrh 	reg	u_int	mask;
2245802Srrh 	reg	u_int	value;
2255802Srrh 
2265802Srrh 	i = CH_N;
2275802Srrh 	if (n == 0){
2285802Srrh 		do{
2295802Srrh 			*dst++ = *src++;
2305802Srrh 		} while(--i);
2315802Srrh 		return(0);
2325802Srrh 	}
2335802Srrh 
2345802Srrh 	carryi = 0;
2355802Srrh 	mask = ONES(n);
2365802Srrh 
2375802Srrh 	if (n > 0){
2385802Srrh 		do{
2395802Srrh 			value = *src++;
2405802Srrh 			carryo = (value >> (CH_BITS - n)) & mask;
2415802Srrh 			value <<= n;
2425802Srrh 			value &= ~mask;
2435802Srrh 			*dst++ = value | carryi;
2445802Srrh 			carryi = carryo;
2455802Srrh 		} while (--i);
2465802Srrh 		return(carryi ? OVF_LSHIFT : 0);
2475802Srrh 	} else {
2485802Srrh 		n = -n;
2495802Srrh 		src += CH_N;
2505802Srrh 		dst += CH_N;
2515802Srrh 		do{
2525802Srrh 			value = *--src;
2535802Srrh 			carryo = value & mask;
2545802Srrh 			value >>= n;
2555802Srrh 			value &= ONES(CH_BITS - n);
2565802Srrh 			*--dst = value | carryi;
2575802Srrh 			carryi = carryo << (CH_BITS - n);
2585802Srrh 		} while (--i);
2595802Srrh 		return(carryi ? OVF_LSHIFT : 0);
2605802Srrh 	}
2615802Srrh }
2625802Srrh 
numaddd(dst,src1,val)2635802Srrh Ovf numaddd(dst, src1, val)
2645802Srrh 	chptr	dst, src1;
2655802Srrh 	int	val;
2665802Srrh {
2675802Srrh 	static	Bignum	work;
2685802Srrh 
2695802Srrh 	work.num_uchar[0] = val;
2705802Srrh 	return (numaddv(dst, src1, CH_FIELD(work)));
2715802Srrh }
2725802Srrh 
numaddv(dst,src1,src2)2735802Srrh Ovf numaddv(dst, src1, src2)
2745802Srrh 	reg	chptr	dst, src1, src2;
2755802Srrh {
2765802Srrh 	reg	int	i;
2775802Srrh 	reg	int	carry;
2785802Srrh 	reg	u_int	A,B,value;
2795802Srrh 
2805802Srrh 	carry = 0;
2815802Srrh 	i = CH_N;
2825802Srrh 	do{
2835802Srrh 		A = *src1++;
2845802Srrh 		B = *src2++;
2855802Srrh 		value = A + B + carry;
2865802Srrh 		*dst++ = value;
2875802Srrh 		carry = 0;
2885802Srrh 		if (value < A || value < B)
2895802Srrh 			carry = 1;
2905802Srrh 	} while (--i);
2915802Srrh 	return(carry ? OVF_ADDV : 0);
2925802Srrh }
2935802Srrh 
numnegate(dst,src)2945802Srrh Ovf numnegate(dst, src)
2955802Srrh 	chptr	dst, src;
2965802Srrh {
2975802Srrh 	Ovf	ovf;
2985802Srrh 
2995802Srrh 	ovf = num1comp(dst, src) ;
3005802Srrh 	ovf |= numaddd(dst, dst, 1);
3015802Srrh 	return(ovf);
3025802Srrh }
3035802Srrh 
num1comp(dst,src)3045802Srrh Ovf num1comp(dst, src)
3055802Srrh 	reg	chptr	dst, src;
3065802Srrh {
3075802Srrh 	reg	int	i;
3085802Srrh 	i = CH_N;
3095802Srrh 	do{
3105802Srrh 		*dst++ = ~ *src++;
3115802Srrh 	}while (--i);
3125802Srrh 	return(0);
3135802Srrh }
3145802Srrh 
3155802Srrh /*
3165802Srrh  *	Determine if floating point numbers are
3175802Srrh  *	capable of being represented as a one byte immediate literal constant
3185802Srrh  *	If it is, then stuff the value into *valuep.
3195802Srrh  *	argtype is how the instruction will interpret the number.
3205802Srrh  */
slitflt(number,argtype,valuep)3215802Srrh int slitflt(number, argtype, valuep)
3225802Srrh 	Bignum	number;		/* number presented */
3235802Srrh 	int	argtype;	/* what the instruction expects */
3245802Srrh 	int	*valuep;
3255802Srrh {
3265802Srrh #define	EXPPREC 3
3275802Srrh #define	MANTPREC 3
3285802Srrh 
3295802Srrh 		int	mask;
3305802Srrh 	reg	int	i;
3315802Srrh 		Bignum	unpacked;
3325802Srrh 		Ovf	ovf;
3335802Srrh 
3345802Srrh 	*valuep = 0;
3355802Srrh 	if (!ty_float[argtype])
3365802Srrh 		return(0);
3375802Srrh 	unpacked = bignumunpack(number, &ovf);
3385802Srrh 	assert(ovf == 0, "overflow in unpacking floating #!?");
3395802Srrh 	if (unpacked.num_sign)
3405802Srrh 		return(0);
3415802Srrh 	if (unpacked.num_exponent < 0)
3425802Srrh 		return(0);
3435802Srrh 	if (unpacked.num_exponent > ONES(EXPPREC))
3445802Srrh 		return(0);
3455802Srrh 	for (i = 0; i < HOC; i++){
3465802Srrh 		if (CH_FIELD(unpacked)[i])
3475802Srrh 			return(0);
3485802Srrh 	}
3495802Srrh 	if ((CH_FIELD(unpacked)[HOC]) & ONES(CH_BITS - MANTPREC))
3505802Srrh 		return(0);
3515802Srrh 	*valuep = (unpacked.num_exponent & ONES(EXPPREC)) << MANTPREC;
3525802Srrh 	mask = (CH_FIELD(unpacked)[HOC]) >> (CH_BITS - MANTPREC);
3535802Srrh 	mask &= ONES(MANTPREC);
3545802Srrh 	*valuep |= mask;
3555802Srrh 	*valuep &= ONES(MANTPREC + EXPPREC);
3565802Srrh 	return(1);
3575802Srrh }
3585802Srrh 
3595802Srrh #ifndef STANDALONE
3605802Srrh /*
3615802Srrh  *	Output a big number to txtfil
3625802Srrh  *	Called only when passno == 2
3635802Srrh  *
3645802Srrh  *	The conversion specifies the width of the number to be written out.
3655802Srrh  *	The width is supplied from either an initialized data directive
3665802Srrh  *	(for example .float, .double), or from the operand size
3675802Srrh  *	defined by an operator.
3685802Srrh  *	If the number is of type quad or octal,
3695802Srrh  *	we just write it out; this allows one to specify bit
3705802Srrh  *	patterns for floating point numbers.
3715802Srrh  *	If the number is one of the floating types and the conversion
3725802Srrh  *	is not the same type, then we complain, but do the conversion anyway.
3735802Srrh  *	The conversion is strict.
3745802Srrh  */
bignumwrite(number,toconv)3755802Srrh bignumwrite(number, toconv)
3765802Srrh 	Bignum	number;
3775802Srrh 	int	toconv;		/* one of TYP[QO FDGH] */
3785802Srrh {
3795802Srrh 	reg	u_int	*bp;
3805802Srrh 
3815802Srrh 	if (passno != 2)
3825802Srrh 		return;
3835802Srrh 
3845802Srrh 	bp = &number.num_uint[0];
3855802Srrh 	switch(number.num_tag){
3865802Srrh 	case TYPB:
3875802Srrh 	case TYPW:
3885802Srrh 	case TYPL:
3895802Srrh 	case TYPQ:
3905802Srrh 	case TYPO:
3915802Srrh 		number = intconvert(number, toconv);
3925802Srrh 		break;
3935802Srrh 	default:
3945802Srrh 		number = floatconvert(number, toconv);
3955802Srrh 		break;
3965802Srrh 	}
3975802Srrh 	bwrite((char *)bp, ty_nbyte[toconv], txtfil);
3985802Srrh }
3995802Srrh #endif STANDALONE
400