📄 reg_round.s
字号:
orl %edx,%edx jnz LDo_64_round_up jmp L_Re_normaliseLRound_nearest_64: cmpl $0x80000000,%edx jc LCheck_truncate_64 jne LDo_64_round_up /* Now test for round-to-even */ testb $1,%bl jz LCheck_truncate_64LDo_64_round_up: movb LOST_UP,FPU_bits_lost addl $1,%ebx adcl $0,%eaxLCheck_Round_Overflow: jnc L_Re_normalise /* Overflow, adjust the result (significand to 1.0) */ rcrl $1,%eax rcrl $1,%ebx incw EXP(%edi) jmp L_Re_normaliseLCheck_truncate_64: orl %edx,%edx jz L_Re_normaliseLTruncate_64: movb LOST_DOWN,FPU_bits_lostL_Re_normalise: testb $0xff,FPU_denormal jnz Normalise_resultL_Normalised: movl TAG_Valid,%edxL_deNormalised: cmpb LOST_UP,FPU_bits_lost je L_precision_lost_up cmpb LOST_DOWN,FPU_bits_lost je L_precision_lost_downL_no_precision_loss: /* store the result */L_Store_significand: movl %eax,SIGH(%edi) movl %ebx,SIGL(%edi) cmpw EXP_OVER,EXP(%edi) jge L_overflow movl %edx,%eax /* Convert the exponent to 80x87 form. */ addw EXTENDED_Ebias,EXP(%edi) andw $0x7fff,EXP(%edi)fpu_reg_round_signed_special_exit: cmpb SIGN_POS,PARAM5 je fpu_reg_round_special_exit orw $0x8000,EXP(%edi) /* Negative sign for the result. */fpu_reg_round_special_exit:#ifndef NON_REENTRANT_FPU popl %ebx /* adjust the stack pointer */#endif /* NON_REENTRANT_FPU */ fpu_Arith_exit: popl %ebx popl %edi popl %esi leave ret/* * Set the FPU status flags to represent precision loss due to * round-up. */L_precision_lost_up: push %edx push %eax call set_precision_flag_up popl %eax popl %edx jmp L_no_precision_loss/* * Set the FPU status flags to represent precision loss due to * truncation. */L_precision_lost_down: push %edx push %eax call set_precision_flag_down popl %eax popl %edx jmp L_no_precision_loss/* * The number is a denormal (which might get rounded up to a normal) * Shift the number right the required number of bits, which will * have to be undone later... */L_Make_denorm: /* The action to be taken depends upon whether the underflow exception is masked */ testb CW_Underflow,%cl /* Underflow mask. */ jz Unmasked_underflow /* Do not make a denormal. */ movb DENORMAL,FPU_denormal pushl %ecx /* Save */ movw EXP_UNDER+1,%cx subw EXP(%edi),%cx cmpw $64,%cx /* shrd only works for 0..31 bits */ jnc Denorm_shift_more_than_63 cmpw $32,%cx /* shrd only works for 0..31 bits */ jnc Denorm_shift_more_than_32/* * We got here without jumps by assuming that the most common requirement * is for a small de-normalising shift. * Shift by [1..31] bits */ addw %cx,EXP(%edi) orl %edx,%edx /* extension */ setne %ch /* Save whether %edx is non-zero */ xorl %edx,%edx shrd %cl,%ebx,%edx shrd %cl,%eax,%ebx shr %cl,%eax orb %ch,%dl popl %ecx jmp Denorm_done/* Shift by [32..63] bits */Denorm_shift_more_than_32: addw %cx,EXP(%edi) subb $32,%cl orl %edx,%edx setne %ch orb %ch,%bl xorl %edx,%edx shrd %cl,%ebx,%edx shrd %cl,%eax,%ebx shr %cl,%eax orl %edx,%edx /* test these 32 bits */ setne %cl orb %ch,%bl orb %cl,%bl movl %ebx,%edx movl %eax,%ebx xorl %eax,%eax popl %ecx jmp Denorm_done/* Shift by [64..) bits */Denorm_shift_more_than_63: cmpw $64,%cx jne Denorm_shift_more_than_64/* Exactly 64 bit shift */ addw %cx,EXP(%edi) xorl %ecx,%ecx orl %edx,%edx setne %cl orl %ebx,%ebx setne %ch orb %ch,%cl orb %cl,%al movl %eax,%edx xorl %eax,%eax xorl %ebx,%ebx popl %ecx jmp Denorm_doneDenorm_shift_more_than_64: movw EXP_UNDER+1,EXP(%edi)/* This is easy, %eax must be non-zero, so.. */ movl $1,%edx xorl %eax,%eax xorl %ebx,%ebx popl %ecx jmp Denorm_doneUnmasked_underflow: movb UNMASKED_UNDERFLOW,FPU_denormal jmp Denorm_done/* Undo the de-normalisation. */Normalise_result: cmpb UNMASKED_UNDERFLOW,FPU_denormal je Signal_underflow/* The number must be a denormal if we got here. */#ifdef PARANOID /* But check it... just in case. */ cmpw EXP_UNDER+1,EXP(%edi) jne L_norm_bugged#endif /* PARANOID */#ifdef PECULIAR_486 /* * This implements a special feature of 80486 behaviour. * Underflow will be signalled even if the number is * not a denormal after rounding. * This difference occurs only for masked underflow, and not * in the unmasked case. * Actual 80486 behaviour differs from this in some circumstances. */ orl %eax,%eax /* ms bits */ js LPseudoDenormal /* Will be masked underflow */#else orl %eax,%eax /* ms bits */ js L_Normalised /* No longer a denormal */#endif /* PECULIAR_486 */ jnz LDenormal_adj_exponent orl %ebx,%ebx jz L_underflow_to_zero /* The contents are zero */LDenormal_adj_exponent: decw EXP(%edi)LPseudoDenormal: testb $0xff,FPU_bits_lost /* bits lost == underflow */ movl TAG_Special,%edx jz L_deNormalised /* There must be a masked underflow */ push %eax pushl EX_Underflow call EXCEPTION popl %eax popl %eax movl TAG_Special,%edx jmp L_deNormalised/* * The operations resulted in a number too small to represent. * Masked response. */L_underflow_to_zero: push %eax call set_precision_flag_down popl %eax push %eax pushl EX_Underflow call EXCEPTION popl %eax popl %eax/* Reduce the exponent to EXP_UNDER */ movw EXP_UNDER,EXP(%edi) movl TAG_Zero,%edx jmp L_Store_significand/* The operations resulted in a number too large to represent. */L_overflow: addw EXTENDED_Ebias,EXP(%edi) /* Set for unmasked response. */ push %edi call arith_overflow pop %edi jmp fpu_reg_round_signed_special_exitSignal_underflow: /* The number may have been changed to a non-denormal */ /* by the rounding operations. */ cmpw EXP_UNDER,EXP(%edi) jle Do_unmasked_underflow jmp L_NormalisedDo_unmasked_underflow: /* Increase the exponent by the magic number */ addw $(3*(1<<13)),EXP(%edi) push %eax pushl EX_Underflow call EXCEPTION popl %eax popl %eax jmp L_Normalised#ifdef PARANOID#ifdef PECULIAR_486L_bugged_denorm_486: pushl EX_INTERNAL|0x236 call EXCEPTION popl %ebx jmp L_exception_exit#elseL_bugged_denorm: pushl EX_INTERNAL|0x230 call EXCEPTION popl %ebx jmp L_exception_exit#endif /* PECULIAR_486 */ L_bugged_round24: pushl EX_INTERNAL|0x231 call EXCEPTION popl %ebx jmp L_exception_exitL_bugged_round53: pushl EX_INTERNAL|0x232 call EXCEPTION popl %ebx jmp L_exception_exitL_bugged_round64: pushl EX_INTERNAL|0x233 call EXCEPTION popl %ebx jmp L_exception_exitL_norm_bugged: pushl EX_INTERNAL|0x234 call EXCEPTION popl %ebx jmp L_exception_exitL_entry_bugged: pushl EX_INTERNAL|0x235 call EXCEPTION popl %ebxL_exception_exit: mov $-1,%eax jmp fpu_reg_round_special_exit#endif /* PARANOID */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -