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