386fpemu.inc

来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 1,702 行 · 第 1/5 页

INC
1,702
字号
        mov     ecx,8                   ; do 8 times
fslup:  lea     esi,[ebx+ebp].fpstack   ; - point source to stack top
        movsd                           ; - save the value
        movsd                           ; - ...
        movsw                           ; - ...
        movzx   ebx,TENTBL[ebx].t_next  ; - 'pop' the stack
        loop    fslup                   ; end do
ENDIF
        mov     edi,ebx
        endm

rest87  macro size                      ; put user memory into the 87
        mov     ecx,ENV_SIZE / 4        ; set up size reg
        push    ds                      ; save registers
        push    es                      ; and xchg ds,es
        mov     ax,es                   ; ...
        mov     dx,ds                   ; ...
        mov     es,dx                   ; ...
        mov     ds,ax                   ; ...
        mov     edi,ebp                 ; ...
        rep     movsd                   ; put into 8087
IFDIF   <size>,<ENV_SIZE>
      ifdef SEGMENTED
        mov     ebx,dword ptr es:[ebp].status;- ebx gets index of top of stack
      else
        mov     ebx,dword ptr    [ebp].status;- ebx gets index of top of stack
      endif
        and     ebx,SW_ST               ; - ...
        shr     ebx,SW_ST_SHIFT         ; - ...
        lea     ebx,[ebx+ebx*4]         ; - ... times 5
        add     ebx,ebx                 ; - ... ... times 2
      ifdef SEGMENTED
        mov     dword ptr es:[ebp].stktop,ebx;- save index of top of stack
      else
        mov     dword ptr    [ebp].stktop,ebx;- save index of top of stack
      endif
        mov     ecx,8                   ; do 8 times
frlup:  lea     edi,[ebp+ebx].fpstack   ; - point to st(0)
        movsd                           ; - restore st(0)
        movsd                           ; - ...
        movsw                           ; - ...
        movzx   ebx,TENTBL[ebx].t_next  ;- 'pop' the stack
        loop    frlup                   ; end do
ENDIF
        pop     es                      ; ...
        pop     ds                      ; ...
        endm

load    macro  where,what                       ; load up hi:lo
        IFIDN           <what>,<double>         ; - then
      ifdef SEGMENTED
        mov     eax,es:[esi]                    ; - load up double
        mov     edx,es:4[esi]                   ; - ...
      else
        mov     eax,   [esi]                    ; - load up double
        mov     edx,   4[esi]                   ; - ...
      endif
        _lea    ebx,where                       ; - ...
        call    __EmuFDLD                       ; - convert to tbyte
        ELSE                                    ; else if long
        IFIDN      <what>,<long>                ; - then
      ifdef SEGMENTED
        mov     eax,es:[esi]                    ; - load long integer
      else
        mov     eax,   [esi]                    ; - load long integer
      endif
        _lea    edx,where                       ; - ...
        call    __I4LD                          ; - convert to tbyte
        ELSE                                    ; else if int
        IFIDN      <what>,<integer>             ; - then
      ifdef SEGMENTED
        mov     ax,es:[esi]                     ; - load an int
      else
        mov     ax,   [esi]                     ; - load an int
      endif
        cwde                                    ; - convert to long
        _lea    edx,where                       ; - ...
        call    __I4LD                          ; - convert to tbyte
        ELSE                                    ; else if double long (8 bytes)
        IFIDN      <what>,<dlong>               ; - then
      ifdef SEGMENTED
        mov     eax,es:[esi]                    ; - load up unsigned long
      else
        mov     eax,   [esi]                    ; - load up unsigned long
      endif
        _lea    edx,where                       ; - ...
        call    __U4LD                          ; - convert to tbyte
        ELSE                                    ; else if float
        IFIDN      <what>,<float>               ; - then
      ifdef SEGMENTED
        mov     eax,es:[esi]                    ; - load a float
      else
        mov     eax,   [esi]                    ; - load a float
      endif
        _lea    edx,where                       ; - ...
        call    __EmuFSLD                       ; - convert to double
        ELSE                                    ; else if st(i)
        IFIDN      <what>,<st(i)>               ; - then
        IFIDN      <where>,<temp>               ; - if going to temp
        mov10   ds,[esi+ebp].fpstack,ds,[ebp].fptemp
        ELSE                                    ; - else going to st
        mov10   ds,[esi+ebp].fpstack,ds,[edi+ebp].fpstack
        ENDIF                                   ; - endif
        ELSE                                    ; else if st
        IFIDN      <what>,<st>                  ; - then
        .ERRDIF   <where>,<temp>                ; - if going to temp
        mov10   ds,[edi+ebp].fpstack,ds,[ebp].fptemp
        ELSE                                    ; else if treal
        IFIDN      <what>,<treal>               ; - then
        IFIDN     <where>,<st>                  ; - if load to st
        mov10   es,[esi],ds,[edi+ebp].fpstack   ; - - move 10 bytes
        ELSE                                    ; - else load to temp
        .ERRDIF   <where>,<temp>                ; - - ...
        mov10   es,[esi],ds,[ebp].fptemp        ; - - move 10 bytes
        ENDIF                                   ; - endif
        ELSE                                    ; else if temp
        IFIDN     <what>,<temp>                 ; - then
        .ERRDIF   <where>,<st>                  ; - loading into st
        mov10   ds,[ebp].fptemp,ds,[ebp+edi].fpstack; - move 10 bytes
        ELSE                                    ; else
        .ERR                                    ; - I can't use my own macro's
        %OUT bad load macro                     ; - ...
        ENDIF                                   ; endif
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ... oh for an elseif
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        endm

