int FPU_to_exp16(FPU_REG const *a, FPU_REG *x) { int sign = getsign(a); *(long long *)&(x->sigl) = *(const long long *)&(a->sigl); /* Set up the exponent as a 16 bit quantity. */ setexponent16(x, exponent(a)); if (exponent16(x) == EXP_UNDER) { /* The number is a de-normal or pseudodenormal. */ /* We only deal with the significand and exponent. */ if (x->sigh & 0x80000000) { /* Is a pseudodenormal. */ /* This is non-80486 behaviour because the number loses its 'denormal' identity. */ addexponent(x, 1); } else { /* Is a denormal. */ addexponent(x, 1); FPU_normalize_nuo(x); } } if (!(x->sigh & 0x80000000)) { EXCEPTION(EX_INTERNAL | 0x180); } return sign; }
int FPU_to_exp16(FPU_REG const *a, FPU_REG *x) { int sign = getsign(a); *(long long *)&(x->sigl) = *(const long long *)&(a->sigl); setexponent16(x, exponent(a)); if (exponent16(x) == EXP_UNDER) { if (x->sigh & 0x80000000) { addexponent(x, 1); } else { addexponent(x, 1); FPU_normalize_nuo(x); } } if (!(x->sigh & 0x80000000)) { EXCEPTION(EX_INTERNAL | 0x180); } return sign; }
static int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, FPU_REG const *b, u_char tagb, u_char signb, FPU_REG * dest, int deststnr, int control_w) { if (((taga == TW_Denormal) || (tagb == TW_Denormal)) && (denormal_operand() < 0)) return FPU_Exception; if (taga == TAG_Zero) { if (tagb == TAG_Zero) { u_char different_signs = signa ^ signb; FPU_copy_to_regi(a, TAG_Zero, deststnr); if (different_signs) { setsign(dest, ((control_w & CW_RC) != RC_DOWN) ? SIGN_POS : SIGN_NEG); } else setsign(dest, signa); return TAG_Zero; } else { reg_copy(b, dest); if ((tagb == TW_Denormal) && (b->sigh & 0x80000000)) { addexponent(dest, 1); tagb = TAG_Valid; } else if (tagb > TAG_Empty) tagb = TAG_Special; setsign(dest, signb); FPU_settagi(deststnr, tagb); return tagb; } } else if (tagb == TAG_Zero) { reg_copy(a, dest); if ((taga == TW_Denormal) && (a->sigh & 0x80000000)) { addexponent(dest, 1); taga = TAG_Valid; } else if (taga > TAG_Empty) taga = TAG_Special; setsign(dest, signa); FPU_settagi(deststnr, taga); return taga; } else if (taga == TW_Infinity) { if ((tagb != TW_Infinity) || (signa == signb)) { FPU_copy_to_regi(a, TAG_Special, deststnr); setsign(dest, signa); return taga; } return arith_invalid(deststnr); } else if (tagb == TW_Infinity) { FPU_copy_to_regi(b, TAG_Special, deststnr); setsign(dest, signb); return tagb; } #ifdef PARANOID EXCEPTION(EX_INTERNAL | 0x101); #endif return FPU_Exception; }
static int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, FPU_REG const *b, u_char tagb, u_char signb, FPU_REG *dest, int deststnr, int control_w) { if ( ((taga == TW_Denormal) || (tagb == TW_Denormal)) && (denormal_operand() < 0) ) return FPU_Exception; if (taga == TAG_Zero) { if (tagb == TAG_Zero) { /* Both are zero, result will be zero. */ u_char different_signs = signa ^ signb; FPU_copy_to_regi(a, TAG_Zero, deststnr); if ( different_signs ) { /* Signs are different. */ /* Sign of answer depends upon rounding mode. */ setsign(dest, ((control_w & CW_RC) != RC_DOWN) ? SIGN_POS : SIGN_NEG); } else setsign(dest, signa); /* signa may differ from the sign of a. */ return TAG_Zero; } else { reg_copy(b, dest); if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) ) { /* A pseudoDenormal, convert it. */ addexponent(dest, 1); tagb = TAG_Valid; } else if ( tagb > TAG_Empty ) tagb = TAG_Special; setsign(dest, signb); /* signb may differ from the sign of b. */ FPU_settagi(deststnr, tagb); return tagb; } } else if (tagb == TAG_Zero) { reg_copy(a, dest); if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) ) { /* A pseudoDenormal */ addexponent(dest, 1); taga = TAG_Valid; } else if ( taga > TAG_Empty ) taga = TAG_Special; setsign(dest, signa); /* signa may differ from the sign of a. */ FPU_settagi(deststnr, taga); return taga; } else if (taga == TW_Infinity) { if ( (tagb != TW_Infinity) || (signa == signb) ) { FPU_copy_to_regi(a, TAG_Special, deststnr); setsign(dest, signa); /* signa may differ from the sign of a. */ return taga; } /* Infinity-Infinity is undefined. */ return arith_invalid(deststnr); } else if (tagb == TW_Infinity) { FPU_copy_to_regi(b, TAG_Special, deststnr); setsign(dest, signb); /* signb may differ from the sign of b. */ return tagb; } #ifdef PARANOID EXCEPTION(EX_INTERNAL|0x101); #endif return FPU_Exception; }