|
|
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.