386fpemu.inc

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

INC
1,702
字号
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
ifdef __WIN387__
        jmp     [precrtn]
else
      ifdef SEGMENTED
        jmp        ds:[ebp].precrtn             ; done instruction
      else
        jmp        [ebp].precrtn                ; done instruction
      endif
endif
        endm

getsavearea     macro
        ; - point to 387 save area
ifdef __WIN387__
        mov     ebp,WIN8087
else
if _OS eq _QNX
        lds     ebp, S_SAVEAREA[ebp]
else
ifdef SEGMENTED
        call    __GETDS
endif
        lea     ebp,my87
endif
endif
        endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; register conventions during instruction decoding
;
; - AH holds modrm byte
; - AL holds low 3 bits of opcode
; - CX value for segment (default DS)
; - DX value for segment to be used with [EBP] and [ESP]
; - DS:ESI points to our current byte to be picked up during decoding
;
; register conventions during instruction "execution"
;
; - DS:EBP points to my '8087' area
; - EDI is the top of stack index
; - - - DS:[EDI+EBP].fpstack points to ST(0)
; - ESI contains i from ST(i) for a non-memory operand
; - - - DS:[ESI+EBP].fpstack points to ST(i)
; - ES:ESI returns the effective address calculated for a memory operand
; - EAX ECX EBX EDX are scratch
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ifdef __WIN387__
;
;       entry point for 387 Emulator under Microsoft Windows 3.0
;
S_DS            = Client_DS
S_SS            = Client_SS
S_ES            = Client_ES
S_FS            = Client_FS
S_GS            = Client_GS
S_EDI           = Client_EDI
S_ESI           = Client_ESI
S_EBP           = Client_EBP
S_ESP           = Client_ESP
S_EBX           = Client_EBX
S_EDX           = Client_EDX
S_ECX           = Client_ECX
S_EAX           = Client_EAX
S_EIP           = Client_EIP
S_CS            = Client_CS
S_FL            = Client_EFlags

        public  __Win387_emulator
__Win387_emulator proc near
        push    EBP                     ; save address of Client_Reg_Struct
        mov     WINBase,eax             ; save various pointers
        mov     WIN8087,ebx             ;    to the client memory
        mov     WINVMHandle,ecx         ;       in the flat addr. space

p_extended:
exit:   mov     ebp,[esp]               ; get access to saved registers

else ;===================================================================

if _OS eq _QNX
;
;       entry point for 387 Emulator under QNX/386 (32-bit side)
;
S_EFL   =       44H
S_CS    =       40H
S_EIP   =       3cH
S_EAX   =       38H
S_ECX   =       34H
S_EDX   =       30H
S_EBX   =       2cH
S_ESP   =       28H
S_EBP   =       24H
S_ESI   =       20H
S_EDI   =       1cH
S_DS    =       18H
S_ES    =       14H
S_FS    =       10H
S_GS    =       0cH
S_SS    =       08H
S_SAVEAREA =    04H

        public  __int7
__int7  proc    near
        push    ss                      ; save SS for emulator
        push    ebx                     ; push emulator save area offset
        call    start_emulation         ; start emulating
        add     esp,8                   ; throw away SS/save area value
        pop     gs                      ; restore sregs
        pop     fs                      ; ...
        pop     es                      ; ...
        pop     ds                      ; ...
        popad                           ; restore gprs
        iretd                           ; return from interrupt

start_emulation:
;;      get_st0                         ; get st*10 into edi
p_extended:
exit:   mov     ebp,esp                 ; get access to saved registers

else ;===================================================================
;
;       entry point for 387 Emulator under DOS-extenders
;
; from push instructions
Push_DS         =       4
Push_SS         =       Push_DS+2
Push_ES         =       Push_DS+4

; from pushad instruction
Push_EDI        =       Push_ES+4
Push_ESI        =       Push_EDI+4
Push_EBP        =       Push_ESI+4
Push_ESP        =       Push_EBP+4
Push_EBX        =       Push_ESP+4
Push_EDX        =       Push_EBX+4
Push_ECX        =       Push_EDX+4
Push_EAX        =       Push_ECX+4

