chipd32.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 992 行 · 第 1/3 页

ASM
992
字号
        fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80

;  The following lines check the numerator exponent before scaling.
;  This in order to prevent undeflow when scaling the numerator,
;  which will cause a denormal exception flag to be set when the
;  actual divide is preformed. This flag would not have been set
;  normally. If there is a risk of underflow, the scale factor is
;  17/16 instead of 15/16.
;
        mov     eax, [esp+MAIN_NUMER+8] ; test numerator exponent
        and     eax, 07fffh
        cmp     eax, 00001h
        je      small_numer

        fmul    fdiv_scale_1            ; scale denominator by 15/16
        fxch
        fmul    fdiv_scale_1            ; scale numerator by 15/16
        fxch

;
;  The next line restores the users control word.  If the incoming
;  control word had the underflow exception masked and precision
;  control set to 80 bits, this line can be omitted.
;

        fldcw   [esp+PREV_CW]           ; restore caller's control word
        fdivp   st(1), st               ; use of hardware is OK.
        ret

small_numer:
        fmul    fdiv_scale_2            ; scale denominator by 17/16
        fxch
        fmul    fdiv_scale_2            ; scale numerator by 17/16
        fxch

;
;  The next line restores the users control word.  If the incoming
;  control word had the underflow exception masked and precision
;  control set to 80 bits, this line can be omitted.
;

        fldcw   [esp+PREV_CW]           ; restore caller's control word
        fdivp   st(1), st               ; use of hardware is OK.
        ret

denormal:
        mov     eax, [esp+MAIN_DENOM]   ; test for whole mantissa == 0
        or      eax, [esp+MAIN_DENOM+4] ; test for whole mantissa == 0
        jnz     denormal_divide_scaled  ; denominator is not zero
invalid_denom:                          ; zero or invalid denominator
        fdivp   st(1), st               ; use of hardware is OK.
        ret

denormal_divide_scaled:
        mov     eax, [esp + MAIN_DENOM + 8]     ; get exponent
        and     eax, 07fffh             ; check for zero exponent
        jnz     invalid_denom           ;
;
;  The following six lines turn off exceptions and set the
;  precision control to 80 bits.  The former is necessary to
;  force any traps to be taken at the divide instead of the scaling
;  code.  The latter is necessary in order to get full precision for
;  codes with incoming 32 and 64 bit precision settings.  If
;  it can be guaranteed that before reaching this point, the underflow
;  exception is masked and the precision control is at 80 bits, these
;  five lines can be omitted.
;

        fnstcw  [esp+PREV_CW]           ; save caller's control word
        mov     eax, [esp+PREV_CW]
        or      eax, 033fh              ; mask exceptions, pc=80
        and     eax, 0f3ffh             ; set rounding mode to nearest
        mov     [esp+PATCH_CW], eax
        fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80

        mov     eax, [esp + MAIN_NUMER +8]      ; test numerator exponent
        and     eax, 07fffh             ; check for denormal numerator
        je      denormal_numer
        cmp     eax, 07fffh             ; NaN or infinity
        je      invalid_numer
        mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
        add     eax, eax                ; shift the first bit into carry
        jnc     invalid_numer           ; if there is no carry, we have an
                                        ; invalid numer
        jmp     numer_ok

denormal_numer:
        mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
        add     eax, eax                ; shift the first bit into carry
        jc      invalid_numer           ; if there is a carry, we have an
                                        ; invalid numer

numer_ok:
        fxch
        fstp    st                      ; pop numerator
        fld     st                      ; make copy of denominator
        fmul    dword ptr[one_shl_63]   ; make denominator not denormal
        fstp    tbyte ptr [esp+MAIN_DENOM]      ; save modified denominator
        fld     tbyte ptr [esp+MAIN_NUMER]      ; load numerator
        fxch                            ; restore proper order
        fwait

;  The next line restores the users control word.  If the incoming
;  control word had the underflow exception masked and precision
;  control set to 80 bits, this line can be omitted.
;

        fldcw   [esp+PREV_CW]           ; restore caller's control word
        jmp     retry                   ; start the whole thing over

