fldm086.asm

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

ASM
439
字号

ifdef _BUILDING_MATHLIB

include mdef.inc
include struct.inc
include xception.inc

        modstart    fldm086, word


endif

;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
;<>
;<>     long double math library
;<>
;<>     inputs: AX - pointer to long double (op1)
;<>             DX - pointer to long double (op2)
;<>             BX - pointer to long double (result)
;<>
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

        xdefp   __FLDM           ; 10-byte real multiply
        xdefp   ___LDM           ; 10-byte real multiply


;=====================================================================

        defp    __FLDM
ifdef _BUILDING_MATHLIB
        push    DS              ; save DS
        push    SS              ; fpc code assumes parms are relative to SS
        pop     DS              ; ...
endif
        push    SI              ; save SI
        push    DI              ; save DI
        push    CX              ; save CX
        push    BX              ; save pointer to result
        mov     SI,AX           ; point to op1
        mov     DI,DX           ; point to op2
        lcall   ___LDM          ; do the multiply
        pop     DI              ; restore pointer to result
        mov     [DI],DX         ; store result
        mov     2[DI],CX        ; ...
        mov     4[DI],BX        ; ...
        mov     6[DI],AX        ; ...
        mov     8[DI],SI        ; ...
        pop     CX              ; restore CX
        pop     DI              ; restore DI
        pop     SI              ; restore SI
ifdef _BUILDING_MATHLIB
        pop     DS              ; restore DS
endif
        ret                     ; return
        endproc __FLDM

        defp    __FLDMC
ifdef _BUILDING_MATHLIB
        push    DS              ; save DS
        push    SS              ; fpc code assumes parms are relative to SS
        pop     DS              ; ...
endif
        push    SI              ; save SI
        push    DI              ; save DI
        push    CX              ; save CX
        push    BX              ; save pointer to result
        mov     SI,AX           ; point to op1
        mov     DI,DX           ; point to op2
        push    CS:8[DI]        ; push constant op2 onto stack
        push    CS:6[DI]        ; ...
        push    CS:4[DI]        ; ...
        push    CS:2[DI]        ; ...
        push    CS:[DI]         ; ...
        mov     DI,SP           ; point to op2
        lcall   ___LDM          ; do the multiply
        add     SP,10           ; remove constant from stack
        pop     DI              ; restore pointer to result
        mov     [DI],DX         ; store result
        mov     2[DI],CX        ; ...
        mov     4[DI],BX        ; ...
        mov     6[DI],AX        ; ...
        mov     8[DI],SI        ; ...
        pop     CX              ; restore CX
        pop     DI              ; restore DI
        pop     SI              ; restore SI
ifdef _BUILDING_MATHLIB
        pop     DS              ; restore DS
endif
        ret                     ; return
        endproc __FLDMC

        defp    mul_oflow       ; overflow
        mov     SI,CX           ; get sign
        or      SI,7FFFh        ; set exponent for infinity
        mov     AX,8000h        ; set fraction
        sub     BX,BX           ; ...
        mov     CX,BX           ; ...
        mov     DX,BX           ; ...
ifdef _BUILDING_MATHLIB
        pop     DS              ; restore DS
endif
        ret                     ; return
        endproc mul_oflow
;
; input:
;       DI - pointer to operand
;       AX - sign+exponent of op1
;       DX - sign+exponent of op2
;
        defp    mul_by_pow2
        mov     CX,AX           ; calc. sign of result
        xor     CX,DX           ; ...
        and     CX,8000h        ; ...
        and     AX,7FFFh        ; isolate exponent
        and     DX,7FFFh        ; ...
        _guess                  ; guess: overflow
          cmp   AX,7FFFh        ; - see if op1 was infinity     06-nov-92
          je    mul_oflow       ; - answer is infinity
          cmp   DX,7FFFh        ; - see if op2 was infinity
          je    mul_oflow       ; - answer is infinity
          add   AX,DX           ; - determine exponent of result
          sub   AX,3FFFh        ; - remove extra bias
          _quif c               ; - quit if exponent is negative
          cmp   AX,7FFFh        ; - check for overflow
          jae   mul_oflow       ; - . . .
        _endguess               ; endguess
        cmp     AX,-64          ; if exponent is too small
        _if     l               ; then underflow
          sub   AX,AX           ; - set result to 0
          mov   BX,AX           ; - ...
          mov   CX,AX           ; - ...
          mov   DX,AX           ; - ...
          mov   SI,AX           ; - ...
ifdef _BUILDING_MATHLIB
          pop   DS              ; - restore DS
endif
          ret                   ; - return
        _endif                  ; endif
        push    CX              ; save sign
        mov     SI,AX           ; get exponent
        mov     AX,6[DI]        ; load mantissa
        mov     BX,4[DI]        ; ...
        mov     CX,2[DI]        ; ...
        mov     DX,[DI]         ; ...
        pop     DI              ; restore sign
        or      SI,SI           ; if denormal number
        _if     s               ; then
          _loop                 ; - loop
            shr   AX,1          ; - - shift number right
            rcr   BX,1          ; - - ...
            rcr   CX,1          ; - - ...
            rcr   DX,1          ; - - ...
            inc   SI            ; - - increment exponent
          _until  e             ; - until done
        _endif                  ; endif
        or      SI,DI           ; get sign
ifdef _BUILDING_MATHLIB
        pop     DS              ; restore DS
endif
        ret                     ; return
        endproc mul_by_pow2


; input:
;       SI - pointer to op1
;       DI - pointer to op2
; output:
;       SI - exponent+sign of result
;       AX:BX:CX:DX - mantissa


        defp    ___LDM
ifdef _BUILDING_MATHLIB
        push    DS              ; save DS
        push    SS              ; fpc code assumes parms are relative to SS
        pop     DS              ; ...
endif
        mov     AX,8[SI]        ; get exponent+sign of op1
        mov     DX,8[DI]        ; get exponent+sign of op2
        _guess                  ; guess: op1 is 0
          sub   BX,BX           ; - counter for number of zeros
          mov   CX,[SI]         ; - quit if op1 is not 0
          or    CX,CX           ; - ...
          _quif ne              ; - ...
          inc   BX              ; - op1 has at least 1 zero
          or    CX,2[SI]        ; - check the higher order words
          _quif ne              ; - ...
          inc   BX              ; - op1 has at least 2 zeros
          or    CX,4[SI]        ; - ...
          _quif ne              ; - ...
          inc   BX              ; - op1 has at least 3 zeros
          or    CX,6[SI]        ; - ...

;         if CX = 8000h, then op1 is a power of 2, just return op2 with
;         appropriate sign and exponent
          cmp   CX,8000h        ; - if op1 is a power of 2
          jne   l1
pow2_hop: jmp   mul_by_pow2     ; - then do special calc.

l1:       or    CX,CX           ; - test high order word
          _quif ne              ; - quit if op1 is not 0
          _shl  AX,1            ; - place sign in carry
          _if   e               ; - if operand one is 0
            mov   BX,AX         ; - - set result to 0
            mov   DX,AX         ; - - ...
            mov   SI,AX         ; - - ...
ifdef _BUILDING_MATHLIB
            pop   DS            ; - - restore DS
endif
            ret                 ; - - return
          _endif                ; - endif
          rcr   AX,1            ; - put back the sign
        _endguess               ; endguess

        _guess                  ; guess: op2 is 0
          mov   CX,[DI]         ; - quit if op2 is not 0
          or    CX,CX           ; - ...
          _quif ne              ; - ...
          dec   BX              ; - decrement counter
          or    CX,2[DI]        ; - check the higher order words

⌨️ 快捷键说明

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