|
|
1.1 ! root 1: /*---------------------------------------------------------------------------+ ! 2: | reg_mul.c | ! 3: | | ! 4: | Multiply one FPU_REG by another, put the result in a destination FPU_REG. | ! 5: | | ! 6: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | ! 7: | Australia. E-mail [email protected] | ! 8: | | ! 9: | | ! 10: +---------------------------------------------------------------------------*/ ! 11: ! 12: /*---------------------------------------------------------------------------+ ! 13: | The destination may be any FPU_REG, including one of the source FPU_REGs. | ! 14: +---------------------------------------------------------------------------*/ ! 15: ! 16: #include "fpu_system.h" ! 17: #include "exception.h" ! 18: #include "reg_constant.h" ! 19: #include "fpu_emu.h" ! 20: ! 21: ! 22: /* This routine must be called with non-empty registers */ ! 23: void reg_mul(FPU_REG *a, FPU_REG *b, FPU_REG *dest) ! 24: { ! 25: if (!(a->tag | b->tag)) ! 26: { ! 27: /* This should be the most common case */ ! 28: reg_u_mul(a, b, dest); ! 29: dest->exp += - EXP_BIAS + 1; ! 30: dest->sign = (a->sign ^ b->sign); ! 31: dest->tag = TW_Valid; ! 32: if ( dest->exp <= EXP_UNDER ) ! 33: { arith_underflow(FPU_st0_ptr); } ! 34: else if ( dest->exp >= EXP_OVER ) ! 35: { arith_overflow(FPU_st0_ptr); } ! 36: return; ! 37: } ! 38: else if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero)) ! 39: { ! 40: /* Must have either both arguments == zero, or ! 41: one valid and the other zero. ! 42: The result is therefore zero. */ ! 43: reg_move(&CONST_Z, dest); ! 44: } ! 45: else if ((a->tag <= TW_Denormal) && (b->tag <= TW_Denormal)) ! 46: { ! 47: /* One or both arguments are de-normalized */ ! 48: /* Internal de-normalized numbers are not supported yet */ ! 49: EXCEPTION(EX_INTERNAL|0x105); ! 50: reg_move(&CONST_Z, dest); ! 51: } ! 52: else ! 53: { ! 54: /* Must have infinities, NaNs, etc */ ! 55: if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) ) ! 56: { real_2op_NaN(a, b, dest); return; } ! 57: else if (a->tag == TW_Infinity) ! 58: { ! 59: if (b->tag == TW_Zero) ! 60: { arith_invalid(dest); return; } ! 61: else ! 62: { ! 63: reg_move(a, dest); ! 64: dest->sign = a->sign == b->sign ? SIGN_POS : SIGN_NEG; ! 65: } ! 66: } ! 67: else if (b->tag == TW_Infinity) ! 68: { ! 69: if (a->tag == TW_Zero) ! 70: { arith_invalid(dest); return; } ! 71: else ! 72: { ! 73: reg_move(b, dest); ! 74: dest->sign = a->sign == b->sign ? SIGN_POS : SIGN_NEG; ! 75: } ! 76: } ! 77: #ifdef PARANOID ! 78: else ! 79: { ! 80: EXCEPTION(EX_INTERNAL|0x102); ! 81: } ! 82: #endif PARANOID ! 83: dest->sign = (a->sign ^ b->sign); ! 84: } ! 85: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.