invalid_numer:
;
;  The next line restores the users control word.  If the incoming
;  control word had the underflow exception masked and precision
;  control set to 80 bits, this line can be omitted.
;
        fldcw   [esp + PREV_CW]
        fdivp   st(1), st               ; use of hardware is OK.
        ret

fdiv_main_routine       ENDP

        public  __fdiv_fpr
        defpe   __fdiv_fpr

        sub     esp, STACK_SIZE
        jmp     dword ptr dispatch_table[eax*4]


label0:
        fdiv    st,st(0)                ; D8 F0         FDIV    ST,ST(0)
        add     esp, STACK_SIZE
        ret
label1:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label2:
        fdivr   st,st(0)                ; D8 F8         FDIVR   ST,ST(0)
        add     esp, STACK_SIZE
        ret
label3:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label4:
        fdiv    st(0),st                ; DC F8/D8 F0   FDIV    ST(0),ST
        add     esp, STACK_SIZE
        ret
label5:
        fdivp   st(0),st                ; DE F8         FDIVP   ST(0),ST
        add     esp, STACK_SIZE
        ret
label6:
        fdivr   st(0),st                ; DC F0/DE F0   FDIVR   ST(0),ST
        add     esp, STACK_SIZE
        ret
label7:
        fdivrp  st(0),st                ; DE F0         FDIVRP  ST(0),ST
        add     esp, STACK_SIZE
        ret
label8:
        fdiv_st 1, 0
        ret
label9:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label10:
        fdivr_st 1, 0
        ret
label11:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label12:
        fdiv_sti 1, 0
        ret
label13:
        fdivp_sti 1, 0
        ret
label14:
        fdivr_sti 1, 0
        ret
label15:
        fdivrp_sti 1, 0
        ret
label16:
        fdiv_st 2, 1
        ret
label17:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label18:
        fdivr_st 2, 1
        ret
label19:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label20:
        fdiv_sti 2, 1
        ret
label21:
        fdivp_sti 2, 1
        ret
label22:
        fdivr_sti 2, 1
        ret
label23:
        fdivrp_sti 2, 1
        ret
label24:
        fdiv_st 3, 2
        ret
label25:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label26:
        fdivr_st 3, 2
        ret
label27:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label28:
        fdiv_sti 3, 2
        ret
label29:
        fdivp_sti 3, 2
        ret
label30:
        fdivr_sti 3, 2
        ret
label31:
        fdivrp_sti 3, 2
        ret
label32:
        fdiv_st 4, 3
        ret
label33:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label34:
        fdivr_st 4, 3
        ret
label35:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label36:
        fdiv_sti 4, 3
        ret
label37:
        fdivp_sti 4, 3
        ret
label38:
        fdivr_sti 4, 3
        ret
label39:
        fdivrp_sti 4, 3
        ret
label40:
        fdiv_st 5, 4
        ret
label41:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label42:
        fdivr_st 5, 4
        ret
label43:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label44:
        fdiv_sti 5, 4
        ret
label45:
        fdivp_sti 5, 4
        ret
label46:
        fdivr_sti 5, 4
        ret
label47:
        fdivrp_sti 5, 4
        ret
label48:
        fdiv_st 6, 5
        ret
label49:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label50:
        fdivr_st 6, 5
        ret
label51:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label52:
        fdiv_sti 6, 5
        ret
label53:
        fdivp_sti 6, 5
        ret
label54:
        fdivr_sti 6, 5
        ret
label55:
        fdivrp_sti 6, 5
        ret
label56:
        fdiv_st 7, 6
        ret
label57:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label58:
        fdivr_st 7, 6
        ret
label59:
        add     esp, STACK_SIZE
        int     ILLEGAL_OPC
label60:
        fdiv_sti 7, 6
        ret
label61:
        fdivp_sti 7, 6
        ret
label62:
        fdivr_sti 7, 6
        ret
label63:
        fdivrp_sti 7, 6
        ret
__fdiv_fpr      ENDP


__fdivp_sti_st    PROC    NEAR

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?