; from dos extender's umbrella interrupt handler
X_EIP           =       Push_EAX+4
X_CS            =       X_EIP+4
X_FL            =       X_CS+4
Orig_EIP        =       X_FL+4
Orig_CS         =       Orig_EIP+4
Orig_FL         =       Orig_CS+4
Orig_ESP        =       Orig_FL+4
Orig_SS         =       Orig_ESP+4
Orig_ES         =       Orig_SS+4
Orig_DS         =       Orig_ES+4
Orig_FS         =       Orig_DS+4
Orig_GS         =       Orig_FS+4
X_INFO          =       Orig_GS+4
X_INUM          =       X_INFO+4
Orig_CR2        =       X_INUM+4

S_DS            = Push_DS
S_SS            = Push_SS
S_ES            = Push_ES
S_EDI           = Push_EDI
S_ESI           = Push_ESI
S_EBP           = Push_EBP
S_ESP           = Push_ESP
S_EBX           = Push_EBX
S_EDX           = Push_EDX
S_ECX           = Push_ECX
S_EAX           = Push_EAX
S_EIP           = Orig_EIP
S_CS            = Orig_CS
S_FL            = Orig_FL

;
;       entry point for Phar Lap version 3.0
;
adj     =  3*4

        public  __int7_pl3

        align   4
__int7_pl3  proc near
        sti                             ; interrupts back on
        pushad                          ; save gprs
        mov     ebp,esp                 ; get base
        push    dword ptr (Orig_ES)-adj[ebp]   ; push ES
        push    dword ptr (Orig_DS)-adj[ebp]   ; push DS
        mov     cx,Orig_SS-adj[ebp]     ; ...
        mov     S_SS-adj[ebp],cx        ; save SS
        mov     ecx,Orig_ESP-adj[ebp]   ; get original esp
        mov     S_ESP-adj[ebp],ecx      ; ...
        call    start_emulation         ; start emulating
        pop     ds                      ; restore DS
        pop     es                      ; restore ES
        popad                           ; restore gprs
        iretd                           ; return from interrupt
__int7_pl3 endp

        public  __int7_X32VM

        align   4
__int7_X32VM    proc    near
        sti                             ; interrupts back on
        mov     eax,12[esp]             ; get pointer to int_struct
        push    dword ptr ss:20[eax]    ; push original CS
        push    dword ptr ss:16[eax]    ; push original EIP
        push    eax                     ; save address of int_struct
        push    eax                     ; 2 more pushs to line up the stack
        push    eax                     ; ...
;;;;;   pushad                          ; save gprs
;;;     to avoid 386 chip bug when running on a 16-bit stack e.g. X32VM
;;;     we will do individual push instructions rather than using "pushad"
;;;                                                     22-nov-93
        push    dword ptr ss:[eax]      ; - eax
        push    ecx                     ; - ecx
        push    edx                     ; - edx
        push    ebx                     ; - ebx
        push    dword ptr ss:28[eax]    ; - push original ESP value
        mov     eax,ebp                 ; - get ebp
        push    eax                     ; - ebp
        push    esi                     ; - esi
        push    edi                     ; - edi
;;;                                     ; end of "pushad"
        push    es                      ; save es
        push    ds                      ; ...ds
        mov     2[esp],ss               ; ...and ss
        call    start_emulation         ; start emulating
        pop     ds                      ; restore ds
        pop     es                      ; restore es
