fpe86.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 1,454 行 · 第 1/4 页
INC
1,454 行
extrn __GETDS : near
_DOS = 1
_OS2 = 2
_BP equ BP
_SP equ SP
_AX equ AX
_BX equ BX
_CX equ CX
_DX equ DX
_SI equ SI
_DI equ DI
NC = '$'
ifdef _DEBUG
public badop,prtnyi,my87,modrm,memop,stkop,stkop1
endif
sarea struc
control dw 0 ; CW
status dw 0 ; SW
tags dw 0 ; TAG
iptr dw 0,0 ; instruction pointer
dptr dw 0,0 ; data operand pointer
fpstack db 80 dup(0) ; 8 tbyte reals for stack
fptemp db 10 dup(0) ; temporary tbyte real
precrtn dw 0 ; address of precision routine
sarea ends
NDP_SIZE equ 94
ENV_SIZE equ 14
include fpubits.inc
ifdef __QNX__
extrn "C",__FPEhandler : near;
endif
_DATA segment word public 'DATA'
ifndef __QNX__
extrn "C",__FPE_handler : dword
my87 sarea <>
endif
ifdef _DEBUG
nyimsg db ": not yet implemented",0dH,0aH,NC
illopmsg db "Illegal instruction encountered by 8087 emulator",0dH,0aH,NC
endif
_DATA ends
DGROUP group _DATA
assume ds:DGROUP
include consts.inc
include tentab.inc
include tagtab.inc
include fpucc.inc
ifdef QNX32
S_FL = 38H
S_CS = 34H
S_IP = 30H
S_AX = 2CH
S_CX = 28H
S_DX = 24H
S_BX = 20H
S_SP = 1CH
S_BP = 18H
S_SI = 14H
S_DI = 10H
S_DS = 0CH
S_ES = 08H
S_FS = 04H
S_GS = 00H
else
ifdef __PROTMODE__
ifndef __QNX__
DPMI_SS = 22H
DPMI_SP = 20H
S_FL = 1EH
S_CS = 1CH
S_IP = 1AH
;
; 3 words in here for DPMI (error code, return CS, return IP)
;
else ; __QNX__
S_FL = 18H
S_CS = 16H
S_IP = 14H
endif
else ; not __PROTMODE__
S_FL = 18H
S_CS = 16H
S_IP = 14H
endif
S_AX = 12H
S_CX = 10H
S_DX = 0EH
S_BX = 0CH
S_SP = 0AH
S_BP = 08H
S_SI = 06H
S_DI = 04H
S_DS = 02H
S_ES = 00H
endif
S_MY87 = S_SP
get_st0 macro
mov ax,word ptr [bx].status ; - di gets idx of top of stack
mov al,ah ; - move to bottom
and ax,0038h ; - isolate register number
mov di,ax ; - save 8 * register number
shr ax,1 ; - calc 2 * register number
shr ax,1 ; - ...
add di,ax ; - calc 10 * register number
endm
jmptab macro a,b,c,d,e,f,g,h
local table
mov bl,dh
and bx,7
shl bx,1
jmp word ptr cs:table[bx]
table dw a
dw b
dw c
dw d
dw e
dw f
dw g
dw h
endm
_lea macro reg,what
IFIDN <what>,<st>
lea reg,[di+bp].fpstack
ELSE
IFIDN <what>,<st(i)>
lea reg,[si+bp].fpstack
ELSE
.ERRDIF <what>,<temp>
lea reg,[bp].fptemp
ENDIF
ENDIF
endm
saveflg macro ; MACRO
inc ax ; -1,0,1,2 -> 0,1,2,3
mov dx,ds:[bp].status ; get status word
and dx,NOT SW_CC ; turn off C0,C1,C2,C3
mov bx,ax ; turn on new bits
or dh,byte ptr cs:fpbits[bx] ; ...
mov ds:[bp].status,dx ; save in status word
endm
savecc macro ; MACRO
and ax,7 ; keep low order 3 bits of quot
mov dx,ds:[bp].status ; get status word
and dx,NOT SW_CC ; turn off C0,C1,C2,C3
mov bx,ax ; turn on new bits
or dh,cs:ccbits[bx] ; ...
mov ds:[bp].status,dx ; save in status word
endm
tag_st0 macro new_tag
IFDIF <new_tag>,<t_empty>
mov bx,cs:tagtab[di].t_off ; get turn off mask
and ds:[bp].tags,bx ; turn off the bits
ENDIF
IFDIF <new_tag>,<t_valid>
mov bx,cs:tagtab[di].&new_tag ; get new bits
or ds:[bp].tags,bx ; turn on new bits
ENDIF
endm
tag_sti macro new_tag
IFDIF <new_tag>,<t_empty>
mov bx,cs:tagtab[si].t_off ; get turn off mask
and ds:[bp].tags,bx ; turn off the bits
ENDIF
IFDIF <new_tag>,<t_valid>
mov bx,cs:tagtab[si].&new_tag ; get new bits
or ds:[bp].tags,bx ; turn on new bits
ENDIF
endm
pushstk macro
decstp
; if full entry, to incstp and exception!
; mark as valid, zero or invalid
tag_st0 t_valid
endm
decstp macro ; MACRO
mov di,cs:tentab[di].t_prev ; dec stack pointer
mov bx,cs:tentab[di].t_stktop ; update top of stack pointer
and ds:[bp].status,NOT SW_ST ;...
or word ptr ds:[bp].status,bx ; put back into SW_ST
endm
popstk macro
; if empty entry, take exception
; mark as empty
tag_st0 t_empty
incstp
endm
incstp macro ; MACRO
mov di,cs:tentab[di].t_next ; inc stack pointer
mov bx,cs:tentab[di].t_stktop ; update top of stack pointer
and ds:[bp].status,NOT SW_ST ;...
or word ptr ds:[bp].status,bx ; put back into SW_ST
endm
done macro
jmp exit ; done instruction
endm
popstk_done macro
jmp popstk_exit ; popstk then exit
endm
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
jmp ds:[bp].precrtn ; done instruction
endm
save_regs macro
push ax ; save registers (same order as pusha)
push cx ; ...
push dx ; ...
push bx ; ...
push bp ; ...(sp)
push bp ; ...
push si ; ...
push di ; ...
push ds ; ...
push es ; ...
endm
getretaddr macro ; get return address
ifdef QNX32
mov si,S_IP[bp]
mov es,S_CS[bp]
else
les si,S_IP[bp]
endif
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; exception handling
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
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 for status and control word
; AH - exception code for signal handler
__Exception_HNDLR proc near
or byte ptr ds:[bp].status,AL ; indicate exception occurred
test byte ptr ds:[bp].control,AL ; if exception unmasked
_if e ; then
push si ; - save registers
push di ; - ...
push cx ; - ...
push es ; - ...
push ds ; - ...
sub sp,NDP_SIZE ; - allocate space for copy of 387
mov cx,ss ; - set ES=SS
mov es,cx ; - ...
mov si,bp ; - point to current copy
mov di,sp ; - point to temporary save area
mov cx,NDP_SIZE/2 ; - number of words to copy
cld ; - make sure forward direction
rep movsw ; - copy it
; call __GETDS ; - point DS to DGROUP
mov AL,AH ; - get exception code
mov AH,0 ; - ...
ifdef __QNX__
call __FPEhandler ; - jump to SIGFPE handler rtn
else
call __FPE_handler ; - 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 di,bp ; - point to current copy
mov si,sp ; - point to temporary save area
mov cx,NDP_SIZE/2 ; - number of words to copy
rep movsw ; - copy it
add sp,NDP_SIZE ; - deallocate space
pop ds ; - restore registers
pop es ; - ...
pop cx ; - ...
pop di ; - ...
pop si ; - ...
_endif ; endif
ret ; return
__Exception_HNDLR endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt int7() ; protected-mode programs trap to here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; QNX entry point: all registers have been saved on stack as above
; also ES:BX contains address of 120 byte save area
;
ifdef __PROTMODE__
public __int7
__int7 proc near
ifndef __QNX__
push ax ; dummy error code
push cs ; CS
call __dmy_int7 ; make stack look like DPMI exception
add sp,2 ; remove dummy error code
iret ; return from interrupt
__dmy_int7:
pusha ; save registers
push ds ; ...
push es ; ...
lea bx,my87 ; ...
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?