fpe86.inc

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

INC
1,454
字号

        extrn   __GETDS : near

_DOS  = 1
_OS2  = 2

 _BP    equ     BP
 _SP    equ     SP
 _AX    equ     AX
 _BX    equ     BX
 _CX    equ     CX
 _DX    equ     DX
 _SI    equ     SI
 _DI    equ     DI

  NC = '$'

ifdef _DEBUG
public  badop,prtnyi,my87,modrm,memop,stkop,stkop1
endif

sarea   struc
control dw              0                       ; CW
status  dw              0                       ; SW
tags    dw              0                       ; TAG
iptr    dw              0,0                     ; instruction pointer
dptr    dw              0,0                     ; data operand pointer
fpstack db              80 dup(0)               ; 8 tbyte reals for stack
fptemp  db              10 dup(0)               ; temporary tbyte real
precrtn dw              0                       ; address of precision routine
sarea   ends

NDP_SIZE        equ     94
ENV_SIZE        equ     14

include fpubits.inc

ifdef __QNX__
        extrn   "C",__FPEhandler   : near;
endif

_DATA segment word public 'DATA'
ifndef __QNX__
        extrn   "C",__FPE_handler  : dword
my87            sarea           <>
endif
ifdef _DEBUG
nyimsg          db ": not yet implemented",0dH,0aH,NC
illopmsg        db "Illegal instruction encountered by 8087 emulator",0dH,0aH,NC
endif
_DATA ends

DGROUP  group   _DATA

assume  ds:DGROUP

include consts.inc
include tentab.inc
include tagtab.inc
include fpucc.inc

ifdef QNX32
S_FL    =       38H
S_CS    =       34H
S_IP    =       30H
S_AX    =       2CH
S_CX    =       28H
S_DX    =       24H
S_BX    =       20H
S_SP    =       1CH
S_BP    =       18H
S_SI    =       14H
S_DI    =       10H
S_DS    =       0CH
S_ES    =       08H
S_FS    =       04H
S_GS    =       00H

else

ifdef __PROTMODE__
ifndef __QNX__
DPMI_SS =       22H
DPMI_SP =       20H
S_FL    =       1EH
S_CS    =       1CH
S_IP    =       1AH
;
; 3 words in here for DPMI (error code, return CS, return IP)
;
else    ; __QNX__
S_FL    =       18H
S_CS    =       16H
S_IP    =       14H
endif
else    ; not __PROTMODE__
S_FL    =       18H
S_CS    =       16H
S_IP    =       14H
endif

S_AX    =       12H
S_CX    =       10H
S_DX    =       0EH
S_BX    =       0CH
S_SP    =       0AH
S_BP    =       08H
S_SI    =       06H
S_DI    =       04H
S_DS    =       02H
S_ES    =       00H
endif
S_MY87  =       S_SP

get_st0 macro
        mov     ax,word ptr [bx].status ; - di gets idx of top of stack
        mov     al,ah                   ; - move to bottom
        and     ax,0038h                ; - isolate register number
        mov     di,ax                   ; - save 8 * register number
        shr     ax,1                    ; - calc 2 * register number
        shr     ax,1                    ; - ...
        add     di,ax                   ; - calc 10 * register number
        endm


jmptab  macro   a,b,c,d,e,f,g,h
        local   table
        mov     bl,dh
        and     bx,7
        shl     bx,1
        jmp     word ptr cs:table[bx]
table   dw      a
        dw      b
        dw      c
        dw      d
        dw      e
        dw      f
        dw      g
        dw      h
        endm

_lea    macro   reg,what
        IFIDN   <what>,<st>
          lea     reg,[di+bp].fpstack
        ELSE
          IFIDN   <what>,<st(i)>
            lea     reg,[si+bp].fpstack
          ELSE
           .ERRDIF <what>,<temp>
           lea     reg,[bp].fptemp
          ENDIF
        ENDIF
        endm

saveflg macro                                   ; MACRO
        inc     ax                              ; -1,0,1,2 -> 0,1,2,3
        mov     dx,ds:[bp].status               ; get status word
        and     dx,NOT SW_CC                    ; turn off C0,C1,C2,C3
        mov     bx,ax                           ; turn on new bits
        or      dh,byte ptr cs:fpbits[bx]       ; ...
        mov     ds:[bp].status,dx               ; save in status word
        endm

savecc  macro                                   ; MACRO
        and     ax,7                            ; keep low order 3 bits of quot
        mov     dx,ds:[bp].status               ; get status word
        and     dx,NOT SW_CC                    ; turn off C0,C1,C2,C3
        mov     bx,ax                           ; turn on new bits
        or      dh,cs:ccbits[bx]                ; ...
        mov     ds:[bp].status,dx               ; save in status word
        endm

tag_st0 macro new_tag
        IFDIF   <new_tag>,<t_empty>
          mov   bx,cs:tagtab[di].t_off          ; get turn off mask
          and   ds:[bp].tags,bx                 ; turn off the bits
        ENDIF
        IFDIF   <new_tag>,<t_valid>
          mov     bx,cs:tagtab[di].&new_tag     ; get new bits
          or      ds:[bp].tags,bx               ; turn on new bits
        ENDIF
        endm

tag_sti macro new_tag
        IFDIF   <new_tag>,<t_empty>
          mov   bx,cs:tagtab[si].t_off          ; get turn off mask
          and   ds:[bp].tags,bx                 ; turn off the bits
        ENDIF
        IFDIF   <new_tag>,<t_valid>
          mov     bx,cs:tagtab[si].&new_tag     ; get new bits
          or      ds:[bp].tags,bx               ; turn on new bits
        ENDIF
        endm

