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