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 + -
显示快捷键?