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