📄 reg_round.s
字号:
LGreater_Half_53: /*Rounding: increment at the 53rd bit*/LDo_53_round_up: movb LOST_UP,FPU_bits_lost andl $0xfffff800,%ebx /* Truncate to 53 bits*/ addl $0x00000800,%ebx adcl $0,%eax jmp LCheck_Round_OverflowLCheck_truncate_53: movl %ebx,%ecx andl $0x000007ff,%ecx orl %edx,%ecx jz LRe_normaliseLTruncate_53: movb LOST_DOWN,FPU_bits_lost andl $0xfffff800,%ebx /* Truncate to 53 bits*/ jmp LRe_normalise/* Round etc to 64 bit precision*/LRound_To_64: movl %esi,%ecx andl CW_RC,%ecx cmpl RC_RND,%ecx je LRound_nearest_64 cmpl RC_CHOP,%ecx je LCheck_truncate_64 cmpl RC_UP,%ecx /* Towards +infinity*/ je LUp_64 cmpl RC_DOWN,%ecx /* Towards -infinity*/ je LDown_64#ifdef PARANOID jmp L_bugged#endif PARANOIDLUp_64: cmpb SIGN_POS,SIGN(%edi) jne LCheck_truncate_64 /* If negative then up==truncate*/ 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 /* Rounding done, no overflow */ /* Overflow, adjust the result (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: cmpl EXP_OVER,EXP(%edi) jge L_overflow /* store the result */ movb TW_Valid,TAG(%edi)xL_Store_significand: movl %eax,SIGH(%edi) movl %ebx,SIGL(%edi)FPU_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(%edi),%ecx subl EXP_UNDER+1,%ecx negl %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 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: /* Increase the exponent by the magic number*/ addl $(3*(1<<13)),EXP(%edi) 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 orl %eax,%eax /* ms bits*/ 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 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_Arith_exitxSignal_underflow: push %eax pushl EX_Underflow call EXCEPTION popl %eax popl %eax jmp xL_Normalised#ifdef PARANOID/* If we ever get here then we have problems! */L_bugged: pushl EX_INTERNAL|0x201 call EXCEPTION popl %ebx jmp FPU_Arith_exitL_norm_bugged: pushl EX_INTERNAL|0x216 call EXCEPTION popl %ebx jmp FPU_Arith_exitL_entry_bugged: pushl EX_INTERNAL|0x217 call EXCEPTION popl %ebx jmp FPU_Arith_exit#endif PARANOID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -