/* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands. See the copyright notice in the ACK home directory, in the file "Copyright". */ /* $Header$ */ /* #define NOFLOAT for machines without floating point #define ACKFLOAT for machines using the ACK floating point software #define IEEEFLOAT for machines using IEEE floating point format #define OWNFLOAT to use floating point format of machine on which the code generator runs If none of these are defined, PDP-11 format is generated. */ #ifndef NOFLOAT #ifndef OWNFLOAT #include struct mantissa { unsigned long h_32; unsigned long l_32; }; struct EXTEND { short sign; short exp; struct mantissa mantissa; #define m1 mantissa.h_32 #define m2 mantissa.l_32 }; static int b64_add(); static int b64_sft(); static mul_ext(e1,e2,e3) struct EXTEND *e1,*e2,*e3; { /* Multiply the extended numbers e1 and e2, and put the result in e3. */ register int i,j; /* loop control */ unsigned short mp[4]; unsigned short mc[4]; unsigned short result[8]; /* result */ register unsigned short *pres; /* first save the sign (XOR) */ e3->sign = e1->sign ^ e2->sign; /* compute new exponent */ e3->exp = e1->exp + e2->exp + 1; /* check for overflow/underflow ??? */ /* 128 bit multiply of mantissas */ /* assign unknown long formats */ /* to known unsigned word formats */ mp[0] = e1->m1 >> 16; mp[1] = (unsigned short) e1->m1; mp[2] = e1->m2 >> 16; mp[3] = (unsigned short) e1->m2; mc[0] = e2->m1 >> 16; mc[1] = (unsigned short) e2->m1; mc[2] = e2->m2 >> 16; mc[3] = (unsigned short) e2->m2; for (i = 8; i--;) { result[i] = 0; } /* * fill registers with their components */ for(i=4, pres = &result[4];i--;pres--) if (mp[i]) { unsigned short k = 0; unsigned long mpi = mp[i]; for(j=4;j--;) { unsigned long tmp = (unsigned long)pres[j] + k; if (mc[j]) tmp += mpi * mc[j]; pres[j] = tmp; k = tmp >> 16; } pres[-1] = k; } if (! (result[0] & 0x8000)) { e3->exp--; for (i = 0; i <= 3; i++) { result[i] <<= 1; if (result[i+1]&0x8000) result[i] |= 1; } result[4] <<= 1; } /* * combine the registers to a total */ e3->m1 = ((unsigned long)(result[0]) << 16) + result[1]; e3->m2 = ((unsigned long)(result[2]) << 16) + result[3]; if (result[4] & 0x8000) { if (++e3->m2 == 0) { if (++e3->m1 == 0) { e3->m1 = 0x80000000; e3->exp++; } } } } static b64_sft(e1,n) struct mantissa *e1; int n; { if (n > 0) { if (n > 63) { e1->l_32 = 0; e1->h_32 = 0; return; } if (n >= 32) { e1->l_32 = e1->h_32; e1->h_32 = 0; n -= 32; } if (n > 0) { e1->l_32 >>= n; if (e1->h_32 != 0) { e1->l_32 |= (e1->h_32 << (32 - n)); e1->h_32 >>= n; } } return; } n = -n; if (n > 0) { if (n > 63) { e1->l_32 = 0; e1->h_32 = 0; return; } if (n >= 32) { e1->h_32 = e1->l_32; e1->l_32 = 0; n -= 32; } if (n > 0) { e1->h_32 <<= n; if (e1->l_32 != 0) { e1->h_32 |= (e1->l_32 >> (32 - n)); e1->l_32 <<= n; } } } } static int b64_add(e1,e2) /* * pointers to 64 bit 'registers' */ struct mantissa *e1,*e2; { register int overflow; int carry; /* add higher pair of 32 bits */ overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32); e1->h_32 += e2->h_32; /* add lower pair of 32 bits */ carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32); e1->l_32 += e2->l_32; if ((carry) && (++e1->h_32 == 0)) return(1); /* had a 64 bit overflow */ else return(overflow); /* return status from higher add */ } /* The following tables can be computed with the following bc(1) program: obase=16 scale=0 define t(x){ auto a, b, c a=2;b=1;c=2^32;n=1 while(asign = 0; e->exp = 0; e->m1 = e->m2 = 0; c = *s; switch(c) { case '-': e->sign = 1; case '+': s++; } while (c = *s++, isdigit(c) || (c == '.' && ! dotseen++)) { if (c == '.') continue; digitseen = 1; if (e->m1 <= (unsigned long)(0xFFFFFFFF)/10) { struct mantissa a1; a1 = e->mantissa; b64_sft(&(e->mantissa), -3); b64_sft(&a1, -1); b64_add(&(e->mantissa), &a1); a1.h_32 = 0; a1.l_32 = c - '0'; b64_add(&(e->mantissa), &a1); } else exp++; if (dotseen) exp--; } if (! digitseen) return; if (ss) *ss = s - 1; if (c == 'E' || c == 'e') { int exp1 = 0; int sign = 1; switch(*s) { case '-': sign = -1; case '+': s++; } if (c = *s, isdigit(c)) { do { exp1 = 10 * exp1 + (c - '0'); } while (c = *++s, isdigit(c)); if (ss) *ss = s; } exp += sign * exp1; } if (e->m1 == 0 && e->m2 == 0) return; e->exp = 63; while (! (e->m1 & 0x80000000)) { b64_sft(&(e->mantissa),-1); e->exp--; } add_exponent(e, exp); } #endif #endif #ifdef NOFLOAT con_float() { static int been_here; if (argval != 4 && argval != 8) fatal("bad fcon size"); fputs(".data4\t", codefile); if (argval == 8) fputs("0,", codefile); fputs("0 !dummy float\n", codefile); if ( !been_here++) { fputs("Warning : dummy float-constant(s)\n", stderr); } } #else con_float() { int i, j; char *p; #ifdef OWNFLOAT float fl; double f; double atof(); #else int overflow = 0; struct EXTEND e; char buf[8]; #endif if (argval!= 4 && argval!= 8) { fprintf(stderr,"float constant size = %d\n",argval); fatal("bad fcon size"); } fprintf(codefile,"!float %s sz %d\n", str, argval); #ifdef OWNFLOAT f = atof(str); if (argval == 4) { fl = f; p = (char *) &fl; } else { p = (char *) &f; } fprintf(codefile, ".data1 0%o", *p++ & 0377); for (i = argval-1; i; i--) { fprintf(codefile,",0%o", *p++ & 0377); } #else _str_ext_cvt(str, (char **) 0, &e); #if IEEEFLOAT+ACKFLOAT if (argval == 4) { #endif e.exp += 127; #ifndef IEEEFLOAT e.exp += 2; #endif if (e.m1 == 0) e.exp = 0; #if IEEEFLOAT+ACKFLOAT if (e.exp >= 255) { overflow = 1; e.exp = 255; e.m1 = e.m2 = 0; } if (e.exp <= 0) { #if IEEEFLOAT b64_sft(&(e.mantissa), 1); if (e.exp < 0) { b64_sft(&(e.mantissa), -e.exp); e.exp = 0; } #else e.exp = 0; e.m1 = e.m2 = 0; #endif } #endif buf[0] = (e.sign << 7) | (e.exp >> 1); buf[1] = ((e.exp&1) << 7) | ((e.m1 & 0x7fffffff) >> 24); buf[2] = e.m1 >> 16; buf[3] = e.m1 >> 8; if (argval == 8) { buf[4] = e.m1; buf[5] = e.m2 >> 24; buf[6] = e.m2 >> 16; buf[7] = e.m2 >> 8; b64_sft(&(e.mantissa), -56); } else b64_sft(&(e.mantissa), -24); #if IEEEFLOAT+ACKFLOAT } else { e.exp += 1023; #ifndef IEEEFLOAT e.exp += 2; #endif if (e.m1 == 0) e.exp = 0; if (e.exp >= 2047) { overflow = 1; e.exp = 2047; e.m1 = e.m2 = 0; } if (e.exp <= 0) { #if IEEEFLOAT b64_sft(&(e.mantissa), 1); if (e.exp < 0) { b64_sft(&(e.mantissa), -e.exp); e.exp = 0; } #else e.exp = 0; e.m1 = e.m2 = 0; #endif } buf[0] = (e.sign << 7) | (e.exp >> 4); buf[1] = ((e.exp & 017)<< 4) | ((e.m1&0x7fffffff) >> 27); buf[2] = e.m1 >> 19; buf[3] = e.m1 >> 11; buf[4] = e.m1 >> 3; buf[5] = (e.m1 << 5) | (e.m2 >> 27); buf[6] = e.m2 >> 19; buf[7] = e.m2 >> 11; b64_sft(&(e.mantissa), -53); } #endif if (! overflow && (e.m1 & 0x80000000)) for (i = argval-1; i>=0; i--) { if ((buf[i] &0377) != 0377) { buf[i]++; break; } else buf[i] = 0; } if (overflow || i < 0) { fprintf(stderr, "Warning: overflow in floating point constant %s\n", str); } for (i = 0; i < argval; i++) { fprintf(codefile, i != 0 ? ",0%o" : ".data1 0%o", buf[i]&0377); } #endif putc('\n', codefile); } #endif