pushstk macro
        decstp
        ; if full entry, to incstp and exception!
        ; mark as valid, zero or invalid
        tag_st0 t_valid
        endm

decstp  macro                                   ; MACRO
        mov     di,cs:tentab[di].t_prev         ; dec stack pointer
        mov     bx,cs:tentab[di].t_stktop       ; update top of stack pointer
        and     ds:[bp].status,NOT SW_ST        ;...
        or      word ptr ds:[bp].status,bx      ; put back into SW_ST
        endm

popstk  macro
        ; if empty entry, take exception
        ; mark as empty
        tag_st0 t_empty
        incstp
        endm

incstp  macro                                   ; MACRO
        mov     di,cs:tentab[di].t_next         ; inc stack pointer
        mov     bx,cs:tentab[di].t_stktop       ; update top of stack pointer
        and     ds:[bp].status,NOT SW_ST        ;...
        or      word ptr ds:[bp].status,bx      ; put back into SW_ST
        endm

done    macro
        jmp     exit                            ; done instruction
        endm

popstk_done     macro
        jmp     popstk_exit                     ; popstk then exit
        endm

saveflg_done    macro
        jmp     saveflg_exit                    ; saveflg then exit
        endm

saveflg_popstk_done     macro
        jmp     saveflg_popstk_exit             ; saveflg, popstk then exit
        endm

donearith macro
        jmp        ds:[bp].precrtn              ; done instruction
        endm

save_regs macro
        push    ax                      ; save registers (same order as pusha)
        push    cx                      ; ...
        push    dx                      ; ...
        push    bx                      ; ...
        push    bp                      ; ...(sp)
        push    bp                      ; ...
        push    si                      ; ...
        push    di                      ; ...
        push    ds                      ; ...
        push    es                      ; ...
        endm

getretaddr macro                        ; get return address
ifdef QNX32
        mov     si,S_IP[bp]
        mov     es,S_CS[bp]
else
        les     si,S_IP[bp]
endif
        endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       exception handling
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
        xdefp   F8DivZero
F8DivZero proc  near
        mov     AL,SW_ZE                ; indicate zero divide
        mov     AH,FPE_ZERODIVIDE       ; ...
        call    __Exception_HNDLR       ; process exception
        ret                             ; return
F8DivZero endp

        xdefp   F8InvalidOp
F8InvalidOp proc near
        mov     AL,SW_IE                ; indicate invalid operation
        mov     AH,FPE_INVALID          ; ...
        call    __Exception_HNDLR       ; process exception
        ret                             ; return
F8InvalidOp endp

        xdefp   F8OverFlow
F8OverFlow proc near
        mov     AL,SW_OE                ; get OVERFLOW mask
        mov     AH,FPE_OVERFLOW         ; set OVERFLOW exception code
        call    __Exception_HNDLR       ; process exception
        ret                             ; return
F8OverFlow endp

        xdefp   __Exception_HNDLR
;
; input:
;       AL - exception mask for status and control word
;       AH - exception code for signal handler

__Exception_HNDLR proc  near
        or      byte ptr ds:[bp].status,AL   ; indicate exception occurred
        test    byte ptr ds:[bp].control,AL  ; if exception unmasked
        _if     e                       ; then
          push  si                      ; - save registers
          push  di                      ; - ...
          push  cx                      ; - ...
          push  es                      ; - ...
          push  ds                      ; - ...
          sub   sp,NDP_SIZE             ; - allocate space for copy of 387
          mov   cx,ss                   ; - set ES=SS
          mov   es,cx                   ; - ...
          mov   si,bp                   ; - point to current copy
          mov   di,sp                   ; - point to temporary save area
          mov   cx,NDP_SIZE/2           ; - number of words to copy
          cld                           ; - make sure forward direction
          rep   movsw                   ; - copy it
;          call  __GETDS                 ; - point DS to DGROUP
          mov   AL,AH                   ; - get exception code
          mov   AH,0                    ; - ...
ifdef __QNX__
          call  __FPEhandler            ; - jump to SIGFPE handler rtn
else
          call  __FPE_handler           ; - jump to SIGFPE handler rtn
endif
          mov   cx,ds                   ; - set ES=DS
          mov   es,cx                   ; - ...
          mov   cx,ss                   ; - set DS=SS
          mov   ds,cx                   ; - ...
          mov   di,bp                   ; - point to current copy
          mov   si,sp                   ; - point to temporary save area
          mov   cx,NDP_SIZE/2           ; - number of words to copy
          rep   movsw                   ; - copy it
          add   sp,NDP_SIZE             ; - deallocate space
          pop   ds                      ; - restore registers
          pop   es                      ; - ...
          pop   cx                      ; - ...
          pop   di                      ; - ...
          pop   si                      ; - ...
        _endif                          ; endif
        ret                             ; return
__Exception_HNDLR endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       interrupt int7()     ; protected-mode programs trap to here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; QNX entry point: all registers have been saved on stack as above
;       also ES:BX contains address of 120 byte save area
;
ifdef __PROTMODE__
        public  __int7
__int7  proc    near
ifndef __QNX__
        push    ax                      ; dummy error code
        push    cs                      ; CS
        call    __dmy_int7              ; make stack look like DPMI exception
        add     sp,2                    ; remove dummy error code
        iret                            ; return from interrupt

__dmy_int7:
        pusha                           ; save registers
        push    ds                      ; ...
        push    es                      ; ...
        lea     bx,my87                 ; ...

⌨️ 快捷键说明

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