386fpemu.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 1,702 行 · 第 1/5 页
INC
1,702 行
ifdef __WIN387__
_guess ; - guess: have to map in address
cmp cx,S_DS[ebp] ; - - is it client's ds(/es/ss)?
_quif e ; - - yes, use pre-calculated base
cmp cx,S_CS[ebp] ; - - is it client's cs?
_quif e ; - - yes, use pre-calculated base
push eax ; - - save eax
movzx ecx,cx ; - - selector to map
VxDcall3 _SelectorMapFlat, WINVMHandle, ecx, 0
add ebx,eax ; - - add base of selector to relative
; offset from start of selector
pop eax ; - - restore eax
_admit ; - admit: can use WINBase
add ebx,WINBase ; - - shift address correctly!
_endguess ; - endguess
sub esi,WINBase ; - set to EIP within client's cs
mov S_EIP[ebp],esi ; - save it
else
mov S_EIP[ebp],esi ; - zap return address
endif
mov esi,ebx ; - get address
mov bl,ah ; - get r/m bits again
and ebx,038H ; - isolate opcode portion 0RRR000
or bl,al ; - or in other part of opcode 0RRRooo
getsavearea
get_st0 ; get st*10 into edi
ifdef SEGMENTED
jmp dword ptr cs:memop[ebx*4];- emulate the instruction
else
jmp dword ptr memop[ebx*4];- emulate the instruction
endif
luup: mov al,[esi] ; get possible prefix in al
cmp al,9Bh ; check for "fwait"
ja endlup ; ... go check for possible prefix
prefix_byte: je short inc_esi ; skip over "fwait" opcode
cmp al,26h ; check for "es:"
je short is_es ; - continue with next byte
cmp al,2Eh ; if its cs:
je short is_cs ; - record cs in dx and continue
cmp al,36H ; if its ss:
je short is_ss ; - record ss in dx and continue
cmp al,3EH ; if its ds:
je short is_ds ; - record ds in dx and continue
cmp al,64H ; if its fs:
je short is_fs ; - record fs in dx and continue
cmp al,65H ; if its gs:
je short is_gs ; - record gs in dx and continue
cmp al,66H ; if its operand length
je short inc_esi ; - continue with next byte
cmp al,67H ; if its address length
jne endlup ; - its not handled!!!!
inc_esi:inc esi ; just bump past prefix
jmp short luup ;
is_cs: mov cx,S_CS[ebp]
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
is_ds: mov cx,S_DS[ebp]
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
is_ss: mov cx,S_SS[ebp] ;
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
is_es: mov cx,S_ES[ebp] ;
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
is_fs:
ifdef __WIN387__
mov cx,S_FS[ebp]
else
mov cx,fs ;
endif
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
is_gs:
ifdef __WIN387__
mov cx,S_GS[ebp]
else
mov cx,gs ;
endif
mov edx,ecx ;
inc esi ; bump past prefix
jmp short luup ;
calc_st0:
calc_sti:
stkins: ; else
ifdef __WIN387__
sub esi,WINBase ; - set to addr in client
mov S_EIP[ebp],esi ; - save it
else
mov S_EIP[ebp],esi ; - zap return address
endif
getsavearea
; al has bottom 3 bits of opcode
; ah has modrm bytes
mov dl,ah ; - get modrm byte mmRRRrrr
and edx,038H ; - isolate opcode portion 00RRR000
or dl,al ; - + other part of opcode 00RRRooo
ifdef SEGMENTED
mov edi,dword ptr ds:[ebp].stktop;- di gets index of top of stack
else
mov edi,dword ptr [ebp].stktop;- di gets index of top of stack
endif
;; ifdef SEGMENTED
;; mov edi,dword ptr ds:[ebp].status;- di gets index of top of stack
;; else
;; mov edi,dword ptr [ebp].status;- di gets index of top of stack
;; endif
;; and edi,SW_ST ; - ...
;; shr edi,SW_ST_SHIFT ; - ...
mov bl,ah ; - get the "i" from ST(I) mmRRRrrr
and ebx,7 ; - ...
;; mov esi,ebx ; - ...
;; add esi,edi ; - add to top of stack
movzx esi,TENTBL[edi].t_regnum; - get top of stack reg #
add esi,ebx ; - plus "i"
and esi,7 ; - - modulo 7
;; lea edi,[edi+edi*4] ; - multiply ST index by 10
;; add edi,edi ; - ...
lea esi,[esi+esi*4] ; - multiply ST(i) index by 10
add esi,esi ; - ...
ifdef SEGMENTED
jmp dword ptr cs:stkop[edx*4]; - execute the instruction
else
jmp dword ptr stkop[edx*4]; - execute the instruction
endif
exit99:
;
; save updated stack top
;
ifdef __WIN387__
pop EBP ; restore EBP
endif
ret ; return from emulation
p_single: ; round result to single precision
lea EBX,[edi+ebp].fpstack ; point to stack top
mov EDX,0FFFFFF00h ; get mask of bits to keep
mov EAX,4[EBX] ; get top part
shl EAX,25 ; get rounding bit
_if c ; if have to round
_if e ; - if half way between
cmp dword ptr [EBX],0 ; - - if bottom part is also 0
_if e ; - - then (half way)
_shl EDX,1 ; - - - adjust mask
_endif ; - - endif
_endif ; - endif
add dword ptr 4[EBX],0100h ; - round up
_if c ; - if exponent needs adjusting
mov dword ptr 4[EBX],80000000h; - - set fraction
inc word ptr 8[EBX] ; - - increment exponent
; check for overflow
_endif ; - endif
_endif ; endif
and 4[EBX],EDX ; mask off bottom bits
mov dword ptr [EBX],0 ; zero the bottom part
jmp exit ; exit
p_double: ; round result to double precision
lea EBX,[edi+ebp].fpstack ; point to stack top
mov EDX,0FFFFF800h ; get mask of bits to keep
mov EAX,[EBX] ; get bottom part
shl EAX,22 ; get rounding bit
_if c ; if have to round
_if e ; - if half way between
_shl EDX,1 ; - - adjust mask
_endif ; - endif
add dword ptr [EBX],0800h ; - round up
adc dword ptr 4[EBX],0 ; - ...
_if c ; - if exponent needs adjusting
mov dword ptr 4[EBX],80000000h; - - set fraction
inc word ptr 8[EBX] ; - - increment exponent
; check for overflow
_endif ; - endif
_endif ; endif
and [EBX],EDX ; mask off bottom bits
jmp exit ; exit
saveflg_popstk_exit:
saveflg
popstk_exit:
popstk
jmp exit
saveflg_exit:
saveflg
jmp exit
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
; AH - exception code
;
__Exception_HNDLR proc near
ifdef SEGMENTED
or byte ptr ds:[ebp].status,AL ; indicate exception occurred
test byte ptr ds:[ebp].control,AL ; if exception unmasked
else
or byte ptr [ebp].status,AL ; indicate exception occurred
test byte ptr [ebp].control,AL ; if exception unmasked
endif
ifndef __WIN387__
_if e ; then
push ESI ; - save registers
push EDI ; - ...
push ECX ; - ...
push ES ; - ...
push DS ; - ...
sub ESP,NDP_SIZE ; - allocate space for copy of 387
mov CX,SS ; - set ES=SS
mov ES,CX ; - ...
mov ESI,EBP ; - point to current copy
mov EDI,ESP ; - point to temporary save area
mov ECX,108/4 ; - number of dwords to copy
cld ; - make sure forward direction
rep movsd ; - copy it
movzx EAX,AH ; - get exception code 21-jul-90
if _OS eq _QNX
call __FPEhandler ; - jump to SIGFPE handler rtn
else
call __FPE_exception_ ; - 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 EDI,EBP ; - point to current copy
mov ESI,ESP ; - point to temporary save area
mov ECX,108/4 ; - number of dwords to copy
cld ; - make sure forward direction
rep movsd ; - copy it
add ESP,NDP_SIZE ; - deallocate space
pop DS ; - restore registers
pop ES ; - ...
pop ECX ; - ...
pop EDI ; - ...
pop ESI ; - ...
_endif ; endif
endif
ret ; return
__Exception_HNDLR endp
;===========================MOD/RM calculations=================================
; NB: 16 bit addressing modes are NYI
DOMODRM macro disp,reg1
IFIDN <disp>,<D0> ; if D0
xor EBX,EBX ; - start ea at 0
ELSE ; else
IFIDN <disp>,<D8> ; - if D8
movsx EBX,byte ptr [ESI] ; - - start it off at D8
inc ESI ; - - bump past displacement
ELSE ; - else
.ERRDIF <disp>,<D32> ; - - it must be D32
mov EBX,dword ptr [ESI] ; - - pick up D32
add ESI,4
ENDIF ; - endif
ENDIF ; endif
IFNB <reg1> ; if there's a register
add EBX,®1[ebp] ; - add the register in too
IFIDN <reg1>,<S_EBP> ; - if register is EBP
mov ecx,edx ; - - get segment for [EBP]
ENDIF ; - endif
IFIDN <reg1>,<S_ESP> ; - if register is ESP
mov ecx,edx ; - - get segment for [EBP]
ENDIF ; - endif
ENDIF ; endif
ret ; return to caller
endm ; nice macro eh?
m00000: DOMODRM D0,S_EAX ; mod r/m byte actions
m00001: DOMODRM D0,S_ECX
m00010: DOMODRM D0,S_EDX
m00011: DOMODRM D0,S_EBX
s00100: DOMODRM D0,S_ESP
m00101: DOMODRM D32
m00110: DOMODRM D0,S_ESI
m00111: DOMODRM D0,S_EDI
m01000: DOMODRM D8,S_EAX
m01001: DOMODRM D8,S_ECX
m01010: DOMODRM D8,S_EDX
m01011: DOMODRM D8,S_EBX
s01100: DOMODRM D8,S_ESP
m01101: DOMODRM D8,S_EBP
m01110: DOMODRM D8,S_ESI
m01111: DOMODRM D8,S_EDI
m10000: DOMODRM D32,S_EAX
m10001: DOMODRM D32,S_ECX
m10010: DOMODRM D32,S_EDX
m10011: DOMODRM D32,S_EBX
s10100: DOMODRM D32,S_ESP
m10101: DOMODRM D32,S_EBP
m10110: DOMODRM D32,S_ESI
m10111: DOMODRM D32,S_EDI
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?