0001
0002 .file "reg_round.S"
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 #include "fpu_emu.h"
0077 #include "exception.h"
0078 #include "control_w.h"
0079
0080
0081 #define LOST_DOWN $1
0082 #define LOST_UP $2
0083
0084
0085 #define DENORMAL $1
0086 #define UNMASKED_UNDERFLOW $2
0087
0088
0089 #ifndef NON_REENTRANT_FPU
0090
0091
0092 #define FPU_bits_lost (%esp)
0093 #define FPU_denormal 1(%esp)
0094
0095 #else
0096
0097
0098 .data
0099 .align 4,0
0100 FPU_bits_lost:
0101 .byte 0
0102 FPU_denormal:
0103 .byte 0
0104 #endif
0105
0106
0107 .text
0108 .globl fpu_reg_round
0109 .globl fpu_Arith_exit
0110
0111
0112 SYM_FUNC_START(FPU_round)
0113 pushl %ebp
0114 movl %esp,%ebp
0115 pushl %esi
0116 pushl %edi
0117 pushl %ebx
0118
0119 movl PARAM1,%edi
0120 movl SIGH(%edi),%eax
0121 movl SIGL(%edi),%ebx
0122 movl PARAM2,%edx
0123
0124 fpu_reg_round:
0125 movl PARAM4,%ecx
0126
0127 #ifndef NON_REENTRANT_FPU
0128 pushl %ebx
0129 #endif
0130
0131 #ifdef PARANOID
0132
0133
0134
0135 #endif
0136
0137 cmpw EXP_UNDER,EXP(%edi)
0138 jle L_Make_denorm
0139
0140 movb $0,FPU_denormal
0141
0142 Denorm_done:
0143 movb $0,FPU_bits_lost
0144
0145 movl %ecx,%esi
0146 andl CW_PC,%ecx
0147 cmpl PR_64_BITS,%ecx
0148 je LRound_To_64
0149
0150 cmpl PR_53_BITS,%ecx
0151 je LRound_To_53
0152
0153 cmpl PR_24_BITS,%ecx
0154 je LRound_To_24
0155
0156 #ifdef PECULIAR_486
0157
0158
0159 cmpl PR_RESERVED_BITS,%ecx
0160 je LRound_To_64
0161 #ifdef PARANOID
0162 jmp L_bugged_denorm_486
0163 #endif
0164 #else
0165 #ifdef PARANOID
0166 jmp L_bugged_denorm
0167 #endif
0168 #endif
0169
0170
0171
0172 LRound_To_24:
0173 movl %esi,%ecx
0174 andl CW_RC,%ecx
0175 cmpl RC_RND,%ecx
0176 je LRound_nearest_24
0177
0178 cmpl RC_CHOP,%ecx
0179 je LCheck_truncate_24
0180
0181 cmpl RC_UP,%ecx
0182 je LUp_24
0183
0184 cmpl RC_DOWN,%ecx
0185 je LDown_24
0186
0187 #ifdef PARANOID
0188 jmp L_bugged_round24
0189 #endif
0190
0191 LUp_24:
0192 cmpb SIGN_POS,PARAM5
0193 jne LCheck_truncate_24
0194
0195 jmp LCheck_24_round_up
0196
0197 LDown_24:
0198 cmpb SIGN_POS,PARAM5
0199 je LCheck_truncate_24
0200
0201 LCheck_24_round_up:
0202 movl %eax,%ecx
0203 andl $0x000000ff,%ecx
0204 orl %ebx,%ecx
0205 orl %edx,%ecx
0206 jnz LDo_24_round_up
0207 jmp L_Re_normalise
0208
0209 LRound_nearest_24:
0210
0211 movl %eax,%ecx
0212 andl $0x000000ff,%ecx
0213 cmpl $0x00000080,%ecx
0214 jc LCheck_truncate_24
0215
0216 jne LGreater_Half_24
0217
0218
0219 orl %ebx,%ebx
0220 jnz LGreater_Half_24
0221
0222 orl %edx,%edx
0223 jnz LGreater_Half_24
0224
0225
0226 testl $0x00000100,%eax
0227 jz LDo_truncate_24
0228
0229 LGreater_Half_24:
0230 LDo_24_round_up:
0231 andl $0xffffff00,%eax
0232 xorl %ebx,%ebx
0233 movb LOST_UP,FPU_bits_lost
0234 addl $0x00000100,%eax
0235 jmp LCheck_Round_Overflow
0236
0237 LCheck_truncate_24:
0238 movl %eax,%ecx
0239 andl $0x000000ff,%ecx
0240 orl %ebx,%ecx
0241 orl %edx,%ecx
0242 jz L_Re_normalise
0243
0244 LDo_truncate_24:
0245 andl $0xffffff00,%eax
0246 xorl %ebx,%ebx
0247 movb LOST_DOWN,FPU_bits_lost
0248 jmp L_Re_normalise
0249
0250
0251
0252 LRound_To_53:
0253 movl %esi,%ecx
0254 andl CW_RC,%ecx
0255 cmpl RC_RND,%ecx
0256 je LRound_nearest_53
0257
0258 cmpl RC_CHOP,%ecx
0259 je LCheck_truncate_53
0260
0261 cmpl RC_UP,%ecx
0262 je LUp_53
0263
0264 cmpl RC_DOWN,%ecx
0265 je LDown_53
0266
0267 #ifdef PARANOID
0268 jmp L_bugged_round53
0269 #endif
0270
0271 LUp_53:
0272 cmpb SIGN_POS,PARAM5
0273 jne LCheck_truncate_53
0274
0275 jmp LCheck_53_round_up
0276
0277 LDown_53:
0278 cmpb SIGN_POS,PARAM5
0279 je LCheck_truncate_53
0280
0281 LCheck_53_round_up:
0282 movl %ebx,%ecx
0283 andl $0x000007ff,%ecx
0284 orl %edx,%ecx
0285 jnz LDo_53_round_up
0286 jmp L_Re_normalise
0287
0288 LRound_nearest_53:
0289
0290 movl %ebx,%ecx
0291 andl $0x000007ff,%ecx
0292 cmpl $0x00000400,%ecx
0293 jc LCheck_truncate_53
0294
0295 jnz LGreater_Half_53
0296
0297
0298 orl %edx,%edx
0299 jnz LGreater_Half_53
0300
0301
0302 testl $0x00000800,%ebx
0303 jz LTruncate_53
0304
0305 LGreater_Half_53:
0306 LDo_53_round_up:
0307 movb LOST_UP,FPU_bits_lost
0308 andl $0xfffff800,%ebx
0309 addl $0x00000800,%ebx
0310 adcl $0,%eax
0311 jmp LCheck_Round_Overflow
0312
0313 LCheck_truncate_53:
0314 movl %ebx,%ecx
0315 andl $0x000007ff,%ecx
0316 orl %edx,%ecx
0317 jz L_Re_normalise
0318
0319 LTruncate_53:
0320 movb LOST_DOWN,FPU_bits_lost
0321 andl $0xfffff800,%ebx
0322 jmp L_Re_normalise
0323
0324
0325
0326 LRound_To_64:
0327 movl %esi,%ecx
0328 andl CW_RC,%ecx
0329 cmpl RC_RND,%ecx
0330 je LRound_nearest_64
0331
0332 cmpl RC_CHOP,%ecx
0333 je LCheck_truncate_64
0334
0335 cmpl RC_UP,%ecx
0336 je LUp_64
0337
0338 cmpl RC_DOWN,%ecx
0339 je LDown_64
0340
0341 #ifdef PARANOID
0342 jmp L_bugged_round64
0343 #endif
0344
0345 LUp_64:
0346 cmpb SIGN_POS,PARAM5
0347 jne LCheck_truncate_64
0348
0349 orl %edx,%edx
0350 jnz LDo_64_round_up
0351 jmp L_Re_normalise
0352
0353 LDown_64:
0354 cmpb SIGN_POS,PARAM5
0355 je LCheck_truncate_64
0356
0357 orl %edx,%edx
0358 jnz LDo_64_round_up
0359 jmp L_Re_normalise
0360
0361 LRound_nearest_64:
0362 cmpl $0x80000000,%edx
0363 jc LCheck_truncate_64
0364
0365 jne LDo_64_round_up
0366
0367
0368 testb $1,%bl
0369 jz LCheck_truncate_64
0370
0371 LDo_64_round_up:
0372 movb LOST_UP,FPU_bits_lost
0373 addl $1,%ebx
0374 adcl $0,%eax
0375
0376 LCheck_Round_Overflow:
0377 jnc L_Re_normalise
0378
0379
0380 rcrl $1,%eax
0381 rcrl $1,%ebx
0382 incw EXP(%edi)
0383 jmp L_Re_normalise
0384
0385 LCheck_truncate_64:
0386 orl %edx,%edx
0387 jz L_Re_normalise
0388
0389 LTruncate_64:
0390 movb LOST_DOWN,FPU_bits_lost
0391
0392 L_Re_normalise:
0393 testb $0xff,FPU_denormal
0394 jnz Normalise_result
0395
0396 L_Normalised:
0397 movl TAG_Valid,%edx
0398
0399 L_deNormalised:
0400 cmpb LOST_UP,FPU_bits_lost
0401 je L_precision_lost_up
0402
0403 cmpb LOST_DOWN,FPU_bits_lost
0404 je L_precision_lost_down
0405
0406 L_no_precision_loss:
0407
0408
0409 L_Store_significand:
0410 movl %eax,SIGH(%edi)
0411 movl %ebx,SIGL(%edi)
0412
0413 cmpw EXP_OVER,EXP(%edi)
0414 jge L_overflow
0415
0416 movl %edx,%eax
0417
0418
0419 addw EXTENDED_Ebias,EXP(%edi)
0420 andw $0x7fff,EXP(%edi)
0421
0422 fpu_reg_round_signed_special_exit:
0423
0424 cmpb SIGN_POS,PARAM5
0425 je fpu_reg_round_special_exit
0426
0427 orw $0x8000,EXP(%edi)
0428
0429 fpu_reg_round_special_exit:
0430
0431 #ifndef NON_REENTRANT_FPU
0432 popl %ebx
0433 #endif
0434
0435 fpu_Arith_exit:
0436 popl %ebx
0437 popl %edi
0438 popl %esi
0439 leave
0440 RET
0441
0442
0443
0444
0445
0446
0447 L_precision_lost_up:
0448 push %edx
0449 push %eax
0450 call set_precision_flag_up
0451 popl %eax
0452 popl %edx
0453 jmp L_no_precision_loss
0454
0455
0456
0457
0458
0459 L_precision_lost_down:
0460 push %edx
0461 push %eax
0462 call set_precision_flag_down
0463 popl %eax
0464 popl %edx
0465 jmp L_no_precision_loss
0466
0467
0468
0469
0470
0471
0472
0473 L_Make_denorm:
0474
0475
0476 testb CW_Underflow,%cl
0477 jz Unmasked_underflow
0478
0479 movb DENORMAL,FPU_denormal
0480
0481 pushl %ecx
0482 movw EXP_UNDER+1,%cx
0483 subw EXP(%edi),%cx
0484
0485 cmpw $64,%cx
0486 jnc Denorm_shift_more_than_63
0487
0488 cmpw $32,%cx
0489 jnc Denorm_shift_more_than_32
0490
0491
0492
0493
0494
0495
0496 addw %cx,EXP(%edi)
0497 orl %edx,%edx
0498 setne %ch
0499 xorl %edx,%edx
0500 shrd %cl,%ebx,%edx
0501 shrd %cl,%eax,%ebx
0502 shr %cl,%eax
0503 orb %ch,%dl
0504 popl %ecx
0505 jmp Denorm_done
0506
0507
0508 Denorm_shift_more_than_32:
0509 addw %cx,EXP(%edi)
0510 subb $32,%cl
0511 orl %edx,%edx
0512 setne %ch
0513 orb %ch,%bl
0514 xorl %edx,%edx
0515 shrd %cl,%ebx,%edx
0516 shrd %cl,%eax,%ebx
0517 shr %cl,%eax
0518 orl %edx,%edx
0519 setne %cl
0520 orb %ch,%bl
0521 orb %cl,%bl
0522 movl %ebx,%edx
0523 movl %eax,%ebx
0524 xorl %eax,%eax
0525 popl %ecx
0526 jmp Denorm_done
0527
0528
0529 Denorm_shift_more_than_63:
0530 cmpw $64,%cx
0531 jne Denorm_shift_more_than_64
0532
0533
0534 addw %cx,EXP(%edi)
0535 xorl %ecx,%ecx
0536 orl %edx,%edx
0537 setne %cl
0538 orl %ebx,%ebx
0539 setne %ch
0540 orb %ch,%cl
0541 orb %cl,%al
0542 movl %eax,%edx
0543 xorl %eax,%eax
0544 xorl %ebx,%ebx
0545 popl %ecx
0546 jmp Denorm_done
0547
0548 Denorm_shift_more_than_64:
0549 movw EXP_UNDER+1,EXP(%edi)
0550
0551 movl $1,%edx
0552 xorl %eax,%eax
0553 xorl %ebx,%ebx
0554 popl %ecx
0555 jmp Denorm_done
0556
0557
0558 Unmasked_underflow:
0559 movb UNMASKED_UNDERFLOW,FPU_denormal
0560 jmp Denorm_done
0561
0562
0563
0564 Normalise_result:
0565 cmpb UNMASKED_UNDERFLOW,FPU_denormal
0566 je Signal_underflow
0567
0568
0569 #ifdef PARANOID
0570
0571 cmpw EXP_UNDER+1,EXP(%edi)
0572 jne L_norm_bugged
0573 #endif
0574
0575 #ifdef PECULIAR_486
0576
0577
0578
0579
0580
0581
0582
0583
0584 orl %eax,%eax
0585 js LPseudoDenormal
0586 #else
0587 orl %eax,%eax
0588 js L_Normalised
0589 #endif
0590
0591 jnz LDenormal_adj_exponent
0592
0593 orl %ebx,%ebx
0594 jz L_underflow_to_zero
0595
0596 LDenormal_adj_exponent:
0597 decw EXP(%edi)
0598
0599 LPseudoDenormal:
0600 testb $0xff,FPU_bits_lost
0601 movl TAG_Special,%edx
0602 jz L_deNormalised
0603
0604
0605 push %eax
0606 pushl EX_Underflow
0607 call EXCEPTION
0608 popl %eax
0609 popl %eax
0610 movl TAG_Special,%edx
0611 jmp L_deNormalised
0612
0613
0614
0615
0616
0617
0618 L_underflow_to_zero:
0619 push %eax
0620 call set_precision_flag_down
0621 popl %eax
0622
0623 push %eax
0624 pushl EX_Underflow
0625 call EXCEPTION
0626 popl %eax
0627 popl %eax
0628
0629
0630 movw EXP_UNDER,EXP(%edi)
0631 movl TAG_Zero,%edx
0632 jmp L_Store_significand
0633
0634
0635
0636 L_overflow:
0637 addw EXTENDED_Ebias,EXP(%edi)
0638 push %edi
0639 call arith_overflow
0640 pop %edi
0641 jmp fpu_reg_round_signed_special_exit
0642
0643
0644 Signal_underflow:
0645
0646
0647 cmpw EXP_UNDER,EXP(%edi)
0648 jle Do_unmasked_underflow
0649
0650 jmp L_Normalised
0651
0652 Do_unmasked_underflow:
0653
0654 addw $(3*(1<<13)),EXP(%edi)
0655 push %eax
0656 pushl EX_Underflow
0657 call EXCEPTION
0658 popl %eax
0659 popl %eax
0660 jmp L_Normalised
0661
0662
0663 #ifdef PARANOID
0664 #ifdef PECULIAR_486
0665 L_bugged_denorm_486:
0666 pushl EX_INTERNAL|0x236
0667 call EXCEPTION
0668 popl %ebx
0669 jmp L_exception_exit
0670 #else
0671 L_bugged_denorm:
0672 pushl EX_INTERNAL|0x230
0673 call EXCEPTION
0674 popl %ebx
0675 jmp L_exception_exit
0676 #endif
0677
0678 L_bugged_round24:
0679 pushl EX_INTERNAL|0x231
0680 call EXCEPTION
0681 popl %ebx
0682 jmp L_exception_exit
0683
0684 L_bugged_round53:
0685 pushl EX_INTERNAL|0x232
0686 call EXCEPTION
0687 popl %ebx
0688 jmp L_exception_exit
0689
0690 L_bugged_round64:
0691 pushl EX_INTERNAL|0x233
0692 call EXCEPTION
0693 popl %ebx
0694 jmp L_exception_exit
0695
0696 L_norm_bugged:
0697 pushl EX_INTERNAL|0x234
0698 call EXCEPTION
0699 popl %ebx
0700 jmp L_exception_exit
0701
0702 L_entry_bugged:
0703 pushl EX_INTERNAL|0x235
0704 call EXCEPTION
0705 popl %ebx
0706 L_exception_exit:
0707 mov $-1,%eax
0708 jmp fpu_reg_round_special_exit
0709 #endif
0710
0711 SYM_FUNC_END(FPU_round)