386fpemu.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 1,702 行 · 第 1/5 页
INC
1,702 行
;*****************************************************************************
;*
;* Open Watcom Project
;*
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;* ========================================================================
;*
;* This file contains Original Code and/or Modifications of Original
;* Code as defined in and that are subject to the Sybase Open Watcom
;* Public License version 1.0 (the 'License'). You may not use this file
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;* provided with the Original Code and Modifications, and is also
;* available at www.sybase.com/developer/opensource.
;*
;* The Original Code and all software distributed under the License are
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;* NON-INFRINGEMENT. Please see the License for the specific language
;* governing rights and limitations under the License.
;*
;* ========================================================================
;*
;* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;* DESCRIBE IT HERE!
;*
;*****************************************************************************
ifdef _DEBUG
if _OS eq _NW
extrn puts_ : near
NC = 0
else
NC = '$'
endif
endif
ifndef __WIN387__
extrn __GETDS : near
if _OS eq _QNX
extrn "C",__FPEhandler : near
else
extrn __FPE_exception_ : near
endif
endif
ifdef _DEBUG
public badop,prtnyi,my87,mrm,sib,memop,stkop,stkop1
endif
sarea struc
control dw 0,0 ; CW
status dw 0,0 ; SW
tags dw 0,0 ; TAG
iptr dd 0,0 ; instruction pointer
dataptr dd 0,0 ; data operand pointer
fpstack db 80 dup(0) ; 8 tbyte reals for stack
fptemp db 10 dup(0) ; temporary tbyte real
stktop dd 0 ; stack top * 10
ifndef __WIN387__
precrtn dd 0 ; address of precision rtn
endif
sarea ends
NDP_SIZE equ 108
ENV_SIZE equ 28
include fpubits.inc
startdata
if _OS ne _QNX
my87 sarea <>
endif
ifdef __WIN387__
precrtn dd p_extended ; address of precision rtn
endif
ifdef _DEBUG
nyimsg db ": not yet implemented",0dH,0aH,NC
illopmsg db "Illegal instruction encountered by 8087 emulator",0dH,0aH,NC
endif
ifdef __WIN387__
WIN8087 dd 0
WINBase dd 0
WINVMHandle dd 0
endif
enddata
include consts.inc
include tentab.inc
include tagtab.inc
include fpucc.inc
ifdef SEGMENTED
TENTBL equ cs:tentab
TAGTBL equ cs:tagtab
else
TENTBL equ tentab
TAGTBL equ tagtab
endif
;
; NOTE: to make this damn thing work for windows, you have to use
; MASM5. ANNNNND, masm5 is too stupid to figure out that these
; offsets should be 32-bit offsets, SOOOOOO, you have to use
; this stupid macro to make it work. The macro
; should be commented out if using masm, since masm doesn't
; understand. I hate microsoft.
align 4
mrm dd m00000 ; mod r/m byte select table
dd m00001
dd m00010
dd m00011
dd dosib
dd m00101
dd m00110
dd m00111
dd m01000
dd m01001
dd m01010
dd m01011
dd dosib
dd m01101
dd m01110
dd m01111
dd m10000
dd m10001
dd m10010
dd m10011
dd dosib
dd m10101
dd m10110
dd m10111
sib dd m00000 ; sib base/displacement table
dd m00001
dd m00010
dd m00011
dd s00100
dd m00101
dd m00110
dd m00111
dd m01000
dd m01001
dd m01010
dd m01011
dd s01100
dd m01101
dd m01110
dd m01111
dd m10000
dd m10001
dd m10010
dd m10011
dd s10100
dd m10101
dd m10110
dd m10111
memop dd m00,m01,m02,m03,m04,m05,m06,m07 ; memory instr
dd m10,m11,m12,m13,m14,m15,m16,m17 ; select table
dd m20,m21,m22,m23,m24,m25,m26,m27
dd m30,m31,m32,m33,m34,m35,m36,m37
dd m40,m41,m42,m43,m44,m45,m46,m47
dd m50,m51,m52,m53,m54,m55,m56,m57
dd m60,m61,m62,m63,m64,m65,m66,m67
dd m70,m71,m72,m73,m74,m75,m76,m77
stkop dd s00,s01,s02,s03,s04,s05,s06,s07 ; stack operand
dd s10,s11,s12,s13,s14,s15,s16,s17 ; select table
dd s20,s21,s22,s23,s24,s25,s26,s27
dd s30,s31,s32,s33,s34,s35,s36,s37
dd s40,s41,s42,s43,s44,s45,s46,s47
dd s50,s51,s52,s53,s54,s55,s56,s57
dd s60,s61,s62,s63,s64,s65,s66,s67
dd s70,s71,s72,s73,s74,s75,s76,s77
dd calc_st0 ; _0_ entries
dd calc_sti ; _i_ entries
;
; stkop1 table entries contain an index into stkop table
; _0_ indicates that the result will be stored in st(0)
; _i_ indicates that the result will be stored in st(i)
_0_ equ 100o
_i_ equ 101o
stkop1 db _0_,_0_,02o,03o,_i_,_0_,_i_,_0_ ; stack operand
db _0_,_0_,12o,13o,_i_,_0_,_i_,_0_ ; select table
db _0_,21o,22o,23o,_0_,_0_,26o,_0_
db _0_,_0_,32o,33o,_0_,_0_,36o,_0_
db _0_,41o,42o,43o,_i_,_0_,_i_,47o
db _0_,51o,52o,53o,_i_,_0_,_i_,57o
db _0_,61o,62o,63o,_i_,65o,_i_,67o
db _0_,71o,72o,73o,_i_,75o,_i_,77o
get_st0 macro
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
endm
;; and edi,SW_ST ; - ...
;; shr edi,SW_ST_SHIFT ; - ...
;; lea edi,[edi+edi*4] ; - ... times 5
;; add edi,edi ; - ... ... times 2
;; endm
jmptab macro a,b,c,d,e,f,g,h
local table
jmp dword ptr cs:table[ebx*4]
table dd a
dd b
dd c
dd d
dd e
dd f
dd g
dd h
endm
saveflg macro ; MACRO
inc eax ; -1,0,1,2 -> 0,1,2,3
ifdef SEGMENTED
mov dx,ds:[ebp].status ; get status word
else
mov dx, [ebp].status ; get status word
endif
and dx,NOT SW_CC ; turn off C0,C1,C2,C3
ifdef SEGMENTED
or dh,cs:fpbits[eax] ; turn on new C0,C1,C2,C3
mov ds:[ebp].status,dx ; save in status word
else
or dh, fpbits[eax] ; turn on new C0,C1,C2,C3
mov [ebp].status,dx ; save in status word
endif
endm
savecc macro ; MACRO
and eax,7 ; keep low order 3 bits of quot
ifdef SEGMENTED
mov dx,ds:[ebp].status ; get status word
and dx,NOT SW_CC ; turn off C0,C1,C2,C3
or dh,cs:ccbits[eax] ; turn on new C0,C1,C3
mov ds:[ebp].status,dx ; save in status word
else
mov dx, [ebp].status ; get status word
and dx,NOT SW_CC ; turn off C0,C1,C2,C3
or dh, ccbits[eax] ; turn on new C0,C1,C3
mov [ebp].status,dx ; save in status word
endif
endm
tag_st0 macro newtag
mov bx,TAGTBL[edi].t_off ; get turn off mask
ifdef SEGMENTED
and ds:[ebp].tags,bx ; turn off the bits
else
and [ebp].tags,bx ; turn off the bits
endif
ifdif <newtag>,<t_valid>
mov bx,TAGTBL[edi].&newtag ; get new bits
ifdef SEGMENTED
or ds:[ebp].tags,bx ; turn on new bits
else
or [ebp].tags,bx ; turn on new bits
endif
endif
endm
tag_sti macro newtag
mov bx,TAGTBL[esi].t_off ; get turn off mask
ifdef SEGMENTED
and ds:[ebp].tags,bx ; turn off the bits
else
and [ebp].tags,bx ; turn off the bits
endif
ifdif <newtag>,<t_valid>
mov bx,TAGTBL[esi].&newtag ; get new bits
ifdef SEGMENTED
or ds:[ebp].tags,bx ; turn on new bits
else
or [ebp].tags,bx ; turn on new bits
endif
endif
endm
pushstk macro
decstp
tag_st0 t_valid
; if full entry, to incstp and exception!
; mark as valid, zero or invalid
endm
decstp macro ; MACRO
movzx edi,TENTBL[edi].t_prev ; dec stack pointer
mov bx,TENTBL[edi].t_stktop ; update top of stack pointer
ifdef SEGMENTED
and ds:[ebp].status,NOT SW_ST ;...
or word ptr ds:[ebp].status,bx ; put back into SW_ST
mov ds:[ebp].stktop,edi
else
and [ebp].status,NOT SW_ST ;...
or word ptr [ebp].status,bx ; put back into SW_ST
mov [ebp].stktop,edi
endif
endm
popstk macro
; if empty entry, take exception
; mark as empty
tag_st0 t_empty
incstp
endm
incstp macro ; MACRO
movzx edi,TENTBL[edi].t_next ; inc stack pointer
mov bx,TENTBL[edi].t_stktop ; update top of stack pointer
ifdef SEGMENTED
and ds:[ebp].status,NOT SW_ST ;...
or word ptr ds:[ebp].status,bx ; put back into SW_ST
mov ds:[ebp].stktop,edi
else
and [ebp].status,NOT SW_ST ;...
or word ptr [ebp].status,bx ; put back into SW_ST
mov [ebp].stktop,edi
endif
endm
done macro
jmp exit ; done instruction
endm
popstk_done macro
jmp popstk_exit ; popstk then exit
endm
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?