store   macro   what                            ; store st somewhere
        IFIDN   <what>,<double>                 ; - then it
        _lea    eax,st                          ; - point to top of stack
        call    __EmuLDFD                       ; - convert to double
      ifdef SEGMENTED
        mov     es:[esi],eax                    ; - store it
        mov     es:4[esi],edx                   ; - ...
      else
        mov        [esi],eax                    ; - store it
        mov        4[esi],edx                   ; - ...
      endif
        ELSE                                    ; - ...
        IFIDN   <what>,<long>                   ; else if long
        _lea    eax,st                          ; - point to top of stack
        call    __LDI4                          ; - convert to long
      ifdef SEGMENTED
        mov     es:[esi],eax                    ; - store it
      else
        mov        [esi],eax                    ; - store it
      endif
        ELSE                                    ; else if float
        IFIDN   <what>,<float>                  ; - then
        _lea    eax,st                          ; - point to top of stack
        call    __EmuLDFS                       ; - convert to float
      ifdef SEGMENTED
        mov     es:[esi],eax                    ; - store it
      else
        mov        [esi],eax                    ; - store it
      endif
        ELSE                                    ; else if integer
        IFIDN   <what>,<integer>                ; - then
        _lea    eax,st                          ; - point to top of stack
        call    __LDI4                          ; - convert to long
        mov     edx,eax                         ; - save value
        cwde                                    ; - sign extend ax to eax
        cmp     eax,edx                         ; - if not equal
        _if     ne                              ; - then
          mov   ax,8000h                        ; - - indicate overflow
        _endif                                  ; - endif
      ifdef SEGMENTED
        mov     es:[esi],ax                     ; - store it
      else
        mov        [esi],ax                     ; - store it
      endif
        ELSE                                    ; else if double long (8 bytes)
        IFIDN   <what>,<dlong>                  ; - then
        _lea    eax,st                          ; - point to top of stack
        call    __LDU4                          ; - convert to unsigned long
      ifdef SEGMENTED
        mov     es:[esi],eax                    ; - store it
      else
        mov        [esi],eax                    ; - store it
      endif
        ELSE                                    ; else if st(i)
        IFIDN   <what>,<st(i)>                  ; - then
        mov10   ds,[edi+ebp].fpstack,ds,[esi+ebp].fpstack
        ELSE                                    ; else if st(i)
        IFIDN   <what>,<treal>                  ; - then
        mov10   ds,[edi+ebp].fpstack,es,[esi]   ; - move 10 bytes
        ELSE                                    ; else
        .ERR                                    ; - I cant use my own macro
        %OUT bad store macro                    ; - ...
        ENDIF                                   ; endif
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        ENDIF                                   ; ...
        endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;; memory instruction emulation ;;;;;;;;;;;;;;;;;;;;;
;;
;; AT THIS POINT
;; ES:ESI                  - pointer to the memory operand
;; DS:[EDI+EBP].fpstack    - pointer to the top of stack
;; ON EXIT
;; EDI                     - will be updated to reflect top of stack pointer
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

