📄 reg_roun.s
字号:
orl %edx,%edx jnz LDo_64_round_up jmp LRe_normaliseLDown_64: cmpb SIGN_POS,SIGN(%edi) je LCheck_truncate_64 /* If positive then down==truncate */ orl %edx,%edx jnz LDo_64_round_up jmp LRe_normaliseLRound_nearest_64: cmpl $0x80000000,%edx jc LCheck_truncate_64 jne LDo_64_round_up /* Now test for round-to-even */ testb $1,%ebx jz LCheck_truncate_64LDo_64_round_up: movb LOST_UP,FPU_bits_lost addl $1,%ebx adcl $0,%eaxLCheck_Round_Overflow: jnc LRe_normalise /* Overflow, adjust the result (significand to 1.0) */ rcrl $1,%eax rcrl $1,%ebx incl EXP(%edi) jmp LRe_normaliseLCheck_truncate_64: orl %edx,%edx jz LRe_normaliseLTruncate_64: movb LOST_DOWN,FPU_bits_lostLRe_normalise: testb $0xff,FPU_denormal jnz xNormalise_resultxL_Normalised: cmpb LOST_UP,FPU_bits_lost je xL_precision_lost_up cmpb LOST_DOWN,FPU_bits_lost je xL_precision_lost_downxL_no_precision_loss: /* store the result */ movb TW_Valid,TAG(%edi)xL_Store_significand: movl %eax,SIGH(%edi) movl %ebx,SIGL(%edi) xorl %eax,%eax /* No errors detected. */ cmpl EXP_OVER,EXP(%edi) jge L_overflowfpu_reg_round_exit:#ifdef REENTRANT_FPU popl %ebx /* adjust the stack pointer */#endif REENTRANT_FPUfpu_Arith_exit: popl %ebx popl %edi popl %esi leave ret/* * Set the FPU status flags to represent precision loss due to * round-up. */xL_precision_lost_up: push %eax call _set_precision_flag_up popl %eax jmp xL_no_precision_loss/* * Set the FPU status flags to represent precision loss due to * truncation. */xL_precision_lost_down: push %eax call _set_precision_flag_down popl %eax jmp xL_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... */xMake_denorm: /* The action to be taken depends upon whether the underflow exception is masked */ testb CW_Underflow,%cl /* Underflow mask. */ jz xUnmasked_underflow /* Do not make a denormal. */ movb DENORMAL,FPU_denormal pushl %ecx /* Save */ movl EXP_UNDER+1,%ecx subl EXP(%edi),%ecx cmpl $64,%ecx /* shrd only works for 0..31 bits */ jnc xDenorm_shift_more_than_63 cmpl $32,%ecx /* shrd only works for 0..31 bits */ jnc xDenorm_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 */ addl %ecx,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 xDenorm_done/* Shift by [32..63] bits */xDenorm_shift_more_than_32: addl %ecx,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 xDenorm_done/* Shift by [64..) bits */xDenorm_shift_more_than_63: cmpl $64,%ecx jne xDenorm_shift_more_than_64/* Exactly 64 bit shift */ addl %ecx,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 xDenorm_donexDenorm_shift_more_than_64: movl 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 xDenorm_donexUnmasked_underflow: movb UNMASKED_UNDERFLOW,FPU_denormal jmp xDenorm_done/* Undo the de-normalisation. */xNormalise_result: cmpb UNMASKED_UNDERFLOW,FPU_denormal je xSignal_underflow/* The number must be a denormal if we got here. */#ifdef PARANOID /* But check it... just in case. */ cmpl 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 LNormalise_shift_done /* Will be masked underflow */#endif PECULIAR_486 orl %eax,%eax /* ms bits */ js xL_Normalised /* No longer a denormal */ jnz LNormalise_shift_up_to_31 /* Shift left 0 - 31 bits */ orl %ebx,%ebx jz L_underflow_to_zero /* The contents are zero *//* Shift left 32 - 63 bits */ movl %ebx,%eax xorl %ebx,%ebx subl $32,EXP(%edi)LNormalise_shift_up_to_31: bsrl %eax,%ecx /* get the required shift in %ecx */ subl $31,%ecx negl %ecx shld %cl,%ebx,%eax shl %cl,%ebx subl %ecx,EXP(%edi)LNormalise_shift_done: testb $0xff,FPU_bits_lost /* bits lost == underflow */ jz xL_Normalised /* There must be a masked underflow */ push %eax pushl EX_Underflow call _exception popl %eax popl %eax jmp xL_Normalised/* * 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 */ movl EXP_UNDER,EXP(%edi) movb TW_Zero,TAG(%edi) jmp xL_Store_significand/* The operations resulted in a number too large to represent. */L_overflow: push %edi call _arith_overflow pop %edi jmp fpu_reg_round_exitxSignal_underflow: /* The number may have been changed to a non-denormal */ /* by the rounding operations. */ cmpl EXP_UNDER,EXP(%edi) jle xDo_unmasked_underflow jmp xL_NormalisedxDo_unmasked_underflow: /* Increase the exponent by the magic number */ addl $(3*(1<<13)),EXP(%edi) push %eax pushl EX_Underflow call EXCEPTION popl %eax popl %eax jmp xL_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_486L_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_exit#endif PARANOID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -