// Normalize and optionally round floating point operand private static void fnorm(ref UFP a, ulong rnd) { a = new UFP(); var normmask = new ulong[] { 0x6000000000000000, 0x7800000000000000, 0x7F80000000000000, 0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF }; var normtab = new[] { 1, 2, 4, 8, 16, 32, 63 }; if ((a.Fhi & FpUcry).NZ()) { // carry set? //printf("%%PDP-10 FP: carry bit set at normalization, PC = %o\n", pager_PC); a.Flo = (a.Flo >> 1) | ((a.Fhi & 1) << 63); // try to recover a.Fhi = a.Fhi >> 1; // but root cause a.Exp = a.Exp + 1; // should be fixed! } if ((a.Fhi | a.Flo) == 0) { // if fraction = 0 a.Sign = a.Exp = 0; // result is 0 return; } while ((a.Fhi & FpUnorm) == 0) { // normalized? int i; for (i = 0; i < 6; i++) { if ((a.Fhi & normmask[i]).NZ()) { break; } } a.Fhi = (a.Fhi << normtab[i]) | (a.Flo >> (64 - normtab[i])); a.Flo = a.Flo << normtab[i]; a.Exp = a.Exp - normtab[i]; } if (rnd.NZ()) { // rounding? a.Fhi = a.Fhi + rnd; // add round const if ((a.Fhi & FpUcry).NZ()) { // if carry out, a.Fhi = a.Fhi >> 1; // renormalize a.Exp = a.Exp + 1; } } return; }
// Pack floating point result private ulong fpack(UFP r, out ulong lo, bool setlo, bool fdvneg) { var val = new ulong[2]; if (r.Exp < 0) { setf(_fAov | _fFov | _fFxu | _fT1); } else if ((ulong)r.Exp > _fpMExp) { setf(_fAov | _fFov | _fT1); } val[0] = (((((ulong)r.Exp) & _fpMExp) << FpVExp) | ((r.Fhi & FpUfhi) >> FpVUfhi)) & B36.DMASK; if (setlo) { val[1] = ((r.Fhi & FpUflo) >> FpVUflo) & B36.MMASK; } else { val[1] = 0; } if (r.Sign.NZ()) // negate? { if (fdvneg) { // fdvr special? val[1] = ~val[1] & B36.MMASK; // 1's comp val[0] = ~val[0] & B36.DMASK; } else { dmovn(val); } } lo = 0; if (setlo) { lo = val[1]; } return(val[0]); }
// Unpack floating point operand private static void funpack(ulong h, ulong l, out UFP r, bool sgn) { r = new UFP { Sign = getFpsign(h), Exp = getFpexp(h) }; var fphi = getFphi(h); var fplo = getFplo(l); r.Fhi = (fphi << FpVUfhi) | (fplo << FpVUflo); r.Flo = 0; if (r.Sign.NZ()) { r.Exp = r.Exp ^ (int)_fpMExp; // 1s comp exp if (sgn) // signed frac? { if (r.Fhi.NZ()) { r.Fhi = r.Fhi | FpUcry; // extend sign } else { r.Exp = r.Exp + 1; r.Fhi = FpUcry | FpUnorm; } } else // abs frac if (r.Fhi.NZ()) { r.Fhi = uneg(r.Fhi) & FpUfrac; } else { r.Exp = r.Exp + 1; r.Fhi = FpUnorm; } } return; }
private static void duneg(ref UFP x) { //#define DUNEG(x) x.flo = UNEG (x.flo); x.fhi = ~x.fhi + (x.flo == 0) x.Flo = uneg(x.Flo); x.Fhi = ~x.Fhi + (x.Flo == 0).B(); }