include memops.inc

;;;;;;;;;;;;;;;;;;;;;;;;;;; stack instruction emulation ;;;;;;;;;;;;;;;;;;;;;;;;
;; AT THIS POINT
;; DS:[EDI+EBP].fpstack - pointer to ST(0)
;; DS:[ESI+EBP].fpstack - pointer to ST(i)
;; EBX is the bottom 3 bits of modrm byte
;; ON EXIT
;; EDI          - will have been updated to reflect top of stack pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

include stkops.inc

; here are some 386 specific stack ops

s613:;  fpatan
;===================================================================
        _lea    edx,st          ; X
        popstk
        _lea    eax,st          ; Y
        mov     ebx,eax         ; destination
        call    __fpatan
        donearith

s614:;  fxtract
;===================================================================
        _lea    esi,st
        pushstk                                 ; push stack pointer
        _lea    ebx,st
        mov     eax,[esi]
        mov     [ebx],eax
        mov     eax,4[esi]
        mov     4[ebx],eax
        mov     ax,8[esi]
        mov     dx,ax
        and     dx,8000h
        or      dx,3fffh
        mov     8[ebx],dx
        and     ax,7fffh                        ; remove sign
        sub     ax,3fffh                        ; remove bias
        cwde                                    ; sign extend
        mov     edx,esi                         ; st(1)
        call    __I4LD                          ; load exponent
        done

s615:;  fprem1
s710:;  fprem
;===================================================================
        _lea    EAX,st                  ; point to st(0)
        movzx   ESI,TENTBL[EDI].t_next  ; get index for st(1)
        _lea    EDX,st(i)               ; point to st(1)
        call    __fprem                 ; do remainder
        savecc                          ; save condition codes
        donearith

s714:;  frndint
;===================================================================
        rndint                  ; round top of stack
        done

s715:;  fscale
;===================================================================
        mov     esi,edi         ; save top of stack index
;;;        incstp                       ; point to st(1)
        movzx   edi,TENTBL[edi].t_next  ; inc stack pointer
        _lea    EAX,st          ; point to scale factor
        mov     CX,8[EAX]       ; save exponent and sign
        call    __LDI4          ; convert scale factor to integer
        mov     edi,esi         ; restore pointer to st(0)
        _lea    EBX,st          ; point to number to be scaled
;
;       check to see if scale factor is too large;  29-mar-91
;
        mov     EDX,EAX         ; get integer scale factor
        cwde                    ; sign extend low order 16 bits
        cmp     EAX,EDX         ; if exponent doesn't fit in 16 bits
        _if     ne              ; then
          or    CH,CH           ; - if negative scale factor
          _if   s               ; - then
            sub   DX,DX         ; - - underflow
            sub   CX,CX         ; - - clear the sign
          _else                 ; - else
            mov   DX,7FFFh      ; - - overflow
            mov   CX,8[EBX]     ; - - get exponent and sign
            and   CX,8000h      ; - - isolate sign
          _endif                ; - endif
        _else                   ; else
          mov   DX,8[EBX]       ; - get current exponent
          mov   CX,DX           ; - get sign
          and   CX,8000h        ; - ...
          and   DX,7FFFh        ; - isolate exponent
          add   DX,AX           ; - calc. new exponent
          _if     s             ; - if overflow/underflow
            or    AH,AH         ; - - if negative
            _if   s             ; - - then
              sub   DX,DX       ; - - - underflow
              sub   CX,CX       ; - - - clear the sign
            _else               ; - - else
              mov   DX,7FFFh    ; - - - overflow
            _endif              ; - - endif
          _endif                ; - endif
        _endif                  ; endif
        or      DX,CX           ; put in the sign
        mov     8[EBX],DX       ; store new exponent
        done

s470:;  fstsw   ax
;===================================================================
        getword ax,status       ; get status word
ifdef __WIN387__
        mov     ebp,[esp]       ; get access to saved registers
        mov     word ptr S_EAX[ebp],ax   ; update user's AX
else
        mov     ebp,esp         ; get access to saved registers
        mov     S_EAX[ebp],ax   ; update user's AX
endif
        done

ifdef __WIN387__
__Win387_emulator endp
else
__int7  endp
endif

⌨️ 快捷键说明

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