bammi@dsrgsun.ces.cwru.edu (Jwahar R. Bammi) (11/28/88)
#!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # README.UPDATE # dflonum.c # eprintf.c # flonum.h # sflonum.s # This archive created: Thu Oct 27 21:59:41 1988 # By: Jwahar R. Bammi(Case Western Reserve University) # Uucp: {decvax,sun,att}!cwjcc!dsrgsun!bammi # Csnet: bammi@dsrgsun.ces.CWRU.edu # Arpa: bammi@dsrgsun.ces.CWRU.edu # export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile'" '(205 characters)' if test -f 'Makefile' then echo shar: over-writing existing file "'Makefile'" fi sed 's/^X//' << \SHAR_EOF > 'Makefile' Xall: lshort llong X Xlshort: X make -f Makefile.16 clean X make -f Makefile.16 X Xllong: X make -f Makefile.32 clean X make -f Makefile.32 X Xclean: X make -f Makefile.16 clean X make -f Makefile.32 clean X rm -f core SHAR_EOF if test 205 -ne "`wc -c 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 205 characters)' fi echo shar: extracting "'README.UPDATE'" '(1709 characters)' if test -f 'README.UPDATE' then echo shar: over-writing existing file "'README.UPDATE'" fi sed 's/^X//' << \SHAR_EOF > 'README.UPDATE' XThis shar file contains all the context diffs and additional files Xfor GCC minix St library update #1. The context diff are with respect Xto the GCC minix library distributed with the initial release of Xgcc v1.30 for minix St. This means that you should have *already* applied Xa set of diffs that came with that distribution to the origonal library Xsources that came with minix St, *before* you apply the diffs in this Xshar file. X XAcknowledgements: X Many thanks to John Denning who contributed the fixed Xfloating point support routines and to Scott McCauley who initially Xwrote them. Thanks also to Frans Meulenbroeks and Terrence Holm who Xhave been regularly sending fixes for the library code to the net. X XInstallation: X X - please double check that the SRC directory contains the X library source obtained by applying diffs that came with X the initial distribution of gcc v1.30 to files from X /usr/src/lib, and by adding additional files that came X which came with that distribution. X X - copy all the files in this directory to the SRC directory. X - apply the diffs using Larry Wall's patch program X patch < lib-updat1.diff X - edit Makefile.16 and Makefile.32 to adjust $(CROSSDIR) X - run the following command to build all the library objects X make -f Makefile.16 to build all the 16 bit integer objects X make -f Makefile.16 clean to clean them out X make -f Makefile.32 to build all the 32 bit integer objects X (alternately you can just hit make, in which case it will use X Makefile) X X Please send your feed-back to: X-- Xusenet: {decvax,sun}!cwjcc!dsrgsun!bammi jwahar r. bammi Xcsnet: bammi@dsrgsun.ces.CWRU.edu Xarpa: bammi@dsrgsun.ces.CWRU.edu XcompuServe: 71515,155 SHAR_EOF if test 1709 -ne "`wc -c 'README.UPDATE'`" then echo shar: error transmitting "'README.UPDATE'" '(should have been 1709 characters)' fi echo shar: extracting "'dflonum.c'" '(18187 characters)' if test -f 'dflonum.c' then echo shar: over-writing existing file "'dflonum.c'" fi sed 's/^X//' << \SHAR_EOF > 'dflonum.c' X/* A working Gnulib68k, thanks to Scott McCauley for the origonal X version, and John Dunning (jrd@STONY-BROOK.SCRC.Symbolics.COM) X who got this working. X X Please not that only the double float. stuff is picked up from X here, the other long-int and single float stuff come from X fixnum.s and sflonum.s (see flonum.h for the appr. #defs). X ++jrb X */ X X/* Subroutines needed by GCC output code for the 68000/20. X X Compile using -O flag with gcc. X Use the -m68000 flag if you have a 68000 X X This package includes 32 bit integer and 64-bit floating X point routines. X X WARNING: alpha-test version (July 1988) -- probably full of bugs. X If you find a bug, send bugs reports to jsm@phoenix.princeton.edu, X or X X Scott McCauley X PPPL P. O. Box 451 X Princeton NJ 08543 X X Known bugs/features: X X 1) Depending on the version of GCC, this may produce a lot of X warnings about conversion clashes, etc. It should still compile X as is. Also, there appears to be a bug in the register-allocation X parts of gcc that makes the compiler sometimes core dump X or run into an infinite loop. This version works -- if you X decide to change routines these compiler bugs can bite very hard.... X X 2) all single-precision gets converted to double precision in the X math routines (in accordance with K&R), so doing things in X double precision is faster than single precision.... X X 3) double precision floating point division may not be accurate to X the last four or so bits. Most other routines round to the X lsb. X X 4) no support of NaN and Inf X X 5) beware of undefined operations: i.e. a float to integer conversion X when the float is larger than MAXIINT. X X */ X X#include <stdio.h> X/* #include <math.h> */ X X#include "flonum.h" X X#define umultl _umulsi X#define multl _mulsi3 X#define udivl _udivsi3 X#define divl _divsi3 X#define ddiv _divdf3 X#define qmult _qmult X#define dmult _muldf3 X#define dneg _negdf2 X#define dadd _adddf3 X#define dcmp _cmpdf2 X#define dtoul _fixunsdfsi X#define dtol _fixdfsi X#define ltod _floatsidf X X#if 0 /* see eprintf.c in minix library */ X#ifdef L_eprintf X#include <stdio.h> X/* This is used by the `assert' macro. */ Xvoid X _eprintf (string, line) Xchar *string; Xint line; X{ X fprintf (stderr, string, line); X} X#endif X#endif X X#ifdef L_umulsi3 X X/*_umulsi3 (a, b) unsigned a, b; { return a * b; } */ X Xunsigned long umultl(a,b) Xunsigned long a, b; X{ X register unsigned long d7, d6, d5, d4; X X d7 = a; X d6 = b; X d5 = d6; X d4 = d6; X /* without the next line, gcc may core dump. Gcc sometimes X gets confused if you have too many registers */ X X &a; &b; X X /*printf("a %u b %u\n", a, b);*/ X X /* low word */ X MUL(d7, d6); X SWAP(d5); X MUL(d7, d5); X SWAP(d7); X MUL(d7, d4); X d4 += d5; X SWAP(d4); X d4 &= 0xFFFF0000; X d4 += d6; X return(d4); X} X#endif X X#ifdef L_mulsi3 X/* _mulsi3 (a, b) int a, b; { return a * b; } */ X Xlong multl(a, b) Xlong a, b; X{ X int sign = 0; X long umultl(); X if ((a ^ b) < 0) sign = 1; X if (a < 0) a = -a; X if (b < 0) b = -b; X /*printf("a is %d b is %d\n", a, b);*/ X if (sign) return(- umultl(a,b)); X else return(umultl(a,b)); X} X X#endif X X#ifdef L_udivsi3 X/*_udivsi3 (a, b) unsigned a, b; { return a / b; } */ X X/* X this routine based on one in the PD forth package for the sun by Mitch Bradley X */ X Xunsigned udivl(u, v) Xregister unsigned long u, v; X{ X register unsigned short um, ul, vm, vl; X unsigned long ans; X unsigned long u1, v1; X long i; X long rem; X X if (v == 0) { X /* should cause an exception condition */ X DIV(u, v); X fprintf(stderr, "division by zero\n"); X } X if (v > u) return(0); X X ul = u; SWAP(u); um = u; X vl = v; SWAP(v); vm = v; X if (vm == 0) { X u = vl; v = um; X DIV(u, v); X /* note -- if you delete the next line, gcc goes into X an infinite loop */ X if (vm) printf("result is %d\n", v); X vm = v & 0xFFFF; /* dividend is in low word */ X v &= 0xFFFF0000; /* remainder is in high word */ X v += ul; X DIV(vl, v); X v &= 0xFFFF; /* dividend is in low word */ X u = vm; X SWAP(u); X return(v + u); X /*ans = ((um / vl) << 16) + ((((um % vl) << 16) + ul) / vl); X return(ans);*/ X } X X if (vl == 0) return(um / vm); X SWAP(u); SWAP(v); X if ( (u >> 3) < v) { X for(i = 0; u >= v; i++, u -= v); X /*printf("lt 8\n");*/ X return(i); X } X u1 = u; v1 = v; X X /* scale divisor */ X v1--; X for(i = 0; ((unsigned) v1) >= 0xFFFF; v1 >>= 1, i++); X if (++v1 > 0xFFFF) { X i++; v1 >>=1; X } X u1 >>= i; X /*printf("i is %d, u1 is %x, v1 is %x\n", i, u1, v1);*/ X ans = u1 / v1; X rem = u - (ans * v); X if (rem > v) {ans++; rem -= v; } X if (rem > v) {printf("oops\n");} X return(ans); X} X#endif X X#ifdef L_divsi3 X Xlong divl(a, b) Xlong a, b; X{ X int sign = 0; X if ((a ^ b) < 0) sign = 1; X if (a < 0) a = -a; X if (b < 0) b = -b; X if (sign) return(-udivl(a,b)); X else return(udivl(a,b)); X} X#endif X X#ifdef L_umodsi3 X_umodsi3 (a, b) Xunsigned a, b; X{ X /*return a % b;*/ X return (a - ((a/b)*b)); X} X#endif X X#ifdef L_modsi3 X_modsi3 (a, b) Xint a, b; X{ X /*return a % b;*/ X return( a - ((a/b) * b)); X} X#endif X X#ifdef L_lshrsi3 X_lshrsi3 (a, b) Xunsigned a, b; X{ X return a >> b; X} X#endif X X#ifdef L_lshlsi3 X_lshlsi3 (a, b) Xunsigned a, b; X{ X return a << b; X} X#endif X X#ifdef L_ashrsi3 X_ashrsi3 (a, b) Xint a, b; X{ X return a >> b; X} X#endif X X#ifdef L_ashlsi3 X_ashlsi3 (a, b) Xint a, b; X{ X return a << b; X} X#endif X X X/* this divide stuff is hopelessly broken, in addition to being much X more complicated than in needs to be. The new version's at the X end of this file */ X X#if 0 X#ifdef L_divdf3 X X/*double _divdf3 (a, b) double a, b; { return a / b; } */ X Xdouble drecip1(f1) Xdouble f1; X{ X struct bitdouble *bdp = &f1; X unsigned m1, m2; X X printf("drecip1(%X)", f1); X if (bdp->exp == 0 ) return(0L); X if (bdp->mant1 == 0L) { X bdp->exp = 0x3ff + 0x3ff - bdp->exp; X bdp->mant2 = 0L; X return(f1); X } X bdp->exp = 0x3ff + 0x3ff - bdp->exp - 1; X m1 = (0x00100000 + bdp->mant1) >> 5; X m2 = (0x80000000 / m1); X /*printf("m1 %x m2 %x\n", m1, m2);*/ X m2 <<= 5; X m2 &= 0xFFFFF; X /*printf("exp %x mant %x\n", bdp->exp, m2);*/ X bdp->mant1 = m2; X bdp->mant2 = 0L; X printf("drecip1->%X\n", f1); X return(f1); X} X Xdouble drecip(f) Xdouble f; X{ X struct bitdouble *bdp; X double quotient, remainder; X X printf("drecip(%X)", f); X quotient = drecip1(f); X remainder = /* 1.0 */ ((double)one) - quotient * f; X bdp = &remainder; X for(; bdp->exp > 0x3ca; ) { X printf("drc: exp=%X ", bdp->exp); X remainder = /* 1.0 */ ((double)one) - (quotient*f); X printf("rem=%X ", remainder); X quotient = quotient + (drecip1(f)*remainder); X } X printf("drecip->%X\n", quotient); X return(quotient); X} X X Xdouble ddiv(f1, f2) Xdouble f1, f2; X{ X return(f1 * drecip(f2)); X} X#endif X#endif /* commented out divide routines */ X X#ifdef L_muldf3 X/*double _muldf3 (a, b) double a, b; { return a * b; } */ Xqmult(m11, m12, m21, m22, p1, p2) Xunsigned long m11, m12, m21, m22, *p1, *p2; X{ X/* register unsigned long d2 = m11; */ X register long d2 = m11; X register unsigned long d3 = m12, d4 = m21, d5 = m22, d6 =0, d7 = 0; X int i; X /* guess what happens if you delete the next line.... */ X /* &i; */ X for (i = 0; i < 11; i++) ASL2(d2, d3); X for (i = 0; i < 9; i++) ASL2(d4, d5); X X for (i = 0; i < 64; i++) { X if (d2 < 0) { ADD2(d4, d5, d6, d7);} X ASL2(d2, d3); X ASR2(d4, d5); X } X d2 = d6; X d3 = d7; X for (i = 0; i < 9; i++) ASR2(d2, d3); X *p1 = d2; *p2 = d3; X} X Xdouble dmult(f1, f2) Xdouble f1, f2; X{ X register unsigned long d2; X register unsigned d3, d4, d5, d6, d7; X unsigned long p1, p2; X X struct bitdouble X *bdp1 = (struct bitdouble *)&f1, X *bdp2 = (struct bitdouble *)&f2; X int exp1, exp2, i; X X exp1 = bdp1->exp; exp2 = bdp2->exp; X /* check for zero */ X if (! exp1) return(0.0); X if (! exp2) return(0.0); X d2 = 0x00100000 + bdp1->mant1; X d3 = bdp1->mant2; X d4 = 0x00100000 + bdp2->mant1; X d5 = bdp2->mant2; X qmult(d2, d3, d4, d5, &p1, &p2); X d6 = p1; d7 = p2; X X if (d6 & 0x00200000) { X ASR2(d6, d7); X exp1++; X } X X if (bdp1->sign == bdp2->sign) bdp1->sign = 0; X else bdp1->sign = 1; X bdp1->exp = exp1 + exp2 - 0x3ff; X bdp1->mant1 = d6; X bdp1->mant2 = d7; X return(f1); X} X#endif X X#ifdef L_negdf2 X/*double _negdf2 (a) double a; { return -a; } */ X Xdouble dneg(num) Xdouble num; X{ X long *i = (long *)# X *i ^= 0x80000000; X return(num); X} X#endif X X#ifdef L_adddf3 X/*double _adddf3 (a, b) double a, b; { return a + b; } */ X Xdouble dadd(f1, f2) Xdouble f1, f2; X{ X X register long d4, d5, d6, d7; X struct bitdouble X *bdp1 = (struct bitdouble *)&f1, X *bdp2 = (struct bitdouble *)&f2; X short exp1, exp2, sign1, sign2, howmuch, temp; X X exp1 = bdp1->exp; exp2 = bdp2->exp; X X /* check for zero */ X if (! exp1) return(f2); if (! exp2) return(f1); X X /* align them */ X if (exp1 < exp2) { X bdp1 = (struct bitdouble *)&f2; bdp2 = (struct bitdouble *)&f1; X exp1 = bdp1->exp; exp2 = bdp2->exp; X } X howmuch = exp1 - exp2; X if (howmuch > 53) return(f1); X X d7 = bdp2->mant1 + 0x00100000; X d6 = bdp2->mant2; X X d5 = bdp1->mant1 + 0x00100000; X d4 = bdp1->mant2; X X for (temp = 0; temp < howmuch; temp++) ASR2(d7, d6); X X /* take care of negative signs */ X if (bdp1->sign) X { X NEG(d5, d4); X } X if (bdp2->sign) X { X NEG(d7, d6); X } X X ADD2(d7, d6, d5, d4); X bdp1 = (struct bitdouble *)&f1; X X if (d5 < 0) { X NEG(d5, d4); X bdp1->sign = 1; X } else bdp1->sign = 0; X X if (d5 == 0 && d4 == 0) return(0.0); X X for(howmuch = 0; d5 >= 0; howmuch++) ASL2(d5, d4); X X ASL2(d5, d4); X for (temp = 0; temp < 12; temp++) ASR2(d5, d4); X bdp1->mant1 = d5; X bdp1->mant2 = d4; X bdp1->exp = exp1 + 11 - howmuch; X return(f1); X} X X#endif X X#ifdef L_subdf3 Xdouble X _subdf3 (a, b) Xdouble a, b; X{ X return a+(-b); X} X#endif X X#ifdef L_cmpdf2 X/* X int _cmpdf2 (a, b) double a, b; { if (a > b) return 1; X else if (a < b) return -1; return 0; } X */ X Xint dcmp(f1, f2) Xdouble f1, f2; X{ X struct bitdouble *bdp1, *bdp2; X unsigned int s1, s2; X bdp1 = (struct bitdouble *)&f1; X bdp2 = (struct bitdouble *)&f2; X s1 = bdp1->sign; X s2 = bdp2->sign; X if (s1 > s2) return(-1); X if (s1 < s2) return(1); X /* if sign of both negative, switch them */ X if (s1 != 0) { X bdp1 = (struct bitdouble *)&f1; X bdp2 = (struct bitdouble *)&f2; X } X s1 = bdp1->exp; X s2 = bdp2->exp; X if (s1 > s2) return(1); X if (s1 < s2) return(-1); X /* same exponent -- have to compare mantissa */ X s1 = bdp1->mant1; X s2 = bdp2->mant1; X if (s1 > s2) return(1); X if (s1 < s2) return(-1); X s1 = bdp1->mant2; X s2 = bdp2->mant2; X if (s1 > s2) return(1); X if (s1 < s2) return(-1); X return(0); /* the same! */ X} X#endif X X#ifdef L_fixunsdfsi X/*_fixunsdfsi (a) double a; { return (unsigned int) a; } */ X X/* #ifdef L_fixdfsi _fixdfsi (a) double a; { return (int) a; } #endif */ X Xunsigned long dtoul(f) Xdouble f; X{ X struct bitdouble *bdp; X int si, ex, mant1, mant2; X bdp = (struct bitdouble *)&f; X si = bdp->sign; X ex = bdp->exp; X mant1 = bdp->mant1 + 0x00100000; X mant2 = bdp->mant2; X X /* zero value */ X if (ex == 0) return(0L); X /* less than 1 */ X if (ex < 0x3ff) return(0L); X /* less than 0 */ X if (si ) return(0L); X mant1 <<= 10; X mant1 += (mant2 >> 22); X mant1 >>= 30 + (0x3ff - ex); X return(mant1); X} X Xlong dtol(f) Xdouble f; X{ X struct bitdouble *bdp = (struct bitdouble *)&f; X X if (bdp->sign) { X bdp->sign = 0; X return( - dtoul(f)); X } X return(dtoul(f)); X} X#endif X X#ifdef L_fixunsdfdi X X/*double _fixunsdfdi (a) double a; { union double_di u; X u.i[LOW] = (unsigned int) a; u.i[HIGH] = 0; return u.d; } */ X#endif X X X#ifdef L_fixdfdi Xdouble X _fixdfdi (a) Xdouble a; X{ X union double_di u; X u.i[LOW] = (int) a; X u.i[HIGH] = (int) a < 0 ? -1 : 0; X return u.d; X} X#endif X X#ifdef L_floatsidf X/* double _floatsidf (a) int a; { return (double) a; } */ X Xdouble ltod(i) Xlong i; X{ X int expo, shift; X double retval; X struct bitdouble *bdp = (struct bitdouble *)&retval; X if (i == 0) { X long *t = (long *)&retval; X t[0] = 0L; X t[1] = 0L; X return(retval); X } X if (i < 0) { X bdp->sign = 1; X i = -i; X } else bdp->sign = 0; X shift = i; X for (expo = 0x3ff + 31 ; shift > 0; expo--, shift <<= 1); X shift <<= 1; X bdp->exp = expo; X bdp->mant1 = shift >> 12; X bdp->mant2 = shift << 20; X return(retval); X} X X#endif X X#ifdef L_floatdidf X/* ok as is -- will call other routines */ Xdouble X _floatdidf (u) Xunion double_di u; X{ X register double hi X = ((double) u.i[HIGH]) * (double) 0x10000 * (double) 0x10000; X register double low = (unsigned int) u.i[LOW]; X return hi + low; X} X#endif X X#ifdef L_addsf3 XSFVALUE X _addsf3 (a, b) Xunion flt_or_int a, b; X{ X union flt_or_int intify; return INTIFY ((double) a.f + (double) b.f); X} X#endif X X#ifdef L_negsf2 XSFVALUE X _negsf2 (a) Xunion flt_or_int a; X{ X union flt_or_int intify; X return INTIFY (-((double) a.f)); X} X#endif X X#ifdef L_subsf3 XSFVALUE X _subsf3 (a, b) Xunion flt_or_int a, b; X{ X union flt_or_int intify; X return INTIFY (((double) a.f - (double) b.f)); X} X#endif X X#ifdef L_cmpsf2 XSFVALUE X _cmpsf2 (a, b) Xunion flt_or_int a, b; X{ X union flt_or_int intify; X double a1, b1; X a1 = a.f; b1 = b.f; X if ( a1 > b1) X return 1; X else if (a1 < b1) X return -1; X return 0; X} X#endif X X#ifdef L_mulsf3 XSFVALUE X _mulsf3 (a, b) Xunion flt_or_int a, b; X{ X union flt_or_int intify; X return INTIFY (((double) a.f * (double) b.f)); X} X#endif X X#ifdef L_divsf3 XSFVALUE X _divsf3 (a, b) Xunion flt_or_int a, b; X{ X union flt_or_int intify; X return INTIFY (((double) a.f / (double) b.f)); X} X#endif X X#ifdef L_truncdfsf2 Xfloat dtof(d) Xdouble d; X{ X struct bitdouble *bdp = (struct bitdouble *)&d; X float retval; X struct bitfloat *bfp = (struct bitfloat *)&retval; X int tempval; X X bfp->sign = bdp->sign; X if (bdp->exp == 0) return ((float) 0.0); X bfp->exp = bdp->exp - 0x400 + 0x80; X tempval = (bdp->mant1 << 4 ) + ((0xF0000000 & bdp->mant2) >> 28); X /* round */ X tempval++; X if (tempval == 0x01000000) bfp->exp++; X bfp->mant = tempval >> 1; X return(retval); X} X XSFVALUE X _truncdfsf2 (a) Xdouble a; X{ X union flt_or_int intify; X return INTIFY (dtof(a)); X} X#endif X X#ifdef L_extendsfdf2 Xdouble ftod(f) Xunion flt_or_int f; X{ X double retval; X struct bitfloat *bfp = (struct bitfloat *)&f.f; X struct bitdouble *bdp = (struct bitdouble *)&retval; X if (bfp->exp == 0) return(0.0); X bdp->sign = bfp->sign; X bdp->exp = 0x400 - 0x80 + bfp->exp; X bdp->mant1 = bfp->mant >> 3; X bdp->mant2 = (bfp->mant & 0x7) << 29; X /*printf("returning %f from extendsfdf2\n", retval);*/ X return(retval); X} X Xdouble X _extendsfdf2 (a) Xunion flt_or_int a; X{ X union flt_or_int intify; X double retval; X return (ftod(a)); X} X#endif X X#ifdef L_divdf3 X X/* new double-float divide routine, by jrd */ X/* thanks jrd !! */ X Xdouble _divdf3(num, denom) Xdouble num, denom; X{ X double local_num = num; X double local_denom = denom; X struct bitdouble * num_bdp = (struct bitdouble *)(&local_num); X struct bitdouble * den_bdp = (struct bitdouble *)(&local_denom); X short num_exp = num_bdp->exp, X den_exp = den_bdp->exp; X short result_sign = 0; X /* register */ unsigned long num_m1, num_m2, num_m3, num_m4; X register unsigned long den_m1, den_m2, den_m3, den_m4; X unsigned long result_mant[2]; X unsigned long result_mask; X short result_idx; X X if ((num_exp == 0) || (den_exp == 0)) /* zzz should really cause trap */ X return(0.0); X X /* deal with signs */ X result_sign = result_sign + num_bdp->sign - den_bdp->sign; X X /* unpack the numbers */ X num_m1 = num_bdp->mant1 | 0x00100000; /* hidden bit */ X num_m2 = num_bdp->mant2; X num_m3 = /* ret_kludge(0); */ 0; X num_m4 = num_m3; X den_m1 = den_bdp->mant1 | 0x00100000; /* hidden bit */ X den_m2 = den_bdp->mant2; X den_m3 = /* ret_kludge(0); */ 0; X den_m4 = den_m3; X X#if 0 X /* buy a little extra accuracy by shifting num and denum up 10 bits */ X for (result_idx /* loop counter */ = 0 ; result_idx < 10 ; result_idx++) X { X ASL3(num_m1, num_m2, num_m3); X ASL3(den_m1, den_m2, den_m3); X } X#endif X X /* hot wire result mask and index */ X result_mask = 0x00100000; /* start at top mantissa bit */ X result_idx = 0; /* of first word */ X result_mant[0] = num_m3; X result_mant[1] = den_m3; X X /* if denom is greater than num here, shift denom right one and dec num expt */ X if (den_m1 < num_m1) X goto kludge1; /* C is assembly language, X remember? */ X if (den_m1 > num_m1) X goto kludge0; X if (den_m2 <= num_m2) /* first word eq, try 2nd */ X goto kludge1; X X kludge0: X X num_exp--; X ASR4(den_m1, den_m2, den_m3, den_m4); X X kludge1: X X for ( ; result_mask ; ) X { X /* if num >= den, subtract den from num and set bit in result */ X if (num_m1 > den_m1) goto kludge2; X if (num_m1 < den_m1) goto kludge3; X if (num_m2 > den_m2) goto kludge2; X if (num_m2 < den_m2) goto kludge3; X if (num_m3 > den_m3) goto kludge2; X if (num_m3 < den_m3) goto kludge3; X if (num_m4 < den_m4) goto kludge3; X X kludge2: X result_mant[result_idx] |= result_mask; X SUB4(den_m1, den_m2, den_m3, den_m4, num_m1, num_m2, num_m3, num_m4); X kludge3: X ASR4(den_m1, den_m2, den_m3, den_m4); X result_mask >>= 1; X if ((result_mask == 0) && (result_idx == 0)) X { X result_mask = 0x80000000; X result_idx++; X } X } X X /* compute the resultant exponent */ X num_exp = num_exp - den_exp + 0x3FF; X X /* reconstruct the result in local_num */ X num_bdp->sign = result_sign; X num_bdp->exp = num_exp; X num_bdp->mant1 = result_mant[0] & 0xFFFFF; X num_bdp->mant2 = result_mant[1]; X X /* done! */ X return(local_num); X} X#endif SHAR_EOF if test 18187 -ne "`wc -c 'dflonum.c'`" then echo shar: error transmitting "'dflonum.c'" '(should have been 18187 characters)' fi echo shar: extracting "'eprintf.c'" '(230 characters)' if test -f 'eprintf.c' then echo shar: over-writing existing file "'eprintf.c'" fi sed 's/^X//' << \SHAR_EOF > 'eprintf.c' X#include <stdio.h> X/* This is used by the `assert' macro. */ X X#ifdef __GNUC__ Xvoid X#endif X__eprintf (string, line, filename) X char *string; X long line; X char *filename; X{ X fprintf (stderr, string, line, filename); X} SHAR_EOF if test 230 -ne "`wc -c 'eprintf.c'`" then echo shar: error transmitting "'eprintf.c'" '(should have been 230 characters)' fi echo shar: extracting "'flonum.h'" '(4078 characters)' if test -f 'flonum.h' then echo shar: over-writing existing file "'flonum.h'" fi sed 's/^X//' << \SHAR_EOF > 'flonum.h' X X/* Defs and macros for floating point code. This stuff is heavily based X on Scott McCauley's code, except that this version works :-} */ X X X/* These definitions work for machines where an SF value is X returned in the same register as an int. */ X X#ifndef SFVALUE X#define SFVALUE int X#endif X X#ifndef INTIFY X#define INTIFY(FLOATVAL) (intify.f = (FLOATVAL), intify.i) X#endif X X/* quasi-IEEE floating point number definitions */ X Xstruct bitfloat { X unsigned sign : 1; X unsigned exp : 8; X unsigned mant : 23; X}; X Xstruct bitdouble { X unsigned sign : 1; X unsigned exp : 11; X unsigned mant1 : 20; X unsigned long mant2; X}; X Xunion double_di { double d; int i[2]; }; Xunion flt_or_int { int i; float f; }; X X#ifdef WORDS_BIG_ENDIAN X#define HIGH 0 X#define LOW 1 X#else X#define HIGH 1 X#define LOW 0 X#endif X X/* start of symbolic asm definitions */ X X/* you may have to change the g's to d's if you start getting X illegal operands from as */ X X#define MUL(a, b) asm volatile ("mulu %2,%0" : "=d" (b) : "0" (b) , "g" (a)) X#define DIV(a, b) asm volatile ("divu %2,%0" : "=d" (b) : "0" (b) , "g" (a)) X#define SWAP(a) asm volatile ("swap %0" : "=r" (a) : "r" (a) , "r" (a) ) X X#define ASL2(r1, r2) { asm volatile ("asll #1,%0" : "=d" (r2) : "d" (r2));\ X asm volatile ("roxll #1,%0" : "=d" (r1) : "d" (r1)); } X#define ASL3(r1, r2, r3) { asm volatile ("asll #1,%0" : "=d" (r3) : "d" (r3));\ X asm volatile ("roxll #1,%0" : "=d" (r2) : "d" (r2));\ X asm volatile ("roxll #1,%0" : "=d" (r1) : "d" (r1)); } X X#define ASR2(r1, r2) { asm volatile ("asrl #1,%0" : "=d" (r1) : "d" (r1));\ X asm volatile ("roxrl #1,%0" : "=d" (r2) : "d" (r2)); } X#define ASR3(r1, r2, r3) { asm volatile ("asrl #1,%0" : "=d" (r1) : "d" (r1));\ X asm volatile ("roxrl #1,%0" : "=d" (r2) : "d" (r2));\ X asm volatile ("roxrl #1,%0" : "=d" (r3) : "d" (r3)); } X#define ASR4(r1, r2, r3, r4) { asm volatile ("asrl #1,%0" : "=d" (r1) : "d" (r1));\ X asm volatile ("roxrl #1,%0" : "=d" (r2) : "d" (r2));\ X asm volatile ("roxrl #1,%0" : "=d" (r3) : "d" (r3));\ X asm volatile ("roxrl #1,%0" : "=d" (r4) : "d" (r4)); } X X#define ADD2(r1, r2, r3, r4) \ X { asm volatile ("addl %2,%0": "=g" (r4) : "0" (r4) , "g" (r2)); \ X asm volatile ("addxl %2,%0": "=g" (r3) : "0" (r3) , "g" (r1)); } X X/* y <- y - x */ X#define SUB3(x1, x2, x3, y1, y2, y3) \ X { asm volatile ("subl %2,%0": "=g" (y3) : "g" (y3) , "d" (x3)); \ X asm volatile ("subxl %2,%0": "=g" (y2) : "g" (y2) , "d" (x2));\ X asm volatile ("subxl %2,%0": "=g" (y1) : "g" (y1) , "d" (x1)); } X X/* sub4 here is rather complex, as the compiler is overwhelmed by me wanting X to have 8 data registers allocated for mantissa accumulators. Help it out X by declaring a temp that it can move stuff in and out of. */ X#define SUB4(x1, x2, x3, x4, y1, y2, y3, y4) \ X { register long temp = y4; \ X asm volatile ("subl %2,%0": "=d" (temp) : "d" (temp) , "d" (x4)); \ X y4 = temp; temp = y3; \ X asm volatile ("subxl %2,%0": "=d" (temp) : "d" (temp) , "d" (x3));\ X y3 = temp; temp = y2; \ X asm volatile ("subxl %2,%0": "=d" (temp) : "d" (temp) , "d" (x2));\ X y2 = temp; temp = y1; \ X asm volatile ("subxl %2,%0": "=d" (temp) : "d" (temp) , "d" (x1));\ X y1 = temp; } X X#define NEG(r1, r2) { asm volatile ("negl %0" : "=d" (r2) : "d" (r2)); \ X asm volatile ("negxl %0" : "=d" (r1) : "d" (r1)); } X X/* switches for which routines to compile. All the single-float and Xlong-int arithmetic routines are turned off here, as they were all Xdone in assembly language last year. */ X X/* X#define L_umulsi3 X#define L_mulsi3 X#define L_udivsi3 X#define L_divsi3 X#define L_umodsi3 X#define L_modsi3 X#define L_lshrsi3 X#define L_lshlsi3 X#define L_ashrsi3 X#define L_ashlsi3 X*/ X#define L_divdf3 X#define L_muldf3 X#define L_negdf2 X#define L_adddf3 X#define L_subdf3 X#define L_cmpdf2 X#define L_fixunsdfsi X#define L_fixunsdfdi X#define L_fixdfdi X#define L_floatsidf X#define L_floatdidf X/* X#define L_addsf3 X#define L_negsf2 X#define L_subsf3 X#define L_cmpsf2 X#define L_mulsf3 X#define L_divsf3 X*/ X#define L_truncdfsf2 X#define L_extendsfdf2 X SHAR_EOF if test 4078 -ne "`wc -c 'flonum.h'`" then echo shar: error transmitting "'flonum.h'" '(should have been 4078 characters)' fi echo shar: extracting "'sflonum.s'" '(15211 characters)' if test -f 'sflonum.s' then echo shar: over-writing existing file "'sflonum.s'" fi sed 's/^X//' << \SHAR_EOF > 'sflonum.s' X# X# X# Floating point support code. What a crock! X# X# A float looks like: X# X# |S|E.x.p ... |M.a.n.t.i.s.s.a ... | X# +-+----------+--------------------+ X# X# where s is the sign bit, Exp is 8 bits of exponent, interpreted X# as E + 126, and Mantissa is 23 bits of fraction, with a X# hidden bit. The point is to the left of the hidden bit. X# Doubles have another word of mantissa following. X# X# All these routines have calling sequences like c routines, X# ie args on stack in backwards order, return values in d0 X# X X# union double_di { double d; int i[2]; }; X# union flt_or_int { int i; float f; }; X# X## #ifdef L_divdf3 X## double X## _divdf3 (a, b) X## double a, b; X## { X## return a / b; X## } X## #endif X#.text X# .even X#.globl __divdf3 X#__divdf3: X# movel sp@(12),sp@- X# movel sp@(8),sp@- X# jsr __divsf3 X# addql #8,sp X# clrl d1 | kludge!!! X# rts | sigh X## X## #ifdef L_muldf3 X## double X## _muldf3 (a, b) X## double a, b; X## { X## return a * b; X## } X## #endif X# X#.text X# .even X#.globl __muldf3 X#__muldf3: X# movel sp@(12),sp@- X# movel sp@(8),sp@- X# jsr __mulsf3 X# addql #8,sp X# clrl d1 | kludge!!! X# rts | sigh X## X## #ifdef L_negdf2 X## double X## _negdf2 (a) X## double a; X## { X## return -a; X## } X## #endif X# X#.text X# .even X#.globl __negdf2 X#__negdf2: X# movel sp@(8),d1 | get a lo X# movel sp@(4),d0 | get a hi X# beq negdf2_z | zero, leave it X# eorl #0x80000000,d0 | twiddle sign X#negdf2_z: X# rts X## X## #ifdef L_adddf3 X## double X## _adddf3 (a, b) X## double a, b; X## { X## return a + b; X## } X## #endif X# X#.text X# .even X#.globl __adddf3 X#__adddf3: X# movel sp@(12),sp@- X# movel sp@(8),sp@- X# jsr __addsf3 X# addql #8,sp X# clrl d1 | kludge!!! X# rts | sigh X## X## #ifdef L_subdf3 X## double X## _subdf3 (a, b) X## double a, b; X## { X## return a - b; X## } X## #endif X# X#.text X# .even X#.globl __subdf3 X#__subdf3: X# movel sp@(12),sp@- X# movel sp@(8),sp@- X# jsr __subsf3 X# addql #8,sp X# clrl d1 | kludge!!! X# rts | sigh X## X## #ifdef L_cmpdf2 X## int X## _cmpdf2 (a, b) X## double a, b; X## { X## if (a > b) X## return 1; X## else if (a < b) X## return -1; X## return 0; X## } X## #endif X# X#.text X# .even X#.globl __cmpdf2 X#__cmpdf2: X# movel sp@(4),d0 | get b hi X# movel sp@(12),d1 | get a hi X#| X#| crockery. If both neg and not equal, this algorithm lose. find a better one! X#| X# bpl cmpdf2_p X# tstl d0 X# bpl cmpdf2_p X# cmpl d1,d0 X# bgt cmpdf2_m X# blt cmpdf2_1 X# beq cmpdf2_z X#cmpdf2_p: X# cmpl d1,d0 | get a hi X# beq cmpdf2_z | if eq, return 0 X# bgt cmpdf2_1 | if greater, return 1 X#cmpdf2_m: X# movel #-1,d0 | else return -1 X# rts X#cmpdf2_z: X# clrl d0 X# rts X#cmpdf2_1: X# movel #1,d0 X# rts | sigh X## X## #ifdef L_fixunsdfsi X## _fixunsdfsi (a) X## double a; X## { X## return (unsigned int) a; X## } X## #endif X# X#.text X# .even X#.globl __fixunsdfsi X#__fixunsdfsi: X# clrl d0 X# clrl d1 X# rts | sigh X## X## #ifdef L_fixunsdfdi X## double X## _fixunsdfdi (a) X## double a; X## { X## union double_di u; X## u.i[LOW] = (unsigned int) a; X## u.i[HIGH] = 0; X## return u.d; X## } X## #endif X# X#.text X# .even X#.globl __fixunsdfdi X#__fixunsdfdi: X# clrl d0 X# clrl d1 X# rts | sigh X## X## #ifdef L_fixdfsi X## _fixdfsi (a) X## double a; X## { X## return (int) a; X## } X## #endif X# X#.text X# .even X#.globl __fixdfsi X#__fixdfsi: X# link a6,#0 X# movel d2,sp@- | save reg X# clrl d2 | sign flag X# movel a6@(8),d0 | get the float X# beq fixdfsi_ret X# bpl fixdfsi_1 X# addql #1,d2 X#fixdfsi_1: X# movel d0,d1 | snag the exp X# lsrl #7,d1 X# lsrl #8,d1 X# lsrl #8,d1 X# andl #0xFF,d1 X# subl #126,d1 X# andl #0x7FFFFF,d0 | zap cruft X# orl #0x800000,d0 | put back hidden bit X#| X#| at this point the mantissa looks like 2^24 * integer value. X#| if Exp is 24, we're done. If it's less, we shift right, X#| else left X#| X#fixdfsi_2: X# cmpl #24,d1 X# beq fixdfsi_4 | we're done X# bmi fixdfsi_3 | less, shift right X# lsll #1,d0 | greater, shift it left one X# subql #1,d1 | and dec exp X# bra fixdfsi_2 X#fixdfsi_3: X# lsrl #1,d0 | shift right one X# addql #1,d1 | and inc exp X# bra fixdfsi_2 X#fixdfsi_4: X# tstl d2 | negative? X# beq fixdfsi_ret X# negl d0 X#fixdfsi_ret: X# movel sp@+,d2 | get d2 back X# unlk a6 X# rts X## X## #ifdef L_fixdfdi X## double X## _fixdfdi (a) X## double a; X## { X## union double_di u; X## u.i[LOW] = (int) a; X## u.i[HIGH] = (int) a < 0 ? -1 : 0; X## return u.d; X## } X## #endif X# X#.text X# .even X#.globl __fixdfdi X#__fixdfdi: X# clrl d0 X# clrl d1 X# rts | sigh X## X## #ifdef L_floatsidf X## double X## _floatsidf (a) X## int a; X## { X## return (double) a; X## } X## #endif X# X#.text X# .even X#.globl __floatsidf X#__floatsidf: X# link a6,#0 | set up frame X# movel d2,sp@- | save d2; sign flag X# clrl d2 | not negative yet X# movel #24,d1 | exponent so far X# movel a6@(8),d0 | get the int X# beq floatsidf_ret | zero? X# bpl floatsidf_1 | pos, it's ok X# negl d0 | negate it X# addql #1,d2 | bump sign X#floatsidf_1: X#| X#| normalize right if necessary X#| X# cmpl #0xFFFFFF,d0 | too big? X# ble floatsidf_2 | nope, see if need to slide left X# addql #1,d1 | bump exp X# lsrl #1,d0 | and slide mantissa right one X# bra floatsidf_1 X#floatsidf_2: X# btst #23,d0 | got a bit up here yet? X# bne floatsidf_3 | nope, go left X# subql #1,d1 | dec exp X# lsll #1,d0 | and slide mantissa left one X# bra floatsidf_2 X#floatsidf_3: X#| X#| now put it all together X#| X# andl #0x7FFFFF,d0 | zap hidden bit X# addl #126,d1 | offset exp X# andl #0xFF,d1 | trim it X# lsll #8,d1 | shift up X# lsll #8,d1 X# lsll #7,d1 X# orl d1,d0 | stuff it in X# tstl d2 | negative? X# beq floatsidf_ret X# orl #0x80000000,d0 X#floatsidf_ret: X# movel sp@+,d2 X# clrl d1 | ??? X# unlk a6 X# rts | sigh X## X## #ifdef L_floatdidf X## double X## _floatdidf (u) X## union double_di u; X## { X## register double hi X## = ((double) u.i[HIGH]) * (double) 0x10000 * (double) 0x10000; X## register double low = (unsigned int) u.i[LOW]; X## return hi + low; X## } X## #endif X# X#.text X# .even X#.globl __floatdidf X#__floatdidf: X# clrl d0 X# clrl d1 X# rts | sigh X## X# #define INTIFY(FLOATVAL) (intify.f = (FLOATVAL), intify.i) X# X# #ifdef L_addsf3 X# int X# _addsf3 (a, b) X# union flt_or_int a, b; X# { X# union flt_or_int intify; X# return INTIFY (a.f + b.f); X# } X# #endif X X.text X .even X.globl __addsf3 X__addsf3: X link a6,#0 | don't need any locals X moveml #0x3F00,sp@- | save all data registers X movel a6@(8),d0 | get a X beq addsf_ret_b | zero .. just return b X movel #23,d6 | shift count X movel d0,d2 | get the exponent X lsrl d6,d2 | and shift right X andl #0xFF,d2 | no sign bit X subl #126,d2 | offset the exponent X movel a6@(12),d1 | get b X beq addsf_ret_a X movel d1,d3 | get the exponent for b X lsrl d6,d3 | and shift right, with implicit extend X andl #0xFF,d3 | make sure we didn't get a sign bit X subl #126,d3 | off set this one too X X andl #0x7FFFFF,d0 | mask a for mantissa X orl #0x800000,d0 | and put in hidden bit X tstl a6@(8) | test the original value X bpl addsf_1 | pos, ok X negl d0 | neg, negate the mantissa Xaddsf_1: X andl #0x7FFFFF,d1 | mask b for mantissa X orl #0x800000,d1 | ditto X tstl a6@(12) | test ... X bpl addsf_2 X negl d1 | negate this one Xaddsf_2: X cmpl d2,d3 | compare Ea to Eb X blt addsf_3 | Ea > Eb X X movel d3,d5 | get Eb X subl d2,d5 | subtract Ea X asrl d5,d0 | yielding count to shift Ma right X movel d3,d5 | use this as resultant exponent X bra addsf_4 | and go rejoin common part Xaddsf_3: X movel d2,d5 | get Ea X subl d3,d5 | subtract Eb X asrl d5,d1 | yielding count to shift Mb right X movel d2,d5 | use this as resultant exponent X Xaddsf_4: X clrl d7 | zap sign flag X addl d1,d0 | add Mb to Ma X X X beq addsf_z | zero? ok, go return zero X bpl addsf_5 | positive? ok, go scale it X negl d0 | negate Mr X movel #1,d7 | remember sign Xaddsf_5: X btst #24,d0 | carry? X beq addsf_6 | nope, it's ok as is X asrl #1,d0 | shift right one X addql #1,d5 | inc exp X X| zzz check for overflow in here someplace X Xaddsf_6: X btst #23,d0 | got a bit in the right place yet? X bne addsf_7 | yes, we're done X lsll #1,d0 | shift left one X subql #1,d5 | dec exponent X bra addsf_6 Xaddsf_7: X andl #0x7FFFFF,d0 | zap out hidden bit X addl #126,d5 | add offset to exp X andl #0xFF,d5 | zap to 8 bits X movel #23,d6 | shift count X lsll d6,d5 | shift the exp up X orl d5,d0 | stick the exp in X tstl d7 | negative? X beq addsf_ret_a X orl #0x80000000,d0 | yup, negate it X bra addsf_ret_a Xaddsf_z: X clrl d0 X bra addsf_ret_a Xaddsf_ret_b: X movel a6@(12),d0 Xaddsf_ret_a: X moveml sp@+,#0x00FC | snarf back all regs X unlk a6 X rts | sigh X# X# #ifdef L_negsf2 X# int X# _negsf2 (a) X# union flt_or_int a; X# { X# union flt_or_int intify; X# return INTIFY (-a.f); X# } X# #endif X X.text X .even X.globl __negsf2 X__negsf2: X movel sp@(4),d0 X beq negsf2_z X eorl #0x80000000,d0 Xnegsf2_z: X rts | sigh X# X# #ifdef L_subsf3 X# int X# _subsf3 (a, b) X# union flt_or_int a, b; X# { X# union flt_or_int intify; X# return INTIFY (a.f - b.f); X# } X# #endif X X.text X .even X.globl __subsf3 X__subsf3: X tstl sp@(8) | kludge. just negate b and add X beq subsf_bz | zero. don't bother X eorl #0x80000000,sp@(8) | negate it X jmp __addsf3 Xsubsf_bz: X movel sp@(4),d0 X rts X X# X# #ifdef L_cmpsf2 X# int X# _cmpsf2 (a, b) X# union flt_or_int a, b; X# { X# union flt_or_int intify; X# if (a.f > b.f) X# return 1; X# else if (a.f < b.f) X# return -1; X# return 0; X# } X# #endif X X.text X .even X.globl __cmpsf2 X__cmpsf2: X movel sp@(4),d0 X movel sp@(12),d1 | get a hi X| X| crockery. If both neg and not equal, this algorithm lose. find a better one! X| X bpl cmpsf2_p X tstl d0 X bpl cmpsf2_p X cmpl d1,d0 X bgt cmpsf2_m X blt cmpsf2_1 X beq cmpsf2_z Xcmpsf2_p: X cmpl d1,d0 X beq cmpsf2_z X bgt cmpsf2_1 Xcmpsf2_m: X movel #-1,d0 X rts Xcmpsf2_z: X clrl d0 X rts Xcmpsf2_1: X movel #1,d0 X rts | sigh X# X# #ifdef L_mulsf3 X# int X# _mulsf3 (a, b) X# union flt_or_int a, b; X# { X# union flt_or_int intify; X# return INTIFY (a.f * b.f); X# } X# #endif X X.text X .even X.globl __mulsf3 X__mulsf3: X| X| multiply. take the numbers apart. shift each exponent down to X| 16 bits. unsigned multiply those. shift that down to 24 bits. X| exponent is Ea + Eb. X| X X link a6,#-8 | 64 bit accum for mult X moveml #0x3F00,sp@- | save all data registers X movel a6@(8),d0 | get a X beq mulsf3_z X movel a6@(12),d1 | get b X beq mulsf3_z X movel #23,d6 | shift count X movel d0,d2 | get the exponent X lsrl d6,d2 | and shift right X andl #0xFF,d2 X subl #126,d2 | offset the exponent X movel d1,d3 | get the exponent for b X lsrl d6,d3 | and shift right X andl #0xFF,d2 X subl #126,d3 | off set this one too X X clrl d7 | negative result flag X andl #0x7FFFFF,d0 | mask a for mantissa X orl #0x800000,d0 | and put in hidden bit X tstl a6@(8) | test the original value X bpl mulsf3_1 | pos, ok X eorl #1,d7 | remember negative Xmulsf3_1: X andl #0x7FFFFF,d1 | mask b for mantissa X orl #0x800000,d1 | ditto X tstl a6@(12) | test ... X bpl mulsf3_2 X eorl #1,d7 Xmulsf3_2: X| lsrl #8,d1 | shift this one down X| lsrl #8,d0 | this one too... X| mulu d1,d0 | do the multiply X X| beq mulsf3_ret | zero? ok, just return X| lsrl #8,d0 | shift right again X X| X| we have mantissas as follows: X| X| |...ah...|...al...| |...bh...|...bl...| X| X| product is composed as: X| X| |....al * bl....| X| |....al * bh....| X| |....ah * bl....| X| |....ah * bh....| X| X| then take the 24 bit chunk that's 16 bits in. X X movel d0,d4 X andl #0xFFFF,d4 | al X movel d1,d5 X andl #0xFFFF,d5 | bl X mulu d5,d4 | that's al * bl X movel d4,a6@(-4) | into the accum X clrl a6@(-8) | zap the top part X X movel d0,d4 X andl #0xFFFF,d4 | al X movel d1,d5 X movel #16,d6 | shift count X lsrl d6,d5 | bh X mulu d5,d4 | al * bh X addl d4,a6@(-6) X X movel d0,d4 X lsrl d6,d4 | ah X movel d1,d5 X andl #0xFFFF,d5 | bl X mulu d5,d4 | ah * bl X addl d4,a6@(-6) X X movel d0,d4 X lsrl d6,d4 | ah X movel d1,d5 X lsrl d6,d5 | bh X mulu d5,d4 | ah * bh X addl d4,a6@(-8) X X movel a6@(-6),d0 | get the relevant part X lsrl #8,d0 | and shift it down X Xmulsf3_norm: X btst #23,d0 | normalized? X bne mulsf3_ok X lsll #1,d0 X subql #1,d2 X bra mulsf3_norm X Xmulsf3_ok: X andl #0x7FFFFF,d0 | zap hidden bit X addl d3,d2 | add Eb to Ea X addl #126,d2 | fix offset X andl #0xFF,d2 | whack to 8 bits X movel #23,d6 | shift count X lsll d6,d2 | shift up to right place X orl d2,d0 | shove it in X tstl d7 | sign neg? X beq mulsf3_ret X orl #0x80000000,d0 | set sign bit X bra mulsf3_ret Xmulsf3_z: X clrl d0 Xmulsf3_ret: X moveml sp@+,#0x00FC | snarf back all regs X unlk a6 X rts | sigh X# X# #ifdef L_divsf3 X# int X# _divsf3 (a, b) X# union flt_or_int a, b; X# { X# union flt_or_int intify; X# return INTIFY (a.f / b.f); X# } X# #endif X X.text X .even X.globl __divsf3 X__divsf3: X| X| divide. sort of like mult, exc we do shifts and subtracts to X| do the division of the mantissa. resultant exponent is Ea - Eb. X| X X link a6,#0 | don't need any locals X moveml #0x3F00,sp@- | save all data registers X movel a6@(8),d0 | get a X movel a6@(12),d1 | get b X movel #23,d6 | shift count X movel d0,d2 | get the exponent X lsrl d6,d2 | and shift right X andl #0xFF,d2 X subl #127,d2 | offset the exponent X movel d1,d3 | get the exponent for b X lsrl d6,d3 | and shift right X andl #0xFF,d3 X subl #127,d3 | off set this one too X X clrl d7 | negative result flag X andl #0x7FFFFF,d0 | mask a for mantissa X orl #0x800000,d0 | and put in hidden bit X tstl a6@(8) | test the original value X bpl divsf3_1 | pos, ok X eorl #1,d7 | remember negative Xdivsf3_1: X andl #0x7FFFFF,d1 | mask b for mantissa X orl #0x800000,d1 | ditto X tstl a6@(12) | test ... X bpl divsf3_2 X eorl #1,d7 Xdivsf3_2: X| X| for now, kludge. shift Ma left and Mb right, then do an unsigned divide X| and shift the result left. Blech X| X X| lsrl #8,d1 | shift this one down X| lsll #7,d0 | this one up X| divu d1,d0 | do the divide X| andl #0xFFFF,d0 | and mask off cruft X X| beq divsf3_ret | zero? ok, just return X| lsll #8,d0 | shift left again X X| same sort of trick as long divide, exc it's easier here, cause X| the numbers (mantissas) are already bit-aligned. X X clrl d4 | accumulator X movel #0x800000,d5 | bit X lsll #7,d0 | buy a little extra accuracy... X lsll #7,d1 Xdivsf3_2a: X cmpl d1,d0 | compare dividend to divisor X bmi divsf3_2b | nope, no bit here X orl d5,d4 | put in the bit X subl d1,d0 | and subtract Xdivsf3_2b: X lsrl #1,d1 | slide divisor down X lsrl #1,d5 | slide bit down X bne divsf3_2a | and go round again X movel d4,d0 | leave the result here X Xdivsf3_3: X btst #23,d0 | right place yet? X bne divsf3_4 X lsll #1,d0 X subql #1,d2 X bra divsf3_3 Xdivsf3_4: X andl #0x7FFFFF,d0 | zap hidden bit X subl d3,d2 | sub Eb from Ea X addl #127,d2 | fix offset X andl #0xFF,d2 | whack to 8 bits X lsll d6,d2 | shift up to right place X orl d2,d0 | shove it in X tstl d7 | sign neg? X beq divsf3_ret X orl #0x80000000,d0 | set sign bit Xdivsf3_ret: X moveml sp@+,#0x00FC | snarf back all regs X unlk a6 X X rts | sigh X## X## #ifdef L_truncdfsf2 X## int X## _truncdfsf2 (a) X## double a; X## { X## union flt_or_int intify; X## return INTIFY (a); X## } X## #endif X# X#.text X# .even X#.globl __truncdfsf2 X#__truncdfsf2: X# movel sp@(4),d0 X# rts X# X## X## #ifdef L_extendsfdf2 X## double X## _extendsfdf2 (a) X## union flt_or_int a; X## { X## union flt_or_int intify; X## return a.f; X## } X## #endif X# X#.text X# .even X#.globl __extendsfdf2 X#__extendsfdf2: X# movel sp@(4),d0 X# clrl d1 X# rts | sigh X# .even X#.text X SHAR_EOF if test 15211 -ne "`wc -c 'sflonum.s'`" then echo shar: error transmitting "'sflonum.s'" '(should have been 15211 characters)' fi # End of shell archive exit 0 usenet: {decvax,sun}!cwjcc!dsrgsun!bammi jwahar r. bammi csnet: bammi@dsrgsun.ces.CWRU.edu arpa: bammi@dsrgsun.ces.CWRU.edu compuServe: 71515,155