This source file includes following definitions.
- reg_add
- reg_sub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include "exception.h"
18 #include "reg_constant.h"
19 #include "fpu_emu.h"
20 #include "control_w.h"
21 #include "fpu_system.h"
22
23
24 void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
25 {
26 int diff;
27
28 if ( !(a->tag | b->tag) )
29 {
30
31 if (!(a->sign ^ b->sign))
32 {
33
34 reg_u_add(a, b, dest);
35 dest->sign = a->sign;
36 return;
37 }
38
39
40 diff = a->exp - b->exp;
41 if (!diff)
42 {
43 diff = a->sigh - b->sigh;
44 if (!diff)
45 {
46 diff = a->sigl > b->sigl;
47 if (!diff)
48 diff = -(a->sigl < b->sigl);
49 }
50 }
51
52 if (diff > 0)
53 {
54 reg_u_sub(a, b, dest);
55 dest->sign = a->sign;
56 }
57 else if ( diff == 0 )
58 {
59 reg_move(&CONST_Z, dest);
60
61 dest->sign = ((control_word & CW_RC) != RC_DOWN)
62 ? SIGN_POS : SIGN_NEG;
63 }
64 else
65 {
66 reg_u_sub(b, a, dest);
67 dest->sign = b->sign;
68 }
69 return;
70 }
71 else
72 {
73 if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
74 { real_2op_NaN(a, b, dest); return; }
75 else if (a->tag == TW_Zero)
76 {
77 if (b->tag == TW_Zero)
78 {
79 char different_signs = a->sign ^ b->sign;
80
81 reg_move(a, dest);
82 if (different_signs)
83 {
84
85
86 dest->sign = ((control_word & CW_RC) != RC_DOWN)
87 ? SIGN_POS : SIGN_NEG;
88 }
89 }
90 else
91 reg_move(b, dest);
92 return;
93 }
94 else if (b->tag == TW_Zero)
95 { reg_move(a, dest); return; }
96 else if (a->tag == TW_Infinity)
97 {
98 if (b->tag != TW_Infinity)
99 { reg_move(a, dest); return; }
100
101 if (a->sign == b->sign)
102 { reg_move(a, dest); return; }
103 reg_move(&CONST_QNaN, dest);
104 return;
105 }
106 else if (b->tag == TW_Infinity)
107 { reg_move(b, dest); return; }
108 }
109 #ifdef PARANOID
110 EXCEPTION(EX_INTERNAL|0x101);
111 #endif
112 }
113
114
115
116 void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
117 {
118 int diff;
119
120 if ( !(a->tag | b->tag) )
121 {
122
123 diff = a->exp - b->exp;
124 if (!diff)
125 {
126 diff = a->sigh - b->sigh;
127 if (!diff)
128 {
129 diff = a->sigl > b->sigl;
130 if (!diff)
131 diff = -(a->sigl < b->sigl);
132 }
133 }
134
135 switch (a->sign*2 + b->sign)
136 {
137 case 0:
138 case 3:
139 if (diff > 0)
140 {
141 reg_u_sub(a, b, dest);
142 dest->sign = a->sign;
143 }
144 else if ( diff == 0 )
145 {
146 reg_move(&CONST_Z, dest);
147
148 dest->sign = ((control_word & CW_RC) != RC_DOWN)
149 ? SIGN_POS : SIGN_NEG;
150 }
151 else
152 {
153 reg_u_sub(b, a, dest);
154 dest->sign = a->sign ^ SIGN_POS^SIGN_NEG;
155 }
156 return;
157 case 1:
158 reg_u_add(a, b, dest);
159 dest->sign = SIGN_POS;
160 return;
161 case 2:
162 reg_u_add(a, b, dest);
163 dest->sign = SIGN_NEG;
164 return;
165 }
166 }
167 else
168 {
169 if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
170 { real_2op_NaN(a, b, dest); return; }
171 else if (b->tag == TW_Zero)
172 {
173 if (a->tag == TW_Zero)
174 {
175 char same_signs = !(a->sign ^ b->sign);
176
177 reg_move(a, dest);
178 if (same_signs)
179 {
180
181 dest->sign = ((control_word & CW_RC) != RC_DOWN)
182 ? SIGN_POS : SIGN_NEG;
183 }
184 }
185 else
186 reg_move(a, dest);
187 return;
188 }
189 else if (a->tag == TW_Zero)
190 {
191 reg_move(b, dest);
192 dest->sign ^= SIGN_POS^SIGN_NEG;
193 return;
194 }
195 else if (a->tag == TW_Infinity)
196 {
197 if (b->tag != TW_Infinity)
198 { reg_move(a, dest); return; }
199 if (a->sign == b->sign)
200 { reg_move(&CONST_QNaN, dest); return; }
201 reg_move(a, dest);
202 return;
203 }
204 else if (b->tag == TW_Infinity)
205 {
206 reg_move(b, dest);
207 dest->sign ^= SIGN_POS^SIGN_NEG;
208 return;
209 }
210 }
211 #ifdef PARANOID
212 EXCEPTION(EX_INTERNAL|0x110);
213 #endif
214 }
215