diff --git a/em.c b/em.c index e9713de..604bb14 100644 --- a/em.c +++ b/em.c @@ -2938,11 +2938,12 @@ static pcl (ea_t ecbea) { if (access == 1 && (ecbea & 0xF) != 0) fault(ACCESSFAULT, 0, ecbea); if ((pa & 01777) <= 02000 - sizeof(ecb)/sizeof(ecb[0])) { - memcpy(ecb, MEM+pa, sizeof(ecb)); //BS + memcpy(ecb, MEM+pa, sizeof(ecb)); + for (i=0; i<9; i++) + swap16(ecb[i]); } else { - *(long long *)(ecb+0) = get64(ecbea+0); - *(long long *)(ecb+4) = get64(ecbea+4); - ecb[8] = get16(ecbea+8); + for (i=0; i<9; i++) + ecb[i] = get16(ecbea+i); } TRACE(T_PCL, " ecb.pb: %o/%o\n ecb.framesize: %d\n ecb.stackroot %o\n ecb.argdisp: %o\n ecb.nargs: %d\n ecb.lb: %o/%o\n ecb.keys: %o\n", ecb[0], ecb[1], ecb[2], ecb[3], ecb[4], ecb[5], ecb[6], ecb[7], ecb[8]); @@ -7128,15 +7129,26 @@ d_flot: /* 0140550 */ goto fetch; d_frn: /* 0140534 */ - TRACE(T_FLOW, " FRN\n"); - CLEARC; - frn(crsl+FAC1); + { + int oflow; + TRACE(T_FLOW, " FRN\n"); + CLEARC; + putfr64(2, frn(getfr64(2), &oflow)); + if (oflow) + mathexception('f', FC_DFP_OFLOW, 0); + } goto fetch; d_dfcm: /* 0140574 */ - TRACE(T_FLOW, " DFCM\n"); - dfcm(crsl+FAC1); - goto fetch; + { + int oflow; + TRACE(T_FLOW, " DFCM\n"); +dfcmfac1: + putfr64(2, dfcm(getfr64(2), &oflow)); + if (oflow) + mathexception('f', FC_DFP_OFLOW, 0); + goto fetch; + } d_adll: /* 0141000 */ TRACE(T_FLOW, " ADLL\n"); @@ -7145,8 +7157,7 @@ d_adll: /* 0141000 */ d_fcmv: /* 0140530 */ TRACE(T_FLOW, " FCMv\n"); - dfcm(crsl+FAC1); - goto fetch; + goto dfcmfac1; d_fsze: /* 0140510 */ TRACE(T_FLOW, " FSZE\n"); @@ -7187,7 +7198,7 @@ d_fsgt: /* 0140515 */ d_int: /* 0140554 */ TRACE(T_FLOW, " INTr\n"); /* XXX: do -1073741824.5 and 1073741823.5 work on Prime, or overflow? */ - if (prieee8(crs+FLTH, &tempd) && -1073741824.0 <= tempd && tempd <= 1073741823.0) { + if (prieee8(getfr64(2), &tempd) && -1073741824.0 <= tempd && tempd <= 1073741823.0) { templ = tempd; putcrs16(B, templ & 0x7FFF); putcrs16(A, templ >> 15); @@ -7199,7 +7210,7 @@ d_int: /* 0140554 */ d_inta: /* 0140531 */ TRACE(T_FLOW, " INTA\n"); /* XXX: do 32767.5 and -32768.5 work on Prime, or overflow? */ - if (prieee8(crs+FLTH, &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { + if (prieee8(getfr64(2), &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { putcrs16(A, (short)tempd); CLEARC; } else @@ -7214,7 +7225,7 @@ d_flta: /* 0140532 */ d_intl: /* 0140533 */ TRACE(T_FLOW, " INTL\n"); - if (prieee8(crs+FLTH, &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { + if (prieee8(getfr64(2), &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { putcrs32s(L, tempd); CLEARC; } else @@ -7967,8 +7978,14 @@ imode: break; case 0144: - TRACE(T_FLOW, " DFCM\n"); - dfcm(crsl+FAC0+dr); + { + int oflow; + TRACE(T_FLOW, " DFCM\n"); +dfcmdr: + putfr64(dr, dfcm(getfr64(dr), &oflow)); + if (oflow) + mathexception('f', FC_DFP_OFLOW, 0); + } break; case 0130: @@ -7993,7 +8010,7 @@ imode: case 0100: TRACE(T_FLOW, " FCM\n"); - dfcm(crsl+FAC0+dr); + goto dfcmdr; break; case 0105: @@ -8017,9 +8034,14 @@ imode: break; case 0107: - TRACE(T_FLOW, " FRN\n"); - CLEARC; - frn(crsl+FAC0+dr); + { + int oflow; + TRACE(T_FLOW, " FRN\n"); + CLEARC; + putfr64(2, frn(getfr64(dr), &oflow)); + if (oflow) + mathexception('f', FC_DFP_OFLOW, 0); + } break; case 0146: /* I-mode FRNM */ @@ -8079,7 +8101,7 @@ imode: case 0103: TRACE(T_FLOW, " INT 0\n"); - if (prieee8(crsl+FAC0, &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { + if (prieee8(getfr64(0), &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { putgr32s(dr, tempd); CLEARC; } else @@ -8088,7 +8110,7 @@ imode: case 0113: TRACE(T_FLOW, " INT 1\n"); - if (prieee8(crsl+FAC1, &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { + if (prieee8(getfr64(2), &tempd) && -2147483648.0 <= tempd && tempd <= 2147483647.0) { putgr32s(dr, (int)tempd); CLEARC; } else @@ -8097,7 +8119,7 @@ imode: case 0101: TRACE(T_FLOW, " INTH 0\n"); - if (prieee8(crsl+FAC0, &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { + if (prieee8(getfr64(0), &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { putgr16s(dr, (short)tempd); CLEARC; } else @@ -8106,7 +8128,7 @@ imode: case 0111: TRACE(T_FLOW, " INTH 1\n"); - if (prieee8(crsl+FAC1, &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { + if (prieee8(getfr64(2), &tempd) && -32768.0 <= tempd && tempd <= 32767.0) { putgr16s(dr, (short)tempd); CLEARC; } else @@ -8631,7 +8653,7 @@ imode: utempl = ((immu64 >> 32) & 0xffffff00) | (immu64 & 0xff); else utempl = get32(ea); - fcs(crsl+FAC0+dr, utempl); + fcs(getfr64(dr), utempl); break; case 5: @@ -8640,7 +8662,7 @@ imode: TRACE(T_FLOW, " DFC\n"); if (*(int *)&ea >= 0) immu64 = get64(ea); - dfcs(crsl+FAC0+dr, immu64); + dfcs(getfr64(dr), immu64); break; default: @@ -8718,6 +8740,7 @@ imode: case 016: /* Special MR FP format */ /* FST, DFST, FA, DFA */ switch (dr) { + int oflow; case 0: case 2: dr &= 2; @@ -8725,7 +8748,7 @@ imode: CLEARC; if (*(int *)&ea >= 0) { if (getcrs16(KEYS) & 010) - frn(crsl+FAC0+dr); + putfr64(2, frn(getfr64(2), &oflow)); /* sing prec can't overflow */ if ((getgr32(FAC0+dr+1) & 0xFF00) == 0) put32((getfr32(dr) & 0xFFFFFF00) | (getgr32(FAC0+dr+1) & 0xFF), ea); else @@ -8761,8 +8784,8 @@ imode: tempa1 = getgr32(FAC0+dr+1) & 0xffff; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC0+dr, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(dr), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else @@ -8783,8 +8806,8 @@ imode: immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC0+dr)) - if (prieee8(crsl+FAC0+dr, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(dr), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else @@ -8875,19 +8898,19 @@ imode: tempa1 = getgr32(FAC0+dr+1) & 0xffff; tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC0+dr, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(dr), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else mathexception('f', FC_SFP_OFLOW, ea); else if (tempa1 < tempa2) { putgr64s(FAC0+dr, immu64); - dfcm(crsl+FAC0+dr); + goto dfcmdr; } } else { putgr64s(FAC0+dr, immu64); - dfcm(crsl+FAC0+dr); + goto dfcmdr; } else if (getgr32s(FAC0+dr) == 0) putgr64s(FAC0+dr, 0); @@ -8901,15 +8924,15 @@ imode: immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC0+dr)) - if (prieee8(crsl+FAC0+dr, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(dr), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else mathexception('f', FC_DFP_OFLOW, ea); else { putgr64s(FAC0+dr, immu64); - dfcm(crsl+FAC0+dr); + goto dfcmdr; } else if (getgr32s(FAC0+dr) == 0) putgr64s(FAC0+dr, 0); @@ -8925,8 +8948,8 @@ imode: immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); } if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC0+dr, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(dr), &tempd1) && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else @@ -8945,8 +8968,8 @@ imode: if (*(int *)&ea >= 0) immu64 = get64(ea); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC0+dr, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(dr), &tempd1) && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC0+dr), 0)) CLEARC; else @@ -9023,8 +9046,8 @@ imode: } if (*(int *)&immu64) if (getgr32s(FAC0+dr)) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC0+dr, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(dr), &tempd1) && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC0+dr), 1)) CLEARC; else @@ -9043,8 +9066,8 @@ imode: immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC0+dr)) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC0+dr, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(dr), &tempd1) && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC0+dr), 1)) CLEARC; else @@ -9973,8 +9996,8 @@ d_fad: /* 00601 */ tempa1 = getcrs16(FEXP); tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC1, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(2), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC1), 0)) CLEARC; else @@ -9992,7 +10015,7 @@ d_fad: /* 00601 */ d_fcs: /* 01101 */ TRACE(T_FLOW, " FCS\n"); templ = get32(ea); - RPL += fcs(crsl+FAC1, templ); + RPL += fcs(getfr64(2), templ); goto fetch; d_fdv: /* 01701 */ @@ -10001,8 +10024,8 @@ d_fdv: /* 01701 */ immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) if (getgr32s(FAC1)) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC1, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(2), &tempd1) && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC1), 1)) CLEARC; else @@ -10026,8 +10049,8 @@ d_fmp: /* 01601 */ immu64 = get32(ea); immu64 = ((immu64 << 32) & 0xffffff0000000000LL) | (immu64 & 0xff); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC1, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(2), &tempd1) && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC1), 0)) CLEARC; else @@ -10047,33 +10070,38 @@ d_fsb: /* 00701 */ tempa1 = getcrs16(FEXP); tempa2 = immu64 & 0xffff; if (abs(tempa1-tempa2) < 48) - if (prieee8(crsl+FAC1, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(2), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC1), 0)) CLEARC; else mathexception('f', FC_SFP_OFLOW, ea); else if (tempa1 < tempa2) { putgr64s(FAC1, immu64); - dfcm(crsl+FAC1); + goto dfcmfac1; } } else { putgr64s(FAC1, immu64); - dfcm(crsl+FAC1); + goto dfcmfac1; } else if (getgr32s(FAC1) == 0) putgr64s(FAC1, 0); goto fetch; d_fst: /* 0401 */ - TRACE(T_FLOW, " FST\n"); - CLEARC; - if (getcrs16(KEYS) & 010) - frn(crsl+FAC1); - if ((getgr32(FAC1+1) & 0xFF00) == 0) - put32((getgr32(FAC1) & 0xFFFFFF00) | (getgr32(FAC1+1) & 0xFF), ea); - else - mathexception('f', FC_SFP_STORE, ea); + { + int oflow; + unsigned long long dfp; + TRACE(T_FLOW, " FST\n"); + CLEARC; + if (getcrs16(KEYS) & 010) + putfr64(2, frn(getfr64(2), &oflow)); /* sing prec can't overflow */ + dfp = getfr64(2); + if ((dfp & 0xFF00) == 0) + put32(((dfp & 0xFFFFFF0000000000LL) >> 32) | (dfp & 0xFF), ea); + else + mathexception('f', FC_SFP_STORE, ea); + } goto fetch; d_dfad: /* 0602 */ @@ -10081,8 +10109,8 @@ d_dfad: /* 0602 */ immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC1)) - if (prieee8(crsl+FAC1, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(2), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1+tempd2, (long long *)(crsl+FAC1), 0)) { CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) + %f (%o %o %o %o)\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP), tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); @@ -10098,7 +10126,7 @@ d_dfad: /* 0602 */ d_dfcs: /* 01102 */ TRACE(T_FLOW, " DFCS\n"); templl = get64(ea); - RPL += dfcs(crsl+FAC1, templl); + RPL += dfcs(getfr64(2), templl); goto fetch; d_dfdv: /* 01702 */ @@ -10107,8 +10135,8 @@ d_dfdv: /* 01702 */ immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC1)) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC1, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(2), &tempd1) && ieeepr8(tempd1/tempd2, (long long *)(crsl+FAC1), 1)) { CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) / %f (%o %o %o %o)\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP), tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); @@ -10125,7 +10153,7 @@ d_dfld: /* 0202 */ TRACE(T_FLOW, " DFLD\n"); putcrs64s(FLTH, get64(ea)); #ifndef NOTRACE - if (!prieee8(crs+FLTH, &tempd1)) + if (!prieee8(getfr64(2), &tempd1)) tempd1 = -0.0; #endif TRACE(T_FLOW, " Loaded %f '%o %o %o %o\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP)); @@ -10136,8 +10164,8 @@ d_dfmp: /* 01602 */ if (getgr32s(FAC1)) { immu64 = get64(ea); if (*(int *)&immu64) - if (prieee8(&immu64, &tempd2) - && prieee8(crsl+FAC1, &tempd1) + if (prieee8(immu64, &tempd2) + && prieee8(getfr64(2), &tempd1) && ieeepr8(tempd1*tempd2, (long long *)(crsl+FAC1), 0)) { CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) * %f (%o %o %o %o)\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP), tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); @@ -10155,8 +10183,8 @@ d_dfsb: /* 0702 */ immu64 = get64(ea); if (*(int *)&immu64) if (getgr32s(FAC1)) - if (prieee8(crsl+FAC1, &tempd1) - && prieee8(&immu64, &tempd2) + if (prieee8(getfr64(2), &tempd1) + && prieee8(immu64, &tempd2) && ieeepr8(tempd1-tempd2, (long long *)(crsl+FAC1), 0)) { CLEARC; TRACE(T_FLOW, " %f ('%o %o %o %o) - %f (%o %o %o %o)\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP), tempd2, (unsigned short)(immu64>>48), (unsigned short)((immu64>>32)&0xffff), (unsigned short)((immu64>>16)&0xffff), (unsigned short)(immu64&0xffff)); @@ -10165,7 +10193,7 @@ d_dfsb: /* 0702 */ mathexception('f', FC_DFP_OFLOW, ea); else { putgr64s(FAC1, immu64); - dfcm(crsl+FAC1); + goto dfcmfac1; } else if (getgr32s(FAC1) == 0) putgr64s(FAC1, 0); @@ -10175,10 +10203,10 @@ d_dfst: /* 0402 */ TRACE(T_FLOW, " DFST\n"); put64(getcrs64s(FLTH), ea); #ifndef NOTRACE - if (!prieee8(crs+FLTH, &tempd1)) + if (!prieee8(getfr64(2), &tempd1)) tempd1 = -0.0; -#endif TRACE(T_FLOW, " Stored %f '%o %o %o %o\n", tempd1, getcrs16(FLTH), getcrs16(FLTL), getcrs16(FLTD), getcrs16(FEXP)); +#endif goto fetch; d_ealb: /* 01302 */ diff --git a/fp.h b/fp.h index 7546b02..973e2b8 100644 --- a/fp.h +++ b/fp.h @@ -40,17 +40,13 @@ http://tima-cmp.imag.fr/~guyot/Cours/Oparithm/english/Op_Ar2.htm /* getdp unpacks a Prime DPFP into 48-bit sign + mantissa (left justified in 64 bits) and a 32-bit signed exponent */ -inline getdp (void *p, long long *frac64, int *exp32) { +inline getdp (unsigned long long p, long long *frac64, int *exp32) { - *frac64 = *(long long *)p & 0xFFFFFFFFFFFF0000LL; /* unpack fraction */ - *exp32 = *((short *)p+3); /* unpack SIGNED exponent */ -} - -inline putdp (void *p, long long frac64, int exp32) { - - *(long long *)p = (frac64 & 0xFFFFFFFFFFFF0000LL) | (exp32 & 0xFFFF); + *frac64 = p & 0xFFFFFFFFFFFF0000LL; /* unpack fraction */ + *exp32 = (short) (p & 0xFFFFLL); /* unpack SIGNED exponent */ } +#define RETFP(frac64, exp32) return ((frac64) & 0xFFFFFFFFFFFF0000LL) | ((exp32) & 0xFFFF) /* Conversion from Prime DPFP to IEEE DPFP Returns true if conversion succeeded, false if it failed. @@ -58,20 +54,7 @@ inline putdp (void *p, long long frac64, int exp32) { IEEE DPFP exponents are only 11 bits. */ -/* Floating point conversion caches. - 1st entry is a Prime-format DPFP number. - 2nd entry is the corresponding IEEE DPFP number. - Unused entries are 0.0 - - There are two corresponding hash arrays, one for Prime entries - and a 2nd for IEEE entries. Whenever a conversion is done, both - types of entries are updated. */ - -static double fpcache[2][512]; -static short primecix[512]; -static short ieeecix[512]; - -int prieee8(void *dp, double *d) { +int prieee8(unsigned long long dp, double *d) { long long frac64, sign; int exp32; @@ -107,7 +90,7 @@ int prieee8(void *dp, double *d) { /* normalize positive fraction until bit 2 is 1 */ - while ((*(int *)&frac64 & 0x40000000) == 0) { + while ((frac64 & 0x4000000000000000LL) == 0) { frac64 = frac64 << 1; exp32--; } @@ -226,7 +209,7 @@ retry: /* XXX: should this be a subtract for negative numbers? */ frac64 += 0x10000; - *p = (frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff); + *p = swap64((frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff)); return okay; } @@ -272,12 +255,12 @@ double fltl (int int32) { /* Prime DPFP complement */ -dfcm (void *dp) { +unsigned long long dfcm (unsigned long long dp, int *oflow) { long long frac64; - int exp32, oflow; + int exp32; CLEARC; - oflow = 0; + *oflow = 0; getdp(dp, &frac64, &exp32); if (frac64 != 0) { /* can't normalize zero */ if (frac64 == 0x8000000000000000LL) { /* overflow case? */ @@ -290,37 +273,34 @@ dfcm (void *dp) { exp32--; } } - putdp(dp, frac64, exp32); - oflow = exp32 > 32767 || exp32 < -32768; + if (exp32 > 32767 || exp32 < -32768) + *oflow = 1; + RETFP(frac64, exp32); } else - *(double *)dp = 0.0;; /* DFCM is documented to clean up dirty zeroes */ - if (oflow) - mathexception('f', FC_DFP_OFLOW, 0); + RETFP(0, 0); /* DFCM is documented to clean up dirty zeroes */ } /* double precision floating point normalize - Passed a pointer to a Prime double precision variable and updates - it in place. May set the C-bit or cause a floating point - exception. */ + Passed a Prime double precision variable and returns normalized + value and overflow flag. */ -void norm(void *dp) { +unsigned long long norm(unsigned long long dp, int *oflow) { long long frac64; int exp32; + *oflow = 0; getdp(dp, &frac64, &exp32); while ((frac64 ^ (frac64 << 1)) >= 0) { frac64 = frac64 << 1; exp32--; } - - putdp(dp, frac64, exp32); if (exp32 > 32767 || exp32 < -32768) - mathexception('f', FC_DFP_OFLOW, 0); + *oflow = 1; + RETFP(frac64, exp32); } - /* double->single floating point round (FRN) instruction. Passed a pointer to a Prime double precision variable, one of the @@ -329,14 +309,15 @@ void norm(void *dp) { NOTE: this routine is coded strangely because I ran into compiler bugs (gcc 4.0.1) */ -void frn(void *dp) { +unsigned long long frn(unsigned long long dp, int *oflow) { long long frac64; int exp32; int doround1, doround2; + *oflow = 0; getdp(dp, &frac64, &exp32); if (frac64 == 0) - *(long long *)dp = 0; + return 0; else { doround1 = ((frac64 & 0x18000000000LL) != 0); doround2 = ((frac64 & 0x8000000000LL) != 0) && ((frac64 & 0x7FFFFF0000LL) != 0); @@ -349,8 +330,8 @@ void frn(void *dp) { exp32++; } frac64 |= (exp32 & 0xFFFF); - norm(&frac64); - *(long long *)dp = frac64; + frac64 = norm(frac64, oflow); + return frac64; } } } @@ -362,16 +343,16 @@ void frn(void *dp) { RPL should be advanced. */ -int fcs (unsigned int *fac, int fop) { +int fcs (unsigned long long fac, int fop) { int templ; short fopexp, facexp; CLEARCC; - templ = fac[0] & 0xffffff00; /* FAC SP mantissa */ + templ = (fac & 0xffffff0000000000LL) >> 32; /* FAC SP mantissa */ if (templ == 0) /* fix dirty zero */ facexp = 0; else - facexp = fac[1] & 0xffff; /* FAC exponent */ + facexp = fac & 0xffff; /* FAC exponent */ fopexp = fop & 0xff; fop = fop & 0xffffff00; if (fop == 0) /* fix dirty zero */ @@ -410,12 +391,12 @@ int fcs (unsigned int *fac, int fop) { Prime ASCII characters in the DAC) won't convert to IEEE. */ -int dfcs (unsigned int *fac, long long fop) { +int dfcs (unsigned long long fac, long long fop) { long long templl; short fopexp, facexp; CLEARCC; - templl = *(long long *)fac; + templl = fac; facexp = templl & 0xffff; /* FAC exponent */ templl = templl & 0xffffffffffff0000LL; /* FAC SP mantissa */ if (templl == 0) /* fix dirty zero */ @@ -448,30 +429,3 @@ int dfcs (unsigned int *fac, long long fop) { } else return 0; /* FAC > operand */ } - - -#if 0 - -/* Prime DPFP multiply */ - -dfmp(void *dp1, void *dp2, ea_t ea) { - long long frac64, frac641, frac642; - int exp32, exp321, exp322; - short fcode; - - fcode = 0; - CLEARC; - getdp(dp1, &frac641, &exp321); - getdp(dp2, &frac642, &exp322); - exp32 = exp321 + exp322; - /* XXX: need to get 128-bit result to test for overflow? */ - frac64 = frac641 * frac642; - if (exp32 > 32767 || exp32 < -32768) - fcode = FC_DFP_OFLOW; - /* insert (optional) rounding code here */ - if (fcode == 0) - putdp(dp1, frac64, exp32); - else - mathexception('f', fcode, ea); -} -#endif diff --git a/regs.h b/regs.h index eb01dde..acfe331 100644 --- a/regs.h +++ b/regs.h @@ -373,6 +373,19 @@ static inline int64_t putgr64s(int offset, int64_t val) { \ pointer to FR0, then use offset as an index */ #define getfr32(offset) getgr32(FAC0+offset) +/* fetch 64-bit unsigned at FP register 0 or 1 + For FP 0, offset=0; for FP 1, offset=2 */ +static inline uint64_t getfr64(int offset) { \ + return (uint64_t) swap64(*(unsigned long long *)(crsl+FAC0+offset)); +} + +/* put 64-bit double in FP reg 0 or 1 + For FP 0, offset=0; for FP 1, offset=2 */ +//#define putfr64(offset, val) +static inline double putfr64(int offset, unsigned long long val) { \ + *(unsigned long long *)(crsl+FAC0+offset) = swap64((val)); +} + /* put 64-bit double in FP reg 0 or 1 For FP 0, offset=0; for FP 1, offset=2 */ //#define putfr64d(offset, val) *(double *)(crsl+FAC0+offset) = (val)