diff --git a/js/src/jsdtoa.c b/js/src/jsdtoa.c index 81d7bfa928c..09b19cf3e80 100644 --- a/js/src/jsdtoa.c +++ b/js/src/jsdtoa.c @@ -41,6 +41,8 @@ #include "jsdtoa.h" #include "jsprf.h" #include "jsutil.h" /* Added by JSIFY */ +#include "jspubtd.h" +#include "jsnum.h" #ifdef JS_THREADSAFE #include "prlock.h" @@ -236,30 +238,12 @@ static double private_mem[PRIVATE_mem], *pmem_next = private_mem; Exactly one of IEEE_8087 or IEEE_MC68k should be defined. #endif -/* Stefan Hanske reports: - * ARM is a little endian architecture but 64 bit double words are stored - * differently: the 32 bit words are in little endian byte order, the two words - * are stored in big endian`s way. - */ -#if defined (IEEE_8087) && !defined(__arm) && !defined(__arm32__) && !defined(__arm26__) -#define word0(x) ((ULong *)&x)[1] -#define word1(x) ((ULong *)&x)[0] -#else -#define word0(x) ((ULong *)&x)[0] -#define word1(x) ((ULong *)&x)[1] -#endif +#define word0(x) JSDOUBLE_HI32(x) +#define set_word0(x, y) JSDOUBLE_SET_HI32(x, y) +#define word1(x) JSDOUBLE_LO32(x) +#define set_word1(x, y) JSDOUBLE_SET_LO32(x, y) -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined(IEEE_8087) -#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ -((unsigned short *)a)[0] = (unsigned short)c, a++) -#else -#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ -((unsigned short *)a)[1] = (unsigned short)c, a++) -#endif +#define Storeinc(a,b,c) (*(a)++ = (b) << 16 | (c) & 0xffff) /* #define P DBL_MANT_DIG */ /* Ten_pmax = floor(P*log(2)/log(5)) */ @@ -878,20 +862,20 @@ static double ulp(double x) #ifndef Sudden_Underflow if (L > 0) { #endif - word0(a) = L; - word1(a) = 0; + set_word0(a, L); + set_word1(a, 0); #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; + set_word0(a, 0x80000 >> L); + set_word1(a, 0); } else { - word0(a) = 0; + set_word0(a, 0); L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << (31 - L); + set_word1(a, L >= 31 ? 1 : 1 << (31 - L)); } } #endif @@ -906,6 +890,8 @@ static double b2d(Bigint *a, int32 *e) double d; #define d0 word0(d) #define d1 word1(d) +#define set_d0(x) set_word0(d, x) +#define set_d1(x) set_word1(d, x) xa0 = a->x; xa = xa0 + a->wds; @@ -916,24 +902,26 @@ static double b2d(Bigint *a, int32 *e) k = hi0bits(y); *e = 32 - k; if (k < Ebits) { - d0 = Exp_1 | y >> (Ebits - k); + set_d0(Exp_1 | y >> (Ebits - k)); w = xa > xa0 ? *--xa : 0; - d1 = y << (32-Ebits + k) | w >> (Ebits - k); + set_d1(y << (32-Ebits + k) | w >> (Ebits - k)); goto ret_d; } z = xa > xa0 ? *--xa : 0; if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> (32 - k); + set_d0(Exp_1 | y << k | z >> (32 - k)); y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> (32 - k); + set_d1(z << k | y >> (32 - k)); } else { - d0 = Exp_1 | y; - d1 = z; + set_d0(Exp_1 | y); + set_d1(z); } ret_d: #undef d0 #undef d1 +#undef set_d0 +#undef set_d1 return d; } @@ -948,12 +936,14 @@ static Bigint *d2b(double d, int32 *e, int32 *bits) ULong *x, y, z; #define d0 word0(d) #define d1 word1(d) +#define set_d0(x) set_word0(d, x) +#define set_d1(x) set_word1(d, x) b = Balloc(1); x = b->x; z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ + set_d0(d0 & 0x7fffffff); /* clear sign bit, which we ignore */ #ifdef Sudden_Underflow de = (int32)(d0 >> Exp_shift); z |= Exp_msk11; @@ -993,6 +983,8 @@ static Bigint *d2b(double d, int32 *e, int32 *bits) } #undef d0 #undef d1 +#undef set_d0 +#undef set_d1 static double ratio(Bigint *a, Bigint *b) @@ -1004,10 +996,10 @@ static double ratio(Bigint *a, Bigint *b) db = b2d(b, &kb); k = ka - kb + 32*(a->wds - b->wds); if (k > 0) - word0(da) += k*Exp_msk1; + set_word0(da, word0(da) + k*Exp_msk1); else { k = -k; - word0(db) += k*Exp_msk1; + set_word0(db, word0(db) + k*Exp_msk1); } return da / db; } @@ -1312,18 +1304,18 @@ dig_done: if (e1 & 1) rv *= bigtens[j]; /* The last multiplication could overflow. */ - word0(rv) -= P*Exp_msk1; + set_word0(rv, word0(rv) - P*Exp_msk1); rv *= bigtens[j]; if ((z = word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; + set_word0(rv, Big0); + set_word1(rv, Big1); } else - word0(rv) += P*Exp_msk1; + set_word0(rv, word0(rv) + P*Exp_msk1); } } else if (e1 < 0) { @@ -1344,13 +1336,13 @@ dig_done: >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(rv) = 0; - word0(rv) &= 0xffffffff << (j-32); + set_word1(rv, 0); + set_word0(rv, word0(rv) & (0xffffffff << (j-32))); if (!word0(rv)) - word0(rv) = 1; + set_word0(rv, 1); } else - word1(rv) &= 0xffffffff << j; + set_word1(rv, word1(rv) & (0xffffffff << j)); } #else for(j = 0; e1 > 1; j++, e1 >>= 1) @@ -1372,8 +1364,8 @@ dig_done: goto ret; } #ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; + set_word0(rv, Tiny0); + set_word1(rv, Tiny1); /* The refinement below will clean * this approximation up. */ @@ -1480,8 +1472,8 @@ dig_done: if ((word0(rv) & Bndry_mask1) == Bndry_mask1 && word1(rv) == 0xffffffff) { /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1; - word1(rv) = 0; + set_word0(rv, (word0(rv) & Exp_mask) + Exp_msk1); + set_word1(rv, 0); #ifdef Avoid_Underflow dsign = 0; #endif @@ -1502,8 +1494,8 @@ dig_done: #else L = (word0(rv) & Exp_mask) - Exp_msk1; #endif - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; + set_word0(rv, L | Bndry_mask1); + set_word1(rv, 0xffffffff); break; } #ifndef ROUND_BIASED @@ -1571,25 +1563,25 @@ dig_done: if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { rv0 = rv; - word0(rv) -= P*Exp_msk1; + set_word0(rv, word0(rv) - P*Exp_msk1); adj = aadj1 * ulp(rv); rv += adj; if ((word0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(rv0) == Big0 && word1(rv0) == Big1) goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; + set_word0(rv, Big0); + set_word1(rv, Big1); goto cont; } else - word0(rv) += P*Exp_msk1; + set_word0(rv, word0(rv) + P*Exp_msk1); } else { #ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { rv0 = rv; - word0(rv) += P*Exp_msk1; + set_word0(rv, word0(rv) + P*Exp_msk1); adj = aadj1 * ulp(rv); rv += adj; if ((word0(rv) & Exp_mask) <= P*Exp_msk1) @@ -1597,12 +1589,12 @@ dig_done: if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; + set_word0(rv, Tiny0); + set_word1(rv, Tiny1); goto cont; } else - word0(rv) -= P*Exp_msk1; + set_word0(rv, word0(rv) - P*Exp_msk1); } else { adj = aadj1 * ulp(rv); @@ -1628,7 +1620,7 @@ dig_done: } #ifdef Avoid_Underflow if (scale && y <= P*Exp_msk1) - word0(aadj1) += (P+1)*Exp_msk1 - y; + set_word0(aadj1, word0(aadj1) + (P+1)*Exp_msk1 - y); #endif adj = aadj1 * ulp(rv); rv += adj; @@ -1658,8 +1650,8 @@ dig_done: } #ifdef Avoid_Underflow if (scale) { - word0(rv0) = Exp_1 - P*Exp_msk1; - word1(rv0) = 0; + set_word0(rv0, Exp_1 - P*Exp_msk1); + set_word1(rv0, 0); if ((word0(rv) & Exp_mask) <= P*Exp_msk1 && word1(rv) & 1 && dsign != 2) { @@ -1667,13 +1659,13 @@ dig_done: #ifdef Sudden_Underflow /* rv will be 0, but this would give the */ /* right result if only rv *= rv0 worked. */ - word0(rv) += P*Exp_msk1; - word0(rv0) = Exp_1 - 2*P*Exp_msk1; + set_word0(rv, word0(rv) + P*Exp_msk1); + set_word0(rv0, Exp_1 - 2*P*Exp_msk1); #endif rv += ulp(rv); } else - word1(rv) &= ~1; + set_word1(rv, word1(rv) & ~1); } rv *= rv0; } @@ -1913,7 +1905,7 @@ JS_dtoa(double d, int mode, JSBool biasUp, int ndigits, if (word0(d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ + set_word0(d, word0(d) & ~Sign_bit); /* clear sign bit */ } else *sign = 0; @@ -1955,8 +1947,8 @@ JS_dtoa(double d, int mode, JSBool biasUp, int ndigits, if ((i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { #endif d2 = d; - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; + set_word0(d2, word0(d2) & Frac_mask1); + set_word0(d2, word0(d2) | Exp_11); /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) @@ -1990,7 +1982,7 @@ JS_dtoa(double d, int mode, JSBool biasUp, int ndigits, i = bbits + be + (Bias + (P-1) - 1); x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) : word1(d) << (32 - i); d2 = x; - word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + set_word0(d2, word0(d2) - 31*Exp_msk1); /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } @@ -2121,7 +2113,7 @@ JS_dtoa(double d, int mode, JSBool biasUp, int ndigits, } /* eps bounds the cumulative error. */ eps = ieps*d + 7.; - word0(eps) -= (P-1)*Exp_msk1; + set_word0(eps, word0(eps) - (P-1)*Exp_msk1); if (ilim == 0) { S = mhi = 0; d -= 5.; diff --git a/js/src/jsnum.h b/js/src/jsnum.h index 9f9a266a99c..0b30379c963 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -48,15 +48,27 @@ JS_BEGIN_EXTERN_C +/* + * Stefan Hanske reports: + * ARM is a little endian architecture but 64 bit double words are stored + * differently: the 32 bit words are in little endian byte order, the two words + * are stored in big endian`s way. + */ + +#if defined(__arm) || defined(__arm32__) || defined(_arm26__) +#define CPU_IS_ARM +#endif + #if __GNUC__ >= 2 -/* This version of the macros is safe for the alias optimizations +/* + * This version of the macros is safe for the alias optimizations * that gcc does, but uses gcc-specific extensions. */ typedef union { jsdouble value; struct { -#ifdef IS_LITTLE_ENDIAN +#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM) uint32 lsw; uint32 msw; #else @@ -72,14 +84,25 @@ typedef union { #define JSDOUBLE_LO32(x) (__extension__ ({ js_ieee_double_shape_type sh_u; \ sh_u.value = (x); \ sh_u.parts.lsw; })) +#define JSDOUBLE_SET_HI32(x, y) (__extension__ ({ \ + js_ieee_double_shape_type sh_u; \ + sh_u.value = (x); \ + sh_u.parts.msw = (y); \ + (x) = sh_u.value; })) +#define JSDOUBLE_SET_LO32(x, y) (__extension__ ({ \ + js_ieee_double_shape_type sh_u; \ + sh_u.value = (x); \ + sh_u.parts.lsw = (y); \ + (x) = sh_u.value; })) #else /* GNUC */ -/* We don't know of any non-gcc compilers that perform alias optimization, +/* + * We don't know of any non-gcc compilers that perform alias optimization, * so this code should work. */ -#ifdef IS_LITTLE_ENDIAN +#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM) #define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) #define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) #else @@ -87,6 +110,9 @@ typedef union { #define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) #endif +#define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y)) +#define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y)) + #endif /* GNUC */ #define JSDOUBLE_HI32_SIGNBIT 0x80000000