fpe86.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 1,454 行 · 第 1/4 页
INC
1,454 行
mov ax,ss ; put SS in DS
mov ds,ax ; ...
mov bp,sp ; get access to registers
jmp short _comint7 ; goto common code
;
; come here for DPMI hosts (e.g. Windows 3.1)
;
public __DPMI_int7
__DPMI_int7:
pusha ; save registers
push ds ; ...
push es ; ...
lea bx,my87 ; ...
mov bp,sp ; get access to registers
mov ds,DPMI_SS[bp] ; set ds = user's SS
else
mov ax,ss ; put SS in DS
mov ds,ax ; ...
mov bp,sp ; get access to registers
endif
_comint7:cld ; make sure forward direction
mov S_MY87[bp],bx ; save offset of save area
get_st0 ; get offset of stack top in DI
p_extended: ; nothing to do
;
; peek at next instruction to see if it is also an emulator interrupt
;
exit: mov bp,sp ; get access to saved registers
mov cx,S_DS[bp] ; get default data segment
mov ax,ds ; segment register for [bp] reference
getretaddr ; get return address
luup: mov dl,es:[si] ; get possible prefix in al
sub dl,26H ; if its es:
js short endlup ; if signed, then not a prefix byte
je short is_es ; - continue with next byte
cmp dl,09BH-26H ; check for "fwait" opcode
je inc_si ; - yes, just skip over it
sub dl,08H ; if its cs:
je short is_cs ; - record cs in cx and continue
sub dl,08H ; if its ss:
je short is_ss ; - record ss in cx and continue
sub dl,08H ; if its ds:
je short is_ds ; - record ds in cx and continue
sub dl,26H ; if its fs:
je short is_fs ; - record fs in cx and continue
dec dl ; if its gs:
je short is_gs ; - record gs in cx and continue
dec dl ; if its operand length
je short inc_si ; - continue with next byte
dec dl ; if its address length
jne short endlup ; - its not handled!!!!
inc_si: inc si ; just bump past prefix
jmp luup ;
is_cs: mov cx,S_CS[bp]
mov ax,cx ; segment for [bp]
inc si ; bump past prefix
jmp luup ;
is_ds: mov cx,S_DS[bp]
mov ax,cx ; segment for [bp]
inc si ; bump past prefix
jmp luup ;
is_ss: mov cx,ds ; (DS contains user's SS)
mov ax,cx ; segment for [bp]
inc si ; bump past prefix
jmp luup ;
is_es: mov cx,S_ES[bp] ;
mov ax,cx ; segment for [bp]
inc si ; bump past prefix
jmp luup ;
is_fs:;;; mov cx,fs ;
inc si ; bump past prefix
jmp luup ;
is_gs:;;; mov cx,gs ;
inc si ; bump past prefix
jmp luup ;
endlup: ; segment of memory operand in cx
mov dx,es:[si] ; load up opcode + modrm
inc si ; point es:si at rest of instruction
inc si ; ...
mov bl,dl ; get opcode
and dl,07H ; get opcode (0-7) into dl
and bl,0F8h ; isolate top bits
cmp bl,0D8h ; if it is an 8087 opcode
je emulate ; then execute it
jmp exit99 ; otherwise exit
__int7 endp
else ; not __PROTMODE__
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt int34() ; int 34h to int 3Bh all come here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public __int34
__int34 proc near
sti ; interrupts back on
save_regs ; save registers (same order as pusha)
mov bp,sp ; get access to registers
mov cx,ds ; save data segment in CX
cld ; make sure forward direction
call __GETDS ; point ds at "8087" save area
lea bx,my87 ; ...
mov S_MY87[bp],bx ; save offset of save area
get_st0 ; get offset of stack top in DI
mov ax,ss ; segment register for [bp] reference
getretaddr ; get return address
mov dx,es:-1[si] ; load up opcode + modrm
inc si ; point ds:si at rest of instruction
and dl,0FH ; get opcode (0-7) into dl
sub dl,4 ; ... (was 34-3B)
jmp emulate ; go emulate instruction
__int34 endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt int3c() ; segment override present
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public __int3c
__int3c proc near
sti ; interrupts back on
save_regs ; save registers (same order as pusha)
mov bp,sp ; get access to registers
cld ; make sure forward direction
call __GETDS ; point ds at "8087" save area
lea bx,my87 ; ...
mov S_MY87[bp],bx ; save offset of save area
get_st0 ; get offset of stack top in DI
getretaddr ; get return address
mov dh,es:[si] ; load up opcode, seg override
inc si ; point ds:si at rest of instruction
next_int3c:
mov dl,dh ; get opcode + segment override
mov dh,es:[si] ; get modrm byte
inc si ; ...
mov bl,dl ; get segment override
_guess ; guess: load cx with segment register
mov cx,S_DS[bp] ; - assume DS
and bl,0C0h ; - isolate segment override bits
_quif e ; - quit if 00 (DS)
mov cx,S_CS[bp] ; - assume CS (10)
shl bl,1 ; - shift out top bit
_quif e ; - quit if 10 (CS)
mov cx,ss ; - assume SS (01)
_quif nc ; - quit if 01 (SS)
mov cx,S_ES[bp] ; - it has to be ES (11)
_endguess ; endguess
mov ax,cx ; segment register for [bp] reference
and dl,0FH ; get opcode (0-7) into al
sub dl,8 ; ... was D8-DF
jmp short emulate ; do the emulation
__int3c endp
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AT THIS POINT ...
;; DL = OPCODE 0-7
;; DH = MODRM byte
;; ES:SI = pointer to rest of instruction (or next instruction)
;; CX = has the segment for a data reference (if any)
;; AX = segment register to be used for [bp] reference
;; DI = offset into 8087 register stack to stack top
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mem_inst:
mov bl,dh ; get mmxxxrrr bits in bl
shr bl,1 ; ... 0mmxxxrr
shr bl,1 ; ... 00mmxxxr
shr bl,1 ; ... 000mmxxx
and bl,018H ; isolate them 000mm000
mov bh,dh ; get r/m bits in bh mmxxxrrr
and bh,7 ; isolate them 00000rrr
or bl,bh ; glue them 000mmrrr
mov bh,0 ; zero top byte
shl bx,1 ; make it an index
call word ptr cs:modrm[bx] ; do effective address calcn
mov S_IP[bp],si ; zap return address
mov es,cx ; get segment for memory operand
mov si,ax ; get offset for memory operand
mov bl,dh ; get r/m bits again
and bl,038H ; isolate opcode portion
or bl,dl ; or in other part of opcode
shl bx,1 ; make it an index
mov bp,S_MY87[bp] ; point BP to save area
push word ptr cs:memop[bx] ; emulate the instruction
and bl,0Eh ; get index for load routine
jmp word ptr cs:loadrtn[bx] ; load memory operand into temp
ifndef __PROTMODE__
next_instruction:
mov dx,es:1[si] ; get next interrupt #, plus next byte
add si,3 ; skip past these bytes
sub dl,34h ; make sure it is int 34h to 3ch
cmp dl,3ch-34h ; ...
je next_int3c ; if int 3ch, go handle it
ja exit99 ; exit if not an emulator interrupt
mov ax,ss ; segment register for [bp] reference
mov cx,S_DS[bp] ; get segment register for memory opnd
endif
;
; fall into emulate for this instruction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AT THIS POINT ...
;; DL = OPCODE 0-7
;; DH = MODRM byte
;; ES:SI = pointer to rest of instruction (or next instruction)
;; CX = has the segment for a data reference (if any)
;; AX = segment register to be used for [bp] reference
;; DI = offset into 8087 register stack to stack top
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
emulate proc near
cmp dh,0C0H ; if its a memory reference
jb mem_inst ; then go execute it
mov S_IP[bp],si ; zap return address
mov bp,S_MY87[bp] ; point bp at "8087"
mov bl,dh ; get r/m bits again
and bx,038H ; isolate opcode portion
or bl,dl ; or in other part of opcode
shl bx,1 ; make it an index
jmp word ptr cs:stkop1[bx] ; jmp to prepare/emulation routine
_i_: push word ptr cs:stkop[bx] ; push address of emulation routine
mov bl,dh ; get "i" from ST(i)
and bl,7 ; ...
mov si,bx ; save "i" in si
add si,cs:tentab[di].t_regnum; calc. reg num of st(i)
and si,7 ; modulo 8
mov cx,si ; save a copy
add si,si ; i times 2
add si,si ; times 4
add si,cx ; times 5
add si,si ; times 10
_lea ax,st ; point AX to st(0)
_lea dx,st(i) ; point DX to st(i)
mov bx,ax ; result goes to st(0)
ret ; return to emulation routine
_r_: push word ptr cs:stkop[bx] ; push address of emulation routine
mov bl,dh ; get "i" from ST(i)
and bl,7 ; ...
mov si,bx ; save "i" in si
add si,cs:tentab[di].t_regnum; calc. reg num of st(i)
and si,7 ; modulo 8
mov cx,si ; save a copy
add si,si ; i times 2
add si,si ; times 4
add si,cx ; times 5
add si,si ; times 10
_lea ax,st(i) ; point AX to st(i)
_lea dx,st ; point DX to st(0)
mov bx,ax ; result goes to st(i)
ret ; return to emulation routine
exit99:
ifdef QNX32
add sp,8
comment ~
db 066h ; restore registers
pop gs
db 066h
pop fs
~
db 066h
pop es
db 066h
pop ds
db 066h
popa
db 066h
iret
else
pop es ; restore registers
pop ds ; ...
pop di ; ...
pop si ; ...
pop bp ; ...
pop bx ; ...(sp)
pop bx ; ...
pop dx ; ...
pop cx ; ...
pop ax ; ...
ifdef __PROTMODE__
ifndef __QNX__
retf ; return from interrupt
else
iret ; return from interrupt
endif
else
iret ; return from interrupt
endif
endif ; QNX32
ifndef __PROTMODE__
p_extended: ; nothing to do
;
; peek at next instruction to see if it is also an emulator interrupt
;
exit: mov bp,sp ; get access to saved registers
getretaddr ; get cs:ip of next instruction
cmp byte ptr es:[si],0CDh ; check for 'int' instruction
jne exit99
jmp next_instruction ; if it is, then go for it
endif
saveflg_popstk_exit:
saveflg
popstk_exit:
popstk
jmp exit
saveflg_exit:
saveflg
jmp exit
p_single: ; round result to single precision
lea bx,[bp+di].fpstack ; point to stack top
mov dx,0FF00h ; get mask of bits to keep
mov ax,4[bx] ; get top part
test ax,80H ; if have to round
_if ne ; then
test al,7FH ; - if half way between
_if e ; - then
_guess ; - - guess
cmp word ptr [bx],0 ; - - - quif rest is not zero
_quif ne ; - - - ...
cmp word ptr 2[bx],0 ; - - - quif rest is not zero
_quif ne ; - - - ...
shl DX,1 ; - - - adjust mask
_endguess ; - - enduess
_endif ; - endif
add word ptr 4[bx],0100h ; - round up
adc word ptr 6[bx],0 ; - ...
_if c ; - if exponent needs adjusting
mov word ptr 6[bx],8000h ; - - set fraction
inc word ptr 8[bx] ; - - increment exponent
; check for overflow ; - -
_endif ; - endif
_endif ; endif
and 4[bx],dx ; mask off bottom bits
mov word ptr 2[bx],0 ; zero the bottom part
mov word ptr [bx],0 ; zero the bottom part
jmp exit ; exit
p_double: ; round result to double precision
lea bx,[bp+di].fpstack ; point to stack top
mov dx,0F800h ; get mask of bits to keep
mov ax,[bx] ; get bottom part
test ax,0400H ; if rounding bit on
_if ne ; then
test ax,03FFH ; - if half way between
_if e ; - then
shl dx,1 ; - - adjust mask
_endif ; - endif
add word ptr [bx],0800h ; - round up
adc word ptr 2[bx],0 ; - ...
adc word ptr 4[bx],0 ; - ...
adc word ptr 6[bx],0 ; - ...
_if c ; - if exponent needs adjusting
mov word ptr 6[bx],8000h ; - - set fraction
inc word ptr 8[bx] ; - - increment exponent
; check for overflow ; - -
_endif ; - endif
_endif ; endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?