1 .file "reg_round.S"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 #include "fpu_asm.h"
73 #include "exception.h"
74 #include "control_w.h"
75
76
77 #define LOST_DOWN $1
78 #define LOST_UP $2
79
80
81 #define DENORMAL $1
82 #define UNMASKED_UNDERFLOW $2
83
84
85 #ifndef NON_REENTRANT_FPU
86
87
88 #define FPU_bits_lost (%esp)
89 #define FPU_denormal 1(%esp)
90
91 #else
92
93
94 .data
95 .align 2,0
96 FPU_bits_lost:
97 .byte 0
98 FPU_denormal:
99 .byte 0
100 #endif NON_REENTRANT_FPU
101
102
103 .text
104 .globl fpu_reg_round
105 .globl fpu_reg_round_sqrt
106 .globl fpu_Arith_exit
107
108
109 ENTRY(round_reg)
110 pushl %ebp
111 movl %esp,%ebp
112 pushl %esi
113 pushl %edi
114 pushl %ebx
115
116 movl PARAM1,%edi
117 movl SIGH(%edi),%eax
118 movl SIGL(%edi),%ebx
119 movl PARAM2,%edx
120 movl PARAM3,%ecx
121 jmp fpu_reg_round_sqrt
122
123 fpu_reg_round:
124 movl PARAM4,%ecx
125
126 fpu_reg_round_sqrt:
127
128 #ifndef NON_REENTRANT_FPU
129 pushl %ebx
130 #endif NON_REENTRANT_FPU
131
132 #ifdef PARANOID
133
134
135
136 #endif PARANOID
137
138 cmpl EXP_UNDER,EXP(%edi)
139 jle xMake_denorm
140
141 movb $0,FPU_denormal
142
143 xDenorm_done:
144 movb $0,FPU_bits_lost
145
146 movl %ecx,%esi
147 andl CW_PC,%ecx
148 cmpl PR_64_BITS,%ecx
149 je LRound_To_64
150
151 cmpl PR_53_BITS,%ecx
152 je LRound_To_53
153
154 cmpl PR_24_BITS,%ecx
155 je LRound_To_24
156
157 #ifdef PECULIAR_486
158
159
160 cmpl PR_RESERVED_BITS,%ecx
161 je LRound_To_64
162 #ifdef PARANOID
163 jmp L_bugged_denorm_486
164 #endif PARANOID
165 #else
166 #ifdef PARANOID
167 jmp L_bugged_denorm
168 #endif PARANOID
169 #endif PECULIAR_486
170
171
172
173 LRound_To_24:
174 movl %esi,%ecx
175 andl CW_RC,%ecx
176 cmpl RC_RND,%ecx
177 je LRound_nearest_24
178
179 cmpl RC_CHOP,%ecx
180 je LCheck_truncate_24
181
182 cmpl RC_UP,%ecx
183 je LUp_24
184
185 cmpl RC_DOWN,%ecx
186 je LDown_24
187
188 #ifdef PARANOID
189 jmp L_bugged_round24
190 #endif PARANOID
191
192 LUp_24:
193 cmpb SIGN_POS,SIGN(%edi)
194 jne LCheck_truncate_24
195
196 jmp LCheck_24_round_up
197
198 LDown_24:
199 cmpb SIGN_POS,SIGN(%edi)
200 je LCheck_truncate_24
201
202 LCheck_24_round_up:
203 movl %eax,%ecx
204 andl $0x000000ff,%ecx
205 orl %ebx,%ecx
206 orl %edx,%ecx
207 jnz LDo_24_round_up
208 jmp LRe_normalise
209
210 LRound_nearest_24:
211
212 movl %eax,%ecx
213 andl $0x000000ff,%ecx
214 cmpl $0x00000080,%ecx
215 jc LCheck_truncate_24
216
217 jne LGreater_Half_24
218
219
220 orl %ebx,%ebx
221 jnz LGreater_Half_24
222
223 orl %edx,%edx
224 jnz LGreater_Half_24
225
226
227 testl $0x00000100,%eax
228 jz LDo_truncate_24
229
230 LGreater_Half_24:
231 LDo_24_round_up:
232 andl $0xffffff00,%eax
233 xorl %ebx,%ebx
234 movb LOST_UP,FPU_bits_lost
235 addl $0x00000100,%eax
236 jmp LCheck_Round_Overflow
237
238 LCheck_truncate_24:
239 movl %eax,%ecx
240 andl $0x000000ff,%ecx
241 orl %ebx,%ecx
242 orl %edx,%ecx
243 jz LRe_normalise
244
245 LDo_truncate_24:
246 andl $0xffffff00,%eax
247 xorl %ebx,%ebx
248 movb LOST_DOWN,FPU_bits_lost
249 jmp LRe_normalise
250
251
252
253 LRound_To_53:
254 movl %esi,%ecx
255 andl CW_RC,%ecx
256 cmpl RC_RND,%ecx
257 je LRound_nearest_53
258
259 cmpl RC_CHOP,%ecx
260 je LCheck_truncate_53
261
262 cmpl RC_UP,%ecx
263 je LUp_53
264
265 cmpl RC_DOWN,%ecx
266 je LDown_53
267
268 #ifdef PARANOID
269 jmp L_bugged_round53
270 #endif PARANOID
271
272 LUp_53:
273 cmpb SIGN_POS,SIGN(%edi)
274 jne LCheck_truncate_53
275
276 jmp LCheck_53_round_up
277
278 LDown_53:
279 cmpb SIGN_POS,SIGN(%edi)
280 je LCheck_truncate_53
281
282 LCheck_53_round_up:
283 movl %ebx,%ecx
284 andl $0x000007ff,%ecx
285 orl %edx,%ecx
286 jnz LDo_53_round_up
287 jmp LRe_normalise
288
289 LRound_nearest_53:
290
291 movl %ebx,%ecx
292 andl $0x000007ff,%ecx
293 cmpl $0x00000400,%ecx
294 jc LCheck_truncate_53
295
296 jnz LGreater_Half_53
297
298
299 orl %edx,%edx
300 jnz LGreater_Half_53
301
302
303 testl $0x00000800,%ebx
304 jz LTruncate_53
305
306 LGreater_Half_53:
307 LDo_53_round_up:
308 movb LOST_UP,FPU_bits_lost
309 andl $0xfffff800,%ebx
310 addl $0x00000800,%ebx
311 adcl $0,%eax
312 jmp LCheck_Round_Overflow
313
314 LCheck_truncate_53:
315 movl %ebx,%ecx
316 andl $0x000007ff,%ecx
317 orl %edx,%ecx
318 jz LRe_normalise
319
320 LTruncate_53:
321 movb LOST_DOWN,FPU_bits_lost
322 andl $0xfffff800,%ebx
323 jmp LRe_normalise
324
325
326
327 LRound_To_64:
328 movl %esi,%ecx
329 andl CW_RC,%ecx
330 cmpl RC_RND,%ecx
331 je LRound_nearest_64
332
333 cmpl RC_CHOP,%ecx
334 je LCheck_truncate_64
335
336 cmpl RC_UP,%ecx
337 je LUp_64
338
339 cmpl RC_DOWN,%ecx
340 je LDown_64
341
342 #ifdef PARANOID
343 jmp L_bugged_round64
344 #endif PARANOID
345
346 LUp_64:
347 cmpb SIGN_POS,SIGN(%edi)
348 jne LCheck_truncate_64
349
350 orl %edx,%edx
351 jnz LDo_64_round_up
352 jmp LRe_normalise
353
354 LDown_64:
355 cmpb SIGN_POS,SIGN(%edi)
356 je LCheck_truncate_64
357
358 orl %edx,%edx
359 jnz LDo_64_round_up
360 jmp LRe_normalise
361
362 LRound_nearest_64:
363 cmpl $0x80000000,%edx
364 jc LCheck_truncate_64
365
366 jne LDo_64_round_up
367
368
369 testb $1,%ebx
370 jz LCheck_truncate_64
371
372 LDo_64_round_up:
373 movb LOST_UP,FPU_bits_lost
374 addl $1,%ebx
375 adcl $0,%eax
376
377 LCheck_Round_Overflow:
378 jnc LRe_normalise
379
380
381 rcrl $1,%eax
382 rcrl $1,%ebx
383 incl EXP(%edi)
384 jmp LRe_normalise
385
386 LCheck_truncate_64:
387 orl %edx,%edx
388 jz LRe_normalise
389
390 LTruncate_64:
391 movb LOST_DOWN,FPU_bits_lost
392
393 LRe_normalise:
394 testb $0xff,FPU_denormal
395 jnz xNormalise_result
396
397 xL_Normalised:
398 cmpb LOST_UP,FPU_bits_lost
399 je xL_precision_lost_up
400
401 cmpb LOST_DOWN,FPU_bits_lost
402 je xL_precision_lost_down
403
404 xL_no_precision_loss:
405
406 movb TW_Valid,TAG(%edi)
407
408 xL_Store_significand:
409 movl %eax,SIGH(%edi)
410 movl %ebx,SIGL(%edi)
411
412 xorl %eax,%eax
413
414 cmpl EXP_OVER,EXP(%edi)
415 jge L_overflow
416
417 fpu_reg_round_exit:
418 #ifndef NON_REENTRANT_FPU
419 popl %ebx
420 #endif NON_REENTRANT_FPU
421
422 fpu_Arith_exit:
423 popl %ebx
424 popl %edi
425 popl %esi
426 leave
427 ret
428
429
430
431
432
433
434 xL_precision_lost_up:
435 push %eax
436 call SYMBOL_NAME(set_precision_flag_up)
437 popl %eax
438 jmp xL_no_precision_loss
439
440
441
442
443
444 xL_precision_lost_down:
445 push %eax
446 call SYMBOL_NAME(set_precision_flag_down)
447 popl %eax
448 jmp xL_no_precision_loss
449
450
451
452
453
454
455
456 xMake_denorm:
457
458
459 testb CW_Underflow,%cl
460 jz xUnmasked_underflow
461
462 movb DENORMAL,FPU_denormal
463
464 pushl %ecx
465 movl EXP_UNDER+1,%ecx
466 subl EXP(%edi),%ecx
467
468 cmpl $64,%ecx
469 jnc xDenorm_shift_more_than_63
470
471 cmpl $32,%ecx
472 jnc xDenorm_shift_more_than_32
473
474
475
476
477
478
479 addl %ecx,EXP(%edi)
480 orl %edx,%edx
481 setne %ch
482 xorl %edx,%edx
483 shrd %cl,%ebx,%edx
484 shrd %cl,%eax,%ebx
485 shr %cl,%eax
486 orb %ch,%dl
487 popl %ecx
488 jmp xDenorm_done
489
490
491 xDenorm_shift_more_than_32:
492 addl %ecx,EXP(%edi)
493 subb $32,%cl
494 orl %edx,%edx
495 setne %ch
496 orb %ch,%bl
497 xorl %edx,%edx
498 shrd %cl,%ebx,%edx
499 shrd %cl,%eax,%ebx
500 shr %cl,%eax
501 orl %edx,%edx
502 setne %cl
503 orb %ch,%bl
504 orb %cl,%bl
505 movl %ebx,%edx
506 movl %eax,%ebx
507 xorl %eax,%eax
508 popl %ecx
509 jmp xDenorm_done
510
511
512 xDenorm_shift_more_than_63:
513 cmpl $64,%ecx
514 jne xDenorm_shift_more_than_64
515
516
517 addl %ecx,EXP(%edi)
518 xorl %ecx,%ecx
519 orl %edx,%edx
520 setne %cl
521 orl %ebx,%ebx
522 setne %ch
523 orb %ch,%cl
524 orb %cl,%al
525 movl %eax,%edx
526 xorl %eax,%eax
527 xorl %ebx,%ebx
528 popl %ecx
529 jmp xDenorm_done
530
531 xDenorm_shift_more_than_64:
532 movl EXP_UNDER+1,EXP(%edi)
533
534 movl $1,%edx
535 xorl %eax,%eax
536 xorl %ebx,%ebx
537 popl %ecx
538 jmp xDenorm_done
539
540
541 xUnmasked_underflow:
542 movb UNMASKED_UNDERFLOW,FPU_denormal
543 jmp xDenorm_done
544
545
546
547 xNormalise_result:
548 cmpb UNMASKED_UNDERFLOW,FPU_denormal
549 je xSignal_underflow
550
551
552 #ifdef PARANOID
553
554 cmpl EXP_UNDER+1,EXP(%edi)
555 jne L_norm_bugged
556 #endif PARANOID
557
558 #ifdef PECULIAR_486
559
560
561
562
563
564
565
566
567 orl %eax,%eax
568 js LNormalise_shift_done
569 #endif PECULIAR_486
570
571 orl %eax,%eax
572 js xL_Normalised
573
574 jnz LNormalise_shift_up_to_31
575
576 orl %ebx,%ebx
577 jz L_underflow_to_zero
578
579
580 movl %ebx,%eax
581 xorl %ebx,%ebx
582 subl $32,EXP(%edi)
583
584 LNormalise_shift_up_to_31:
585 bsrl %eax,%ecx
586 subl $31,%ecx
587 negl %ecx
588 shld %cl,%ebx,%eax
589 shl %cl,%ebx
590 subl %ecx,EXP(%edi)
591
592 LNormalise_shift_done:
593 testb $0xff,FPU_bits_lost
594 jz xL_Normalised
595
596
597 push %eax
598 pushl EX_Underflow
599 call SYMBOL_NAME(exception)
600 popl %eax
601 popl %eax
602 jmp xL_Normalised
603
604
605
606
607
608
609 L_underflow_to_zero:
610 push %eax
611 call SYMBOL_NAME(set_precision_flag_down)
612 popl %eax
613
614 push %eax
615 pushl EX_Underflow
616 call SYMBOL_NAME(exception)
617 popl %eax
618 popl %eax
619
620
621 movl EXP_UNDER,EXP(%edi)
622 movb TW_Zero,TAG(%edi)
623 jmp xL_Store_significand
624
625
626
627 L_overflow:
628 push %edi
629 call SYMBOL_NAME(arith_overflow)
630 pop %edi
631 jmp fpu_reg_round_exit
632
633
634 xSignal_underflow:
635
636
637 cmpl EXP_UNDER,EXP(%edi)
638 jle xDo_unmasked_underflow
639
640 jmp xL_Normalised
641
642 xDo_unmasked_underflow:
643
644 addl $(3*(1<<13)),EXP(%edi)
645 push %eax
646 pushl EX_Underflow
647 call EXCEPTION
648 popl %eax
649 popl %eax
650 jmp xL_Normalised
651
652
653 #ifdef PARANOID
654 #ifdef PECULIAR_486
655 L_bugged_denorm_486:
656 pushl EX_INTERNAL|0x236
657 call EXCEPTION
658 popl %ebx
659 jmp L_exception_exit
660 #else
661 L_bugged_denorm:
662 pushl EX_INTERNAL|0x230
663 call EXCEPTION
664 popl %ebx
665 jmp L_exception_exit
666 #endif PECULIAR_486
667
668 L_bugged_round24:
669 pushl EX_INTERNAL|0x231
670 call EXCEPTION
671 popl %ebx
672 jmp L_exception_exit
673
674 L_bugged_round53:
675 pushl EX_INTERNAL|0x232
676 call EXCEPTION
677 popl %ebx
678 jmp L_exception_exit
679
680 L_bugged_round64:
681 pushl EX_INTERNAL|0x233
682 call EXCEPTION
683 popl %ebx
684 jmp L_exception_exit
685
686 L_norm_bugged:
687 pushl EX_INTERNAL|0x234
688 call EXCEPTION
689 popl %ebx
690 jmp L_exception_exit
691
692 L_entry_bugged:
693 pushl EX_INTERNAL|0x235
694 call EXCEPTION
695 popl %ebx
696 L_exception_exit:
697 mov $1,%eax
698 jmp fpu_reg_round_exit
699 #endif PARANOID