]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | .file "reg_round.S" |
2 | /*---------------------------------------------------------------------------+ | |
3 | | reg_round.S | | |
4 | | | | |
5 | | Rounding/truncation/etc for FPU basic arithmetic functions. | | |
6 | | | | |
7 | | Copyright (C) 1993,1995,1997 | | |
8 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | |
9 | | Australia. E-mail billm@suburbia.net | | |
10 | | | | |
11 | | This code has four possible entry points. | | |
12 | | The following must be entered by a jmp instruction: | | |
13 | | fpu_reg_round, fpu_reg_round_sqrt, and fpu_Arith_exit. | | |
14 | | | | |
15 | | The FPU_round entry point is intended to be used by C code. | | |
16 | | From C, call as: | | |
17 | | int FPU_round(FPU_REG *arg, unsigned int extent, unsigned int control_w) | | |
18 | | | | |
19 | | Return value is the tag of the answer, or-ed with FPU_Exception if | | |
20 | | one was raised, or -1 on internal error. | | |
21 | | | | |
22 | | For correct "up" and "down" rounding, the argument must have the correct | | |
23 | | sign. | | |
24 | | | | |
25 | +---------------------------------------------------------------------------*/ | |
26 | ||
27 | /*---------------------------------------------------------------------------+ | |
28 | | Four entry points. | | |
29 | | | | |
30 | | Needed by both the fpu_reg_round and fpu_reg_round_sqrt entry points: | | |
31 | | %eax:%ebx 64 bit significand | | |
32 | | %edx 32 bit extension of the significand | | |
33 | | %edi pointer to an FPU_REG for the result to be stored | | |
34 | | stack calling function must have set up a C stack frame and | | |
35 | | pushed %esi, %edi, and %ebx | | |
36 | | | | |
37 | | Needed just for the fpu_reg_round_sqrt entry point: | | |
38 | | %cx A control word in the same format as the FPU control word. | | |
39 | | Otherwise, PARAM4 must give such a value. | | |
40 | | | | |
41 | | | | |
42 | | The significand and its extension are assumed to be exact in the | | |
43 | | following sense: | | |
44 | | If the significand by itself is the exact result then the significand | | |
45 | | extension (%edx) must contain 0, otherwise the significand extension | | |
46 | | must be non-zero. | | |
47 | | If the significand extension is non-zero then the significand is | | |
48 | | smaller than the magnitude of the correct exact result by an amount | | |
49 | | greater than zero and less than one ls bit of the significand. | | |
50 | | The significand extension is only required to have three possible | | |
51 | | non-zero values: | | |
52 | | less than 0x80000000 <=> the significand is less than 1/2 an ls | | |
53 | | bit smaller than the magnitude of the | | |
54 | | true exact result. | | |
55 | | exactly 0x80000000 <=> the significand is exactly 1/2 an ls bit | | |
56 | | smaller than the magnitude of the true | | |
57 | | exact result. | | |
58 | | greater than 0x80000000 <=> the significand is more than 1/2 an ls | | |
59 | | bit smaller than the magnitude of the | | |
60 | | true exact result. | | |
61 | | | | |
62 | +---------------------------------------------------------------------------*/ | |
63 | ||
64 | /*---------------------------------------------------------------------------+ | |
65 | | The code in this module has become quite complex, but it should handle | | |
66 | | all of the FPU flags which are set at this stage of the basic arithmetic | | |
67 | | computations. | | |
68 | | There are a few rare cases where the results are not set identically to | | |
69 | | a real FPU. These require a bit more thought because at this stage the | | |
70 | | results of the code here appear to be more consistent... | | |
71 | | This may be changed in a future version. | | |
72 | +---------------------------------------------------------------------------*/ | |
73 | ||
74 | ||
75 | #include "fpu_emu.h" | |
76 | #include "exception.h" | |
77 | #include "control_w.h" | |
78 | ||
79 | /* Flags for FPU_bits_lost */ | |
80 | #define LOST_DOWN $1 | |
81 | #define LOST_UP $2 | |
82 | ||
83 | /* Flags for FPU_denormal */ | |
84 | #define DENORMAL $1 | |
85 | #define UNMASKED_UNDERFLOW $2 | |
86 | ||
87 | ||
88 | #ifndef NON_REENTRANT_FPU | |
89 | /* Make the code re-entrant by putting | |
90 | local storage on the stack: */ | |
91 | #define FPU_bits_lost (%esp) | |
92 | #define FPU_denormal 1(%esp) | |
93 | ||
94 | #else | |
95 | /* Not re-entrant, so we can gain speed by putting | |
96 | local storage in a static area: */ | |
97 | .data | |
98 | .align 4,0 | |
99 | FPU_bits_lost: | |
100 | .byte 0 | |
101 | FPU_denormal: | |
102 | .byte 0 | |
103 | #endif /* NON_REENTRANT_FPU */ | |
104 | ||
105 | ||
106 | .text | |
107 | .globl fpu_reg_round | |
108 | .globl fpu_Arith_exit | |
109 | ||
110 | /* Entry point when called from C */ | |
111 | ENTRY(FPU_round) | |
112 | pushl %ebp | |
113 | movl %esp,%ebp | |
114 | pushl %esi | |
115 | pushl %edi | |
116 | pushl %ebx | |
117 | ||
118 | movl PARAM1,%edi | |
119 | movl SIGH(%edi),%eax | |
120 | movl SIGL(%edi),%ebx | |
121 | movl PARAM2,%edx | |
122 | ||
123 | fpu_reg_round: /* Normal entry point */ | |
124 | movl PARAM4,%ecx | |
125 | ||
126 | #ifndef NON_REENTRANT_FPU | |
127 | pushl %ebx /* adjust the stack pointer */ | |
128 | #endif /* NON_REENTRANT_FPU */ | |
129 | ||
130 | #ifdef PARANOID | |
131 | /* Cannot use this here yet */ | |
132 | /* orl %eax,%eax */ | |
133 | /* jns L_entry_bugged */ | |
134 | #endif /* PARANOID */ | |
135 | ||
136 | cmpw EXP_UNDER,EXP(%edi) | |
137 | jle L_Make_denorm /* The number is a de-normal */ | |
138 | ||
139 | movb $0,FPU_denormal /* 0 -> not a de-normal */ | |
140 | ||
141 | Denorm_done: | |
142 | movb $0,FPU_bits_lost /* No bits yet lost in rounding */ | |
143 | ||
144 | movl %ecx,%esi | |
145 | andl CW_PC,%ecx | |
146 | cmpl PR_64_BITS,%ecx | |
147 | je LRound_To_64 | |
148 | ||
149 | cmpl PR_53_BITS,%ecx | |
150 | je LRound_To_53 | |
151 | ||
152 | cmpl PR_24_BITS,%ecx | |
153 | je LRound_To_24 | |
154 | ||
155 | #ifdef PECULIAR_486 | |
156 | /* With the precision control bits set to 01 "(reserved)", a real 80486 | |
157 | behaves as if the precision control bits were set to 11 "64 bits" */ | |
158 | cmpl PR_RESERVED_BITS,%ecx | |
159 | je LRound_To_64 | |
160 | #ifdef PARANOID | |
161 | jmp L_bugged_denorm_486 | |
162 | #endif /* PARANOID */ | |
163 | #else | |
164 | #ifdef PARANOID | |
165 | jmp L_bugged_denorm /* There is no bug, just a bad control word */ | |
166 | #endif /* PARANOID */ | |
167 | #endif /* PECULIAR_486 */ | |
168 | ||
169 | ||
170 | /* Round etc to 24 bit precision */ | |
171 | LRound_To_24: | |
172 | movl %esi,%ecx | |
173 | andl CW_RC,%ecx | |
174 | cmpl RC_RND,%ecx | |
175 | je LRound_nearest_24 | |
176 | ||
177 | cmpl RC_CHOP,%ecx | |
178 | je LCheck_truncate_24 | |
179 | ||
180 | cmpl RC_UP,%ecx /* Towards +infinity */ | |
181 | je LUp_24 | |
182 | ||
183 | cmpl RC_DOWN,%ecx /* Towards -infinity */ | |
184 | je LDown_24 | |
185 | ||
186 | #ifdef PARANOID | |
187 | jmp L_bugged_round24 | |
188 | #endif /* PARANOID */ | |
189 | ||
190 | LUp_24: | |
191 | cmpb SIGN_POS,PARAM5 | |
192 | jne LCheck_truncate_24 /* If negative then up==truncate */ | |
193 | ||
194 | jmp LCheck_24_round_up | |
195 | ||
196 | LDown_24: | |
197 | cmpb SIGN_POS,PARAM5 | |
198 | je LCheck_truncate_24 /* If positive then down==truncate */ | |
199 | ||
200 | LCheck_24_round_up: | |
201 | movl %eax,%ecx | |
202 | andl $0x000000ff,%ecx | |
203 | orl %ebx,%ecx | |
204 | orl %edx,%ecx | |
205 | jnz LDo_24_round_up | |
206 | jmp L_Re_normalise | |
207 | ||
208 | LRound_nearest_24: | |
209 | /* Do rounding of the 24th bit if needed (nearest or even) */ | |
210 | movl %eax,%ecx | |
211 | andl $0x000000ff,%ecx | |
212 | cmpl $0x00000080,%ecx | |
213 | jc LCheck_truncate_24 /* less than half, no increment needed */ | |
214 | ||
215 | jne LGreater_Half_24 /* greater than half, increment needed */ | |
216 | ||
217 | /* Possibly half, we need to check the ls bits */ | |
218 | orl %ebx,%ebx | |
219 | jnz LGreater_Half_24 /* greater than half, increment needed */ | |
220 | ||
221 | orl %edx,%edx | |
222 | jnz LGreater_Half_24 /* greater than half, increment needed */ | |
223 | ||
224 | /* Exactly half, increment only if 24th bit is 1 (round to even) */ | |
225 | testl $0x00000100,%eax | |
226 | jz LDo_truncate_24 | |
227 | ||
228 | LGreater_Half_24: /* Rounding: increment at the 24th bit */ | |
229 | LDo_24_round_up: | |
230 | andl $0xffffff00,%eax /* Truncate to 24 bits */ | |
231 | xorl %ebx,%ebx | |
232 | movb LOST_UP,FPU_bits_lost | |
233 | addl $0x00000100,%eax | |
234 | jmp LCheck_Round_Overflow | |
235 | ||
236 | LCheck_truncate_24: | |
237 | movl %eax,%ecx | |
238 | andl $0x000000ff,%ecx | |
239 | orl %ebx,%ecx | |
240 | orl %edx,%ecx | |
241 | jz L_Re_normalise /* No truncation needed */ | |
242 | ||
243 | LDo_truncate_24: | |
244 | andl $0xffffff00,%eax /* Truncate to 24 bits */ | |
245 | xorl %ebx,%ebx | |
246 | movb LOST_DOWN,FPU_bits_lost | |
247 | jmp L_Re_normalise | |
248 | ||
249 | ||
250 | /* Round etc to 53 bit precision */ | |
251 | LRound_To_53: | |
252 | movl %esi,%ecx | |
253 | andl CW_RC,%ecx | |
254 | cmpl RC_RND,%ecx | |
255 | je LRound_nearest_53 | |
256 | ||
257 | cmpl RC_CHOP,%ecx | |
258 | je LCheck_truncate_53 | |
259 | ||
260 | cmpl RC_UP,%ecx /* Towards +infinity */ | |
261 | je LUp_53 | |
262 | ||
263 | cmpl RC_DOWN,%ecx /* Towards -infinity */ | |
264 | je LDown_53 | |
265 | ||
266 | #ifdef PARANOID | |
267 | jmp L_bugged_round53 | |
268 | #endif /* PARANOID */ | |
269 | ||
270 | LUp_53: | |
271 | cmpb SIGN_POS,PARAM5 | |
272 | jne LCheck_truncate_53 /* If negative then up==truncate */ | |
273 | ||
274 | jmp LCheck_53_round_up | |
275 | ||
276 | LDown_53: | |
277 | cmpb SIGN_POS,PARAM5 | |
278 | je LCheck_truncate_53 /* If positive then down==truncate */ | |
279 | ||
280 | LCheck_53_round_up: | |
281 | movl %ebx,%ecx | |
282 | andl $0x000007ff,%ecx | |
283 | orl %edx,%ecx | |
284 | jnz LDo_53_round_up | |
285 | jmp L_Re_normalise | |
286 | ||
287 | LRound_nearest_53: | |
288 | /* Do rounding of the 53rd bit if needed (nearest or even) */ | |
289 | movl %ebx,%ecx | |
290 | andl $0x000007ff,%ecx | |
291 | cmpl $0x00000400,%ecx | |
292 | jc LCheck_truncate_53 /* less than half, no increment needed */ | |
293 | ||
294 | jnz LGreater_Half_53 /* greater than half, increment needed */ | |
295 | ||
296 | /* Possibly half, we need to check the ls bits */ | |
297 | orl %edx,%edx | |
298 | jnz LGreater_Half_53 /* greater than half, increment needed */ | |
299 | ||
300 | /* Exactly half, increment only if 53rd bit is 1 (round to even) */ | |
301 | testl $0x00000800,%ebx | |
302 | jz LTruncate_53 | |
303 | ||
304 | LGreater_Half_53: /* Rounding: increment at the 53rd bit */ | |
305 | LDo_53_round_up: | |
306 | movb LOST_UP,FPU_bits_lost | |
307 | andl $0xfffff800,%ebx /* Truncate to 53 bits */ | |
308 | addl $0x00000800,%ebx | |
309 | adcl $0,%eax | |
310 | jmp LCheck_Round_Overflow | |
311 | ||
312 | LCheck_truncate_53: | |
313 | movl %ebx,%ecx | |
314 | andl $0x000007ff,%ecx | |
315 | orl %edx,%ecx | |
316 | jz L_Re_normalise | |
317 | ||
318 | LTruncate_53: | |
319 | movb LOST_DOWN,FPU_bits_lost | |
320 | andl $0xfffff800,%ebx /* Truncate to 53 bits */ | |
321 | jmp L_Re_normalise | |
322 | ||
323 | ||
324 | /* Round etc to 64 bit precision */ | |
325 | LRound_To_64: | |
326 | movl %esi,%ecx | |
327 | andl CW_RC,%ecx | |
328 | cmpl RC_RND,%ecx | |
329 | je LRound_nearest_64 | |
330 | ||
331 | cmpl RC_CHOP,%ecx | |
332 | je LCheck_truncate_64 | |
333 | ||
334 | cmpl RC_UP,%ecx /* Towards +infinity */ | |
335 | je LUp_64 | |
336 | ||
337 | cmpl RC_DOWN,%ecx /* Towards -infinity */ | |
338 | je LDown_64 | |
339 | ||
340 | #ifdef PARANOID | |
341 | jmp L_bugged_round64 | |
342 | #endif /* PARANOID */ | |
343 | ||
344 | LUp_64: | |
345 | cmpb SIGN_POS,PARAM5 | |
346 | jne LCheck_truncate_64 /* If negative then up==truncate */ | |
347 | ||
348 | orl %edx,%edx | |
349 | jnz LDo_64_round_up | |
350 | jmp L_Re_normalise | |
351 | ||
352 | LDown_64: | |
353 | cmpb SIGN_POS,PARAM5 | |
354 | je LCheck_truncate_64 /* If positive then down==truncate */ | |
355 | ||
356 | orl %edx,%edx | |
357 | jnz LDo_64_round_up | |
358 | jmp L_Re_normalise | |
359 | ||
360 | LRound_nearest_64: | |
361 | cmpl $0x80000000,%edx | |
362 | jc LCheck_truncate_64 | |
363 | ||
364 | jne LDo_64_round_up | |
365 | ||
366 | /* Now test for round-to-even */ | |
367 | testb $1,%bl | |
368 | jz LCheck_truncate_64 | |
369 | ||
370 | LDo_64_round_up: | |
371 | movb LOST_UP,FPU_bits_lost | |
372 | addl $1,%ebx | |
373 | adcl $0,%eax | |
374 | ||
375 | LCheck_Round_Overflow: | |
376 | jnc L_Re_normalise | |
377 | ||
378 | /* Overflow, adjust the result (significand to 1.0) */ | |
379 | rcrl $1,%eax | |
380 | rcrl $1,%ebx | |
381 | incw EXP(%edi) | |
382 | jmp L_Re_normalise | |
383 | ||
384 | LCheck_truncate_64: | |
385 | orl %edx,%edx | |
386 | jz L_Re_normalise | |
387 | ||
388 | LTruncate_64: | |
389 | movb LOST_DOWN,FPU_bits_lost | |
390 | ||
391 | L_Re_normalise: | |
392 | testb $0xff,FPU_denormal | |
393 | jnz Normalise_result | |
394 | ||
395 | L_Normalised: | |
396 | movl TAG_Valid,%edx | |
397 | ||
398 | L_deNormalised: | |
399 | cmpb LOST_UP,FPU_bits_lost | |
400 | je L_precision_lost_up | |
401 | ||
402 | cmpb LOST_DOWN,FPU_bits_lost | |
403 | je L_precision_lost_down | |
404 | ||
405 | L_no_precision_loss: | |
406 | /* store the result */ | |
407 | ||
408 | L_Store_significand: | |
409 | movl %eax,SIGH(%edi) | |
410 | movl %ebx,SIGL(%edi) | |
411 | ||
412 | cmpw EXP_OVER,EXP(%edi) | |
413 | jge L_overflow | |
414 | ||
415 | movl %edx,%eax | |
416 | ||
417 | /* Convert the exponent to 80x87 form. */ | |
418 | addw EXTENDED_Ebias,EXP(%edi) | |
419 | andw $0x7fff,EXP(%edi) | |
420 | ||
421 | fpu_reg_round_signed_special_exit: | |
422 | ||
423 | cmpb SIGN_POS,PARAM5 | |
424 | je fpu_reg_round_special_exit | |
425 | ||
426 | orw $0x8000,EXP(%edi) /* Negative sign for the result. */ | |
427 | ||
428 | fpu_reg_round_special_exit: | |
429 | ||
430 | #ifndef NON_REENTRANT_FPU | |
431 | popl %ebx /* adjust the stack pointer */ | |
432 | #endif /* NON_REENTRANT_FPU */ | |
433 | ||
434 | fpu_Arith_exit: | |
435 | popl %ebx | |
436 | popl %edi | |
437 | popl %esi | |
438 | leave | |
439 | ret | |
440 | ||
441 | ||
442 | /* | |
443 | * Set the FPU status flags to represent precision loss due to | |
444 | * round-up. | |
445 | */ | |
446 | L_precision_lost_up: | |
447 | push %edx | |
448 | push %eax | |
449 | call set_precision_flag_up | |
450 | popl %eax | |
451 | popl %edx | |
452 | jmp L_no_precision_loss | |
453 | ||
454 | /* | |
455 | * Set the FPU status flags to represent precision loss due to | |
456 | * truncation. | |
457 | */ | |
458 | L_precision_lost_down: | |
459 | push %edx | |
460 | push %eax | |
461 | call set_precision_flag_down | |
462 | popl %eax | |
463 | popl %edx | |
464 | jmp L_no_precision_loss | |
465 | ||
466 | ||
467 | /* | |
468 | * The number is a denormal (which might get rounded up to a normal) | |
469 | * Shift the number right the required number of bits, which will | |
470 | * have to be undone later... | |
471 | */ | |
472 | L_Make_denorm: | |
473 | /* The action to be taken depends upon whether the underflow | |
474 | exception is masked */ | |
475 | testb CW_Underflow,%cl /* Underflow mask. */ | |
476 | jz Unmasked_underflow /* Do not make a denormal. */ | |
477 | ||
478 | movb DENORMAL,FPU_denormal | |
479 | ||
480 | pushl %ecx /* Save */ | |
481 | movw EXP_UNDER+1,%cx | |
482 | subw EXP(%edi),%cx | |
483 | ||
484 | cmpw $64,%cx /* shrd only works for 0..31 bits */ | |
485 | jnc Denorm_shift_more_than_63 | |
486 | ||
487 | cmpw $32,%cx /* shrd only works for 0..31 bits */ | |
488 | jnc Denorm_shift_more_than_32 | |
489 | ||
490 | /* | |
491 | * We got here without jumps by assuming that the most common requirement | |
492 | * is for a small de-normalising shift. | |
493 | * Shift by [1..31] bits | |
494 | */ | |
495 | addw %cx,EXP(%edi) | |
496 | orl %edx,%edx /* extension */ | |
497 | setne %ch /* Save whether %edx is non-zero */ | |
498 | xorl %edx,%edx | |
499 | shrd %cl,%ebx,%edx | |
500 | shrd %cl,%eax,%ebx | |
501 | shr %cl,%eax | |
502 | orb %ch,%dl | |
503 | popl %ecx | |
504 | jmp Denorm_done | |
505 | ||
506 | /* Shift by [32..63] bits */ | |
507 | Denorm_shift_more_than_32: | |
508 | addw %cx,EXP(%edi) | |
509 | subb $32,%cl | |
510 | orl %edx,%edx | |
511 | setne %ch | |
512 | orb %ch,%bl | |
513 | xorl %edx,%edx | |
514 | shrd %cl,%ebx,%edx | |
515 | shrd %cl,%eax,%ebx | |
516 | shr %cl,%eax | |
517 | orl %edx,%edx /* test these 32 bits */ | |
518 | setne %cl | |
519 | orb %ch,%bl | |
520 | orb %cl,%bl | |
521 | movl %ebx,%edx | |
522 | movl %eax,%ebx | |
523 | xorl %eax,%eax | |
524 | popl %ecx | |
525 | jmp Denorm_done | |
526 | ||
527 | /* Shift by [64..) bits */ | |
528 | Denorm_shift_more_than_63: | |
529 | cmpw $64,%cx | |
530 | jne Denorm_shift_more_than_64 | |
531 | ||
532 | /* Exactly 64 bit shift */ | |
533 | addw %cx,EXP(%edi) | |
534 | xorl %ecx,%ecx | |
535 | orl %edx,%edx | |
536 | setne %cl | |
537 | orl %ebx,%ebx | |
538 | setne %ch | |
539 | orb %ch,%cl | |
540 | orb %cl,%al | |
541 | movl %eax,%edx | |
542 | xorl %eax,%eax | |
543 | xorl %ebx,%ebx | |
544 | popl %ecx | |
545 | jmp Denorm_done | |
546 | ||
547 | Denorm_shift_more_than_64: | |
548 | movw EXP_UNDER+1,EXP(%edi) | |
549 | /* This is easy, %eax must be non-zero, so.. */ | |
550 | movl $1,%edx | |
551 | xorl %eax,%eax | |
552 | xorl %ebx,%ebx | |
553 | popl %ecx | |
554 | jmp Denorm_done | |
555 | ||
556 | ||
557 | Unmasked_underflow: | |
558 | movb UNMASKED_UNDERFLOW,FPU_denormal | |
559 | jmp Denorm_done | |
560 | ||
561 | ||
562 | /* Undo the de-normalisation. */ | |
563 | Normalise_result: | |
564 | cmpb UNMASKED_UNDERFLOW,FPU_denormal | |
565 | je Signal_underflow | |
566 | ||
567 | /* The number must be a denormal if we got here. */ | |
568 | #ifdef PARANOID | |
569 | /* But check it... just in case. */ | |
570 | cmpw EXP_UNDER+1,EXP(%edi) | |
571 | jne L_norm_bugged | |
572 | #endif /* PARANOID */ | |
573 | ||
574 | #ifdef PECULIAR_486 | |
575 | /* | |
576 | * This implements a special feature of 80486 behaviour. | |
577 | * Underflow will be signalled even if the number is | |
578 | * not a denormal after rounding. | |
579 | * This difference occurs only for masked underflow, and not | |
580 | * in the unmasked case. | |
581 | * Actual 80486 behaviour differs from this in some circumstances. | |
582 | */ | |
583 | orl %eax,%eax /* ms bits */ | |
584 | js LPseudoDenormal /* Will be masked underflow */ | |
585 | #else | |
586 | orl %eax,%eax /* ms bits */ | |
587 | js L_Normalised /* No longer a denormal */ | |
588 | #endif /* PECULIAR_486 */ | |
589 | ||
590 | jnz LDenormal_adj_exponent | |
591 | ||
592 | orl %ebx,%ebx | |
593 | jz L_underflow_to_zero /* The contents are zero */ | |
594 | ||
595 | LDenormal_adj_exponent: | |
596 | decw EXP(%edi) | |
597 | ||
598 | LPseudoDenormal: | |
599 | testb $0xff,FPU_bits_lost /* bits lost == underflow */ | |
600 | movl TAG_Special,%edx | |
601 | jz L_deNormalised | |
602 | ||
603 | /* There must be a masked underflow */ | |
604 | push %eax | |
605 | pushl EX_Underflow | |
606 | call EXCEPTION | |
607 | popl %eax | |
608 | popl %eax | |
609 | movl TAG_Special,%edx | |
610 | jmp L_deNormalised | |
611 | ||
612 | ||
613 | /* | |
614 | * The operations resulted in a number too small to represent. | |
615 | * Masked response. | |
616 | */ | |
617 | L_underflow_to_zero: | |
618 | push %eax | |
619 | call set_precision_flag_down | |
620 | popl %eax | |
621 | ||
622 | push %eax | |
623 | pushl EX_Underflow | |
624 | call EXCEPTION | |
625 | popl %eax | |
626 | popl %eax | |
627 | ||
628 | /* Reduce the exponent to EXP_UNDER */ | |
629 | movw EXP_UNDER,EXP(%edi) | |
630 | movl TAG_Zero,%edx | |
631 | jmp L_Store_significand | |
632 | ||
633 | ||
634 | /* The operations resulted in a number too large to represent. */ | |
635 | L_overflow: | |
636 | addw EXTENDED_Ebias,EXP(%edi) /* Set for unmasked response. */ | |
637 | push %edi | |
638 | call arith_overflow | |
639 | pop %edi | |
640 | jmp fpu_reg_round_signed_special_exit | |
641 | ||
642 | ||
643 | Signal_underflow: | |
644 | /* The number may have been changed to a non-denormal */ | |
645 | /* by the rounding operations. */ | |
646 | cmpw EXP_UNDER,EXP(%edi) | |
647 | jle Do_unmasked_underflow | |
648 | ||
649 | jmp L_Normalised | |
650 | ||
651 | Do_unmasked_underflow: | |
652 | /* Increase the exponent by the magic number */ | |
653 | addw $(3*(1<<13)),EXP(%edi) | |
654 | push %eax | |
655 | pushl EX_Underflow | |
656 | call EXCEPTION | |
657 | popl %eax | |
658 | popl %eax | |
659 | jmp L_Normalised | |
660 | ||
661 | ||
662 | #ifdef PARANOID | |
663 | #ifdef PECULIAR_486 | |
664 | L_bugged_denorm_486: | |
665 | pushl EX_INTERNAL|0x236 | |
666 | call EXCEPTION | |
667 | popl %ebx | |
668 | jmp L_exception_exit | |
669 | #else | |
670 | L_bugged_denorm: | |
671 | pushl EX_INTERNAL|0x230 | |
672 | call EXCEPTION | |
673 | popl %ebx | |
674 | jmp L_exception_exit | |
675 | #endif /* PECULIAR_486 */ | |
676 | ||
677 | L_bugged_round24: | |
678 | pushl EX_INTERNAL|0x231 | |
679 | call EXCEPTION | |
680 | popl %ebx | |
681 | jmp L_exception_exit | |
682 | ||
683 | L_bugged_round53: | |
684 | pushl EX_INTERNAL|0x232 | |
685 | call EXCEPTION | |
686 | popl %ebx | |
687 | jmp L_exception_exit | |
688 | ||
689 | L_bugged_round64: | |
690 | pushl EX_INTERNAL|0x233 | |
691 | call EXCEPTION | |
692 | popl %ebx | |
693 | jmp L_exception_exit | |
694 | ||
695 | L_norm_bugged: | |
696 | pushl EX_INTERNAL|0x234 | |
697 | call EXCEPTION | |
698 | popl %ebx | |
699 | jmp L_exception_exit | |
700 | ||
701 | L_entry_bugged: | |
702 | pushl EX_INTERNAL|0x235 | |
703 | call EXCEPTION | |
704 | popl %ebx | |
705 | L_exception_exit: | |
706 | mov $-1,%eax | |
707 | jmp fpu_reg_round_special_exit | |
708 | #endif /* PARANOID */ |