diff options
Diffstat (limited to 'arch/x86/math-emu/reg_add_sub.c')
-rw-r--r-- | arch/x86/math-emu/reg_add_sub.c | 563 |
1 files changed, 261 insertions, 302 deletions
diff --git a/arch/x86/math-emu/reg_add_sub.c b/arch/x86/math-emu/reg_add_sub.c index 7cd3b37ac084..deea48b9f13a 100644 --- a/arch/x86/math-emu/reg_add_sub.c +++ b/arch/x86/math-emu/reg_add_sub.c | |||
@@ -27,7 +27,7 @@ | |||
27 | static | 27 | static |
28 | int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, | 28 | int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, |
29 | FPU_REG const *b, u_char tagb, u_char signb, | 29 | FPU_REG const *b, u_char tagb, u_char signb, |
30 | FPU_REG *dest, int deststnr, int control_w); | 30 | FPU_REG * dest, int deststnr, int control_w); |
31 | 31 | ||
32 | /* | 32 | /* |
33 | Operates on st(0) and st(n), or on st(0) and temporary data. | 33 | Operates on st(0) and st(n), or on st(0) and temporary data. |
@@ -35,340 +35,299 @@ int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, | |||
35 | */ | 35 | */ |
36 | int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w) | 36 | int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w) |
37 | { | 37 | { |
38 | FPU_REG *a = &st(0); | 38 | FPU_REG *a = &st(0); |
39 | FPU_REG *dest = &st(deststnr); | 39 | FPU_REG *dest = &st(deststnr); |
40 | u_char signb = getsign(b); | 40 | u_char signb = getsign(b); |
41 | u_char taga = FPU_gettag0(); | 41 | u_char taga = FPU_gettag0(); |
42 | u_char signa = getsign(a); | 42 | u_char signa = getsign(a); |
43 | u_char saved_sign = getsign(dest); | 43 | u_char saved_sign = getsign(dest); |
44 | int diff, tag, expa, expb; | 44 | int diff, tag, expa, expb; |
45 | 45 | ||
46 | if ( !(taga | tagb) ) | 46 | if (!(taga | tagb)) { |
47 | { | 47 | expa = exponent(a); |
48 | expa = exponent(a); | 48 | expb = exponent(b); |
49 | expb = exponent(b); | 49 | |
50 | 50 | valid_add: | |
51 | valid_add: | 51 | /* Both registers are valid */ |
52 | /* Both registers are valid */ | 52 | if (!(signa ^ signb)) { |
53 | if (!(signa ^ signb)) | 53 | /* signs are the same */ |
54 | { | 54 | tag = |
55 | /* signs are the same */ | 55 | FPU_u_add(a, b, dest, control_w, signa, expa, expb); |
56 | tag = FPU_u_add(a, b, dest, control_w, signa, expa, expb); | 56 | } else { |
57 | } | 57 | /* The signs are different, so do a subtraction */ |
58 | else | 58 | diff = expa - expb; |
59 | { | 59 | if (!diff) { |
60 | /* The signs are different, so do a subtraction */ | 60 | diff = a->sigh - b->sigh; /* This works only if the ms bits |
61 | diff = expa - expb; | 61 | are identical. */ |
62 | if (!diff) | 62 | if (!diff) { |
63 | { | 63 | diff = a->sigl > b->sigl; |
64 | diff = a->sigh - b->sigh; /* This works only if the ms bits | 64 | if (!diff) |
65 | are identical. */ | 65 | diff = -(a->sigl < b->sigl); |
66 | if (!diff) | 66 | } |
67 | { | 67 | } |
68 | diff = a->sigl > b->sigl; | 68 | |
69 | if (!diff) | 69 | if (diff > 0) { |
70 | diff = -(a->sigl < b->sigl); | 70 | tag = |
71 | FPU_u_sub(a, b, dest, control_w, signa, | ||
72 | expa, expb); | ||
73 | } else if (diff < 0) { | ||
74 | tag = | ||
75 | FPU_u_sub(b, a, dest, control_w, signb, | ||
76 | expb, expa); | ||
77 | } else { | ||
78 | FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); | ||
79 | /* sign depends upon rounding mode */ | ||
80 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) | ||
81 | ? SIGN_POS : SIGN_NEG); | ||
82 | return TAG_Zero; | ||
83 | } | ||
71 | } | 84 | } |
72 | } | ||
73 | |||
74 | if (diff > 0) | ||
75 | { | ||
76 | tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb); | ||
77 | } | ||
78 | else if ( diff < 0 ) | ||
79 | { | ||
80 | tag = FPU_u_sub(b, a, dest, control_w, signb, expb, expa); | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); | ||
85 | /* sign depends upon rounding mode */ | ||
86 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) | ||
87 | ? SIGN_POS : SIGN_NEG); | ||
88 | return TAG_Zero; | ||
89 | } | ||
90 | } | ||
91 | 85 | ||
92 | if ( tag < 0 ) | 86 | if (tag < 0) { |
93 | { | 87 | setsign(dest, saved_sign); |
94 | setsign(dest, saved_sign); | 88 | return tag; |
95 | return tag; | 89 | } |
90 | FPU_settagi(deststnr, tag); | ||
91 | return tag; | ||
96 | } | 92 | } |
97 | FPU_settagi(deststnr, tag); | ||
98 | return tag; | ||
99 | } | ||
100 | 93 | ||
101 | if ( taga == TAG_Special ) | 94 | if (taga == TAG_Special) |
102 | taga = FPU_Special(a); | 95 | taga = FPU_Special(a); |
103 | if ( tagb == TAG_Special ) | 96 | if (tagb == TAG_Special) |
104 | tagb = FPU_Special(b); | 97 | tagb = FPU_Special(b); |
105 | 98 | ||
106 | if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) | 99 | if (((taga == TAG_Valid) && (tagb == TW_Denormal)) |
107 | || ((taga == TW_Denormal) && (tagb == TAG_Valid)) | 100 | || ((taga == TW_Denormal) && (tagb == TAG_Valid)) |
108 | || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) | 101 | || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { |
109 | { | 102 | FPU_REG x, y; |
110 | FPU_REG x, y; | 103 | |
104 | if (denormal_operand() < 0) | ||
105 | return FPU_Exception; | ||
106 | |||
107 | FPU_to_exp16(a, &x); | ||
108 | FPU_to_exp16(b, &y); | ||
109 | a = &x; | ||
110 | b = &y; | ||
111 | expa = exponent16(a); | ||
112 | expb = exponent16(b); | ||
113 | goto valid_add; | ||
114 | } | ||
111 | 115 | ||
112 | if ( denormal_operand() < 0 ) | 116 | if ((taga == TW_NaN) || (tagb == TW_NaN)) { |
113 | return FPU_Exception; | 117 | if (deststnr == 0) |
118 | return real_2op_NaN(b, tagb, deststnr, a); | ||
119 | else | ||
120 | return real_2op_NaN(a, taga, deststnr, a); | ||
121 | } | ||
114 | 122 | ||
115 | FPU_to_exp16(a, &x); | 123 | return add_sub_specials(a, taga, signa, b, tagb, signb, |
116 | FPU_to_exp16(b, &y); | 124 | dest, deststnr, control_w); |
117 | a = &x; | ||
118 | b = &y; | ||
119 | expa = exponent16(a); | ||
120 | expb = exponent16(b); | ||
121 | goto valid_add; | ||
122 | } | ||
123 | |||
124 | if ( (taga == TW_NaN) || (tagb == TW_NaN) ) | ||
125 | { | ||
126 | if ( deststnr == 0 ) | ||
127 | return real_2op_NaN(b, tagb, deststnr, a); | ||
128 | else | ||
129 | return real_2op_NaN(a, taga, deststnr, a); | ||
130 | } | ||
131 | |||
132 | return add_sub_specials(a, taga, signa, b, tagb, signb, | ||
133 | dest, deststnr, control_w); | ||
134 | } | 125 | } |
135 | 126 | ||
136 | |||
137 | /* Subtract b from a. (a-b) -> dest */ | 127 | /* Subtract b from a. (a-b) -> dest */ |
138 | int FPU_sub(int flags, int rm, int control_w) | 128 | int FPU_sub(int flags, int rm, int control_w) |
139 | { | 129 | { |
140 | FPU_REG const *a, *b; | 130 | FPU_REG const *a, *b; |
141 | FPU_REG *dest; | 131 | FPU_REG *dest; |
142 | u_char taga, tagb, signa, signb, saved_sign, sign; | 132 | u_char taga, tagb, signa, signb, saved_sign, sign; |
143 | int diff, tag = 0, expa, expb, deststnr; | 133 | int diff, tag = 0, expa, expb, deststnr; |
144 | 134 | ||
145 | a = &st(0); | 135 | a = &st(0); |
146 | taga = FPU_gettag0(); | 136 | taga = FPU_gettag0(); |
147 | 137 | ||
148 | deststnr = 0; | 138 | deststnr = 0; |
149 | if ( flags & LOADED ) | 139 | if (flags & LOADED) { |
150 | { | 140 | b = (FPU_REG *) rm; |
151 | b = (FPU_REG *)rm; | 141 | tagb = flags & 0x0f; |
152 | tagb = flags & 0x0f; | 142 | } else { |
153 | } | 143 | b = &st(rm); |
154 | else | 144 | tagb = FPU_gettagi(rm); |
155 | { | 145 | |
156 | b = &st(rm); | 146 | if (flags & DEST_RM) |
157 | tagb = FPU_gettagi(rm); | 147 | deststnr = rm; |
158 | |||
159 | if ( flags & DEST_RM ) | ||
160 | deststnr = rm; | ||
161 | } | ||
162 | |||
163 | signa = getsign(a); | ||
164 | signb = getsign(b); | ||
165 | |||
166 | if ( flags & REV ) | ||
167 | { | ||
168 | signa ^= SIGN_NEG; | ||
169 | signb ^= SIGN_NEG; | ||
170 | } | ||
171 | |||
172 | dest = &st(deststnr); | ||
173 | saved_sign = getsign(dest); | ||
174 | |||
175 | if ( !(taga | tagb) ) | ||
176 | { | ||
177 | expa = exponent(a); | ||
178 | expb = exponent(b); | ||
179 | |||
180 | valid_subtract: | ||
181 | /* Both registers are valid */ | ||
182 | |||
183 | diff = expa - expb; | ||
184 | |||
185 | if (!diff) | ||
186 | { | ||
187 | diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ | ||
188 | if (!diff) | ||
189 | { | ||
190 | diff = a->sigl > b->sigl; | ||
191 | if (!diff) | ||
192 | diff = -(a->sigl < b->sigl); | ||
193 | } | ||
194 | } | 148 | } |
195 | 149 | ||
196 | switch ( (((int)signa)*2 + signb) / SIGN_NEG ) | 150 | signa = getsign(a); |
197 | { | 151 | signb = getsign(b); |
198 | case 0: /* P - P */ | 152 | |
199 | case 3: /* N - N */ | 153 | if (flags & REV) { |
200 | if (diff > 0) | 154 | signa ^= SIGN_NEG; |
201 | { | 155 | signb ^= SIGN_NEG; |
202 | /* |a| > |b| */ | 156 | } |
203 | tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb); | 157 | |
204 | } | 158 | dest = &st(deststnr); |
205 | else if ( diff == 0 ) | 159 | saved_sign = getsign(dest); |
206 | { | 160 | |
207 | FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); | 161 | if (!(taga | tagb)) { |
208 | 162 | expa = exponent(a); | |
209 | /* sign depends upon rounding mode */ | 163 | expb = exponent(b); |
210 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) | 164 | |
211 | ? SIGN_POS : SIGN_NEG); | 165 | valid_subtract: |
212 | return TAG_Zero; | 166 | /* Both registers are valid */ |
213 | } | 167 | |
214 | else | 168 | diff = expa - expb; |
215 | { | 169 | |
216 | sign = signa ^ SIGN_NEG; | 170 | if (!diff) { |
217 | tag = FPU_u_sub(b, a, dest, control_w, sign, expb, expa); | 171 | diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ |
218 | } | 172 | if (!diff) { |
219 | break; | 173 | diff = a->sigl > b->sigl; |
220 | case 1: /* P - N */ | 174 | if (!diff) |
221 | tag = FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, expb); | 175 | diff = -(a->sigl < b->sigl); |
222 | break; | 176 | } |
223 | case 2: /* N - P */ | 177 | } |
224 | tag = FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, expb); | 178 | |
225 | break; | 179 | switch ((((int)signa) * 2 + signb) / SIGN_NEG) { |
180 | case 0: /* P - P */ | ||
181 | case 3: /* N - N */ | ||
182 | if (diff > 0) { | ||
183 | /* |a| > |b| */ | ||
184 | tag = | ||
185 | FPU_u_sub(a, b, dest, control_w, signa, | ||
186 | expa, expb); | ||
187 | } else if (diff == 0) { | ||
188 | FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); | ||
189 | |||
190 | /* sign depends upon rounding mode */ | ||
191 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) | ||
192 | ? SIGN_POS : SIGN_NEG); | ||
193 | return TAG_Zero; | ||
194 | } else { | ||
195 | sign = signa ^ SIGN_NEG; | ||
196 | tag = | ||
197 | FPU_u_sub(b, a, dest, control_w, sign, expb, | ||
198 | expa); | ||
199 | } | ||
200 | break; | ||
201 | case 1: /* P - N */ | ||
202 | tag = | ||
203 | FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, | ||
204 | expb); | ||
205 | break; | ||
206 | case 2: /* N - P */ | ||
207 | tag = | ||
208 | FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, | ||
209 | expb); | ||
210 | break; | ||
226 | #ifdef PARANOID | 211 | #ifdef PARANOID |
227 | default: | 212 | default: |
228 | EXCEPTION(EX_INTERNAL|0x111); | 213 | EXCEPTION(EX_INTERNAL | 0x111); |
229 | return -1; | 214 | return -1; |
230 | #endif | 215 | #endif |
216 | } | ||
217 | if (tag < 0) { | ||
218 | setsign(dest, saved_sign); | ||
219 | return tag; | ||
220 | } | ||
221 | FPU_settagi(deststnr, tag); | ||
222 | return tag; | ||
231 | } | 223 | } |
232 | if ( tag < 0 ) | ||
233 | { | ||
234 | setsign(dest, saved_sign); | ||
235 | return tag; | ||
236 | } | ||
237 | FPU_settagi(deststnr, tag); | ||
238 | return tag; | ||
239 | } | ||
240 | 224 | ||
241 | if ( taga == TAG_Special ) | 225 | if (taga == TAG_Special) |
242 | taga = FPU_Special(a); | 226 | taga = FPU_Special(a); |
243 | if ( tagb == TAG_Special ) | 227 | if (tagb == TAG_Special) |
244 | tagb = FPU_Special(b); | 228 | tagb = FPU_Special(b); |
245 | 229 | ||
246 | if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) | 230 | if (((taga == TAG_Valid) && (tagb == TW_Denormal)) |
247 | || ((taga == TW_Denormal) && (tagb == TAG_Valid)) | 231 | || ((taga == TW_Denormal) && (tagb == TAG_Valid)) |
248 | || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) | 232 | || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { |
249 | { | 233 | FPU_REG x, y; |
250 | FPU_REG x, y; | ||
251 | 234 | ||
252 | if ( denormal_operand() < 0 ) | 235 | if (denormal_operand() < 0) |
253 | return FPU_Exception; | 236 | return FPU_Exception; |
237 | |||
238 | FPU_to_exp16(a, &x); | ||
239 | FPU_to_exp16(b, &y); | ||
240 | a = &x; | ||
241 | b = &y; | ||
242 | expa = exponent16(a); | ||
243 | expb = exponent16(b); | ||
254 | 244 | ||
255 | FPU_to_exp16(a, &x); | 245 | goto valid_subtract; |
256 | FPU_to_exp16(b, &y); | ||
257 | a = &x; | ||
258 | b = &y; | ||
259 | expa = exponent16(a); | ||
260 | expb = exponent16(b); | ||
261 | |||
262 | goto valid_subtract; | ||
263 | } | ||
264 | |||
265 | if ( (taga == TW_NaN) || (tagb == TW_NaN) ) | ||
266 | { | ||
267 | FPU_REG const *d1, *d2; | ||
268 | if ( flags & REV ) | ||
269 | { | ||
270 | d1 = b; | ||
271 | d2 = a; | ||
272 | } | 246 | } |
273 | else | 247 | |
274 | { | 248 | if ((taga == TW_NaN) || (tagb == TW_NaN)) { |
275 | d1 = a; | 249 | FPU_REG const *d1, *d2; |
276 | d2 = b; | 250 | if (flags & REV) { |
251 | d1 = b; | ||
252 | d2 = a; | ||
253 | } else { | ||
254 | d1 = a; | ||
255 | d2 = b; | ||
256 | } | ||
257 | if (flags & LOADED) | ||
258 | return real_2op_NaN(b, tagb, deststnr, d1); | ||
259 | if (flags & DEST_RM) | ||
260 | return real_2op_NaN(a, taga, deststnr, d2); | ||
261 | else | ||
262 | return real_2op_NaN(b, tagb, deststnr, d2); | ||
277 | } | 263 | } |
278 | if ( flags & LOADED ) | ||
279 | return real_2op_NaN(b, tagb, deststnr, d1); | ||
280 | if ( flags & DEST_RM ) | ||
281 | return real_2op_NaN(a, taga, deststnr, d2); | ||
282 | else | ||
283 | return real_2op_NaN(b, tagb, deststnr, d2); | ||
284 | } | ||
285 | |||
286 | return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG, | ||
287 | dest, deststnr, control_w); | ||
288 | } | ||
289 | 264 | ||
265 | return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG, | ||
266 | dest, deststnr, control_w); | ||
267 | } | ||
290 | 268 | ||
291 | static | 269 | static |
292 | int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, | 270 | int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, |
293 | FPU_REG const *b, u_char tagb, u_char signb, | 271 | FPU_REG const *b, u_char tagb, u_char signb, |
294 | FPU_REG *dest, int deststnr, int control_w) | 272 | FPU_REG * dest, int deststnr, int control_w) |
295 | { | 273 | { |
296 | if ( ((taga == TW_Denormal) || (tagb == TW_Denormal)) | 274 | if (((taga == TW_Denormal) || (tagb == TW_Denormal)) |
297 | && (denormal_operand() < 0) ) | 275 | && (denormal_operand() < 0)) |
298 | return FPU_Exception; | 276 | return FPU_Exception; |
299 | 277 | ||
300 | if (taga == TAG_Zero) | 278 | if (taga == TAG_Zero) { |
301 | { | 279 | if (tagb == TAG_Zero) { |
302 | if (tagb == TAG_Zero) | 280 | /* Both are zero, result will be zero. */ |
303 | { | 281 | u_char different_signs = signa ^ signb; |
304 | /* Both are zero, result will be zero. */ | 282 | |
305 | u_char different_signs = signa ^ signb; | 283 | FPU_copy_to_regi(a, TAG_Zero, deststnr); |
306 | 284 | if (different_signs) { | |
307 | FPU_copy_to_regi(a, TAG_Zero, deststnr); | 285 | /* Signs are different. */ |
308 | if ( different_signs ) | 286 | /* Sign of answer depends upon rounding mode. */ |
309 | { | 287 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) |
310 | /* Signs are different. */ | 288 | ? SIGN_POS : SIGN_NEG); |
311 | /* Sign of answer depends upon rounding mode. */ | 289 | } else |
312 | setsign(dest, ((control_w & CW_RC) != RC_DOWN) | 290 | setsign(dest, signa); /* signa may differ from the sign of a. */ |
313 | ? SIGN_POS : SIGN_NEG); | 291 | return TAG_Zero; |
314 | } | 292 | } else { |
315 | else | 293 | reg_copy(b, dest); |
316 | setsign(dest, signa); /* signa may differ from the sign of a. */ | 294 | if ((tagb == TW_Denormal) && (b->sigh & 0x80000000)) { |
317 | return TAG_Zero; | 295 | /* A pseudoDenormal, convert it. */ |
318 | } | 296 | addexponent(dest, 1); |
319 | else | 297 | tagb = TAG_Valid; |
320 | { | 298 | } else if (tagb > TAG_Empty) |
321 | reg_copy(b, dest); | 299 | tagb = TAG_Special; |
322 | if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) ) | 300 | setsign(dest, signb); /* signb may differ from the sign of b. */ |
323 | { | 301 | FPU_settagi(deststnr, tagb); |
324 | /* A pseudoDenormal, convert it. */ | 302 | return tagb; |
325 | addexponent(dest, 1); | 303 | } |
326 | tagb = TAG_Valid; | 304 | } else if (tagb == TAG_Zero) { |
327 | } | 305 | reg_copy(a, dest); |
328 | else if ( tagb > TAG_Empty ) | 306 | if ((taga == TW_Denormal) && (a->sigh & 0x80000000)) { |
329 | tagb = TAG_Special; | 307 | /* A pseudoDenormal */ |
330 | setsign(dest, signb); /* signb may differ from the sign of b. */ | 308 | addexponent(dest, 1); |
331 | FPU_settagi(deststnr, tagb); | 309 | taga = TAG_Valid; |
332 | return tagb; | 310 | } else if (taga > TAG_Empty) |
333 | } | 311 | taga = TAG_Special; |
334 | } | 312 | setsign(dest, signa); /* signa may differ from the sign of a. */ |
335 | else if (tagb == TAG_Zero) | 313 | FPU_settagi(deststnr, taga); |
336 | { | 314 | return taga; |
337 | reg_copy(a, dest); | 315 | } else if (taga == TW_Infinity) { |
338 | if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) ) | 316 | if ((tagb != TW_Infinity) || (signa == signb)) { |
339 | { | 317 | FPU_copy_to_regi(a, TAG_Special, deststnr); |
340 | /* A pseudoDenormal */ | 318 | setsign(dest, signa); /* signa may differ from the sign of a. */ |
341 | addexponent(dest, 1); | 319 | return taga; |
342 | taga = TAG_Valid; | 320 | } |
343 | } | 321 | /* Infinity-Infinity is undefined. */ |
344 | else if ( taga > TAG_Empty ) | 322 | return arith_invalid(deststnr); |
345 | taga = TAG_Special; | 323 | } else if (tagb == TW_Infinity) { |
346 | setsign(dest, signa); /* signa may differ from the sign of a. */ | 324 | FPU_copy_to_regi(b, TAG_Special, deststnr); |
347 | FPU_settagi(deststnr, taga); | 325 | setsign(dest, signb); /* signb may differ from the sign of b. */ |
348 | return taga; | 326 | return tagb; |
349 | } | ||
350 | else if (taga == TW_Infinity) | ||
351 | { | ||
352 | if ( (tagb != TW_Infinity) || (signa == signb) ) | ||
353 | { | ||
354 | FPU_copy_to_regi(a, TAG_Special, deststnr); | ||
355 | setsign(dest, signa); /* signa may differ from the sign of a. */ | ||
356 | return taga; | ||
357 | } | 327 | } |
358 | /* Infinity-Infinity is undefined. */ | ||
359 | return arith_invalid(deststnr); | ||
360 | } | ||
361 | else if (tagb == TW_Infinity) | ||
362 | { | ||
363 | FPU_copy_to_regi(b, TAG_Special, deststnr); | ||
364 | setsign(dest, signb); /* signb may differ from the sign of b. */ | ||
365 | return tagb; | ||
366 | } | ||
367 | |||
368 | #ifdef PARANOID | 328 | #ifdef PARANOID |
369 | EXCEPTION(EX_INTERNAL|0x101); | 329 | EXCEPTION(EX_INTERNAL | 0x101); |
370 | #endif | 330 | #endif |
371 | 331 | ||
372 | return FPU_Exception; | 332 | return FPU_Exception; |
373 | } | 333 | } |
374 | |||