;;;;;   popad                           ; restore gprs
;;;     to avoid 386 chip bug when running on a 16-bit stack e.g. X32VM
;;;     we will do individual pop instructions rather than using "popad"
;;;                                                     22-nov-93
        pop     edi                     ; - edi
        pop     esi                     ; - esi
        pop     eax                     ; - EBP
        mov     ebp,eax                 ; - ...
        pop     eax                     ; - esp (ignore)
        pop     ebx                     ; - ebx
        pop     edx                     ; - edx
        pop     ecx                     ; - ecx
        pop     eax                     ; - eax
        xchg    eax,[esp]               ; get pointer to int_struct/save eax
        pop     dword ptr ss:[eax]      ; restore eax
        add     esp,2*4                 ; readjust esp
        pop     dword ptr ss:16[eax]    ; copy up new EIP
        add     esp,4                   ; skip over CS
        mov     eax,ss:[eax]            ; reload eax
        iretd                           ; return from interrupt
__int7_X32VM endp

        public  __int7

        align   4
__int7  proc    near
        sub     esp,3*4                 ; adjust esp to match V3 entry condition
        sti                             ; interrupts back on
;;;;;   pushad                          ; save gprs
;;;     to avoid 386 chip bug when running on a 16-bit stack e.g. X32VM
;;;     we will do individual push instructions rather than using "pushad"
;;;                                                     22-nov-93
        push    eax                     ; - eax
        mov     eax,esp                 ; - get esp
        add     eax,12+4+3*4            ; - set ESP to pre-interrupt value
        push    ecx                     ; - ecx
        push    edx                     ; - edx
        push    ebx                     ; - ebx
        push    eax                     ; - adjusted ESP value
        push    ebp                     ; - ebp
        push    esi                     ; - esi
        push    edi                     ; - edi
;;;                                     ; end of "pushad"
        push    es                      ; save es
        push    ds                      ; ...ds
        mov     2[esp],ss               ; ...and ss
        call    start_emulation         ; start emulating
        pop     ds                      ; restore ds
        pop     es                      ; restore es
        popad                           ; restore gprs
        add     esp,3*4                 ; readjust esp
        iretd                           ; return from interrupt

        align   4
start_emulation:
;;      get_st0                         ; get st*10 into edi

p_extended:
exit:   mov     ebp,esp                 ; get access to saved registers

endif
endif
    ifdef __WIN387__
        mov     esi,S_EIP[ebp]          ; get eip
        add     esi,WINBase             ; add base to get at eip in ring 0
    else
      ifdef SEGMENTED
        mov     esi,S_EIP[ebp]          ; get return address
        mov     ds,S_CS[ebp]            ; ...
      else
        mov     esi,S_EIP[ebp]
      endif
    endif
        mov     cx,S_DS[ebp]            ; default segment is ds
        mov     dx,S_SS[ebp]            ; default segment for [EBP] and [ESP]
        mov     al,[esi]                ; get possible prefix in al
        cmp     al,9Bh                  ; check for "fwait"
        jbe     prefix_byte             ; ... go check for possible prefix
endlup:
        mov     bl,al                   ; get opcode
        and     bl,0F8h                 ; check to see if 8087 opcode
        cmp     bl,0D8h                 ; ...
        jne     exit99                  ; exit if not 8087 opcode
        mov     ah,1[esi]               ; get modrm in ah
        add     esi,2                   ; bump past opcode and modrm byte
        and     al,7                    ; isolate real opcode portion 00000ooo
        cmp     ah,0C0H                 ; if its a memory reference
        jnb     stkins                  ; - then
        mov     bl,ah                   ; - get r/m bits in bl        mmRRRrrr
        mov     bh,ah                   ; - get r/m bits in bh        mmRRRrrr
        shr     bh,3                    ; - ...                       000mmRRR
        and     ebx,01807H              ; -                  000mm000 00000rrr
        or      bl,bh                   ; - glue them                 000mmrrr
        mov     bh,0                    ; - zero top bits

      ifdef SEGMENTED
        call    dword ptr cs:mrm[ebx*4] ; - do effective address calcn
      else
        call    dword ptr    mrm[ebx*4] ; - do effective address calcn
      endif
      ifdef SEGMENTED
        mov     es,cx                   ; - segment of memory operand in es
      endif

⌨️ 快捷键说明

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