chipd32.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 992 行 · 第 1/3 页
ASM
992 行
fldcw [esp+PATCH_CW] ; mask exceptions & pc=80
; The following lines check the numerator exponent before scaling.
; This in order to prevent undeflow when scaling the numerator,
; which will cause a denormal exception flag to be set when the
; actual divide is preformed. This flag would not have been set
; normally. If there is a risk of underflow, the scale factor is
; 17/16 instead of 15/16.
;
mov eax, [esp+MAIN_NUMER+8] ; test numerator exponent
and eax, 07fffh
cmp eax, 00001h
je small_numer
fmul fdiv_scale_1 ; scale denominator by 15/16
fxch
fmul fdiv_scale_1 ; scale numerator by 15/16
fxch
;
; The next line restores the users control word. If the incoming
; control word had the underflow exception masked and precision
; control set to 80 bits, this line can be omitted.
;
fldcw [esp+PREV_CW] ; restore caller's control word
fdivp st(1), st ; use of hardware is OK.
ret
small_numer:
fmul fdiv_scale_2 ; scale denominator by 17/16
fxch
fmul fdiv_scale_2 ; scale numerator by 17/16
fxch
;
; The next line restores the users control word. If the incoming
; control word had the underflow exception masked and precision
; control set to 80 bits, this line can be omitted.
;
fldcw [esp+PREV_CW] ; restore caller's control word
fdivp st(1), st ; use of hardware is OK.
ret
denormal:
mov eax, [esp+MAIN_DENOM] ; test for whole mantissa == 0
or eax, [esp+MAIN_DENOM+4] ; test for whole mantissa == 0
jnz denormal_divide_scaled ; denominator is not zero
invalid_denom: ; zero or invalid denominator
fdivp st(1), st ; use of hardware is OK.
ret
denormal_divide_scaled:
mov eax, [esp + MAIN_DENOM + 8] ; get exponent
and eax, 07fffh ; check for zero exponent
jnz invalid_denom ;
;
; The following six lines turn off exceptions and set the
; precision control to 80 bits. The former is necessary to
; force any traps to be taken at the divide instead of the scaling
; code. The latter is necessary in order to get full precision for
; codes with incoming 32 and 64 bit precision settings. If
; it can be guaranteed that before reaching this point, the underflow
; exception is masked and the precision control is at 80 bits, these
; five lines can be omitted.
;
fnstcw [esp+PREV_CW] ; save caller's control word
mov eax, [esp+PREV_CW]
or eax, 033fh ; mask exceptions, pc=80
and eax, 0f3ffh ; set rounding mode to nearest
mov [esp+PATCH_CW], eax
fldcw [esp+PATCH_CW] ; mask exceptions & pc=80
mov eax, [esp + MAIN_NUMER +8] ; test numerator exponent
and eax, 07fffh ; check for denormal numerator
je denormal_numer
cmp eax, 07fffh ; NaN or infinity
je invalid_numer
mov eax, [esp + MAIN_NUMER + 4] ; get bits 32..63 of mantissa
add eax, eax ; shift the first bit into carry
jnc invalid_numer ; if there is no carry, we have an
; invalid numer
jmp numer_ok
denormal_numer:
mov eax, [esp + MAIN_NUMER + 4] ; get bits 32..63 of mantissa
add eax, eax ; shift the first bit into carry
jc invalid_numer ; if there is a carry, we have an
; invalid numer
numer_ok:
fxch
fstp st ; pop numerator
fld st ; make copy of denominator
fmul dword ptr[one_shl_63] ; make denominator not denormal
fstp tbyte ptr [esp+MAIN_DENOM] ; save modified denominator
fld tbyte ptr [esp+MAIN_NUMER] ; load numerator
fxch ; restore proper order
fwait
; The next line restores the users control word. If the incoming
; control word had the underflow exception masked and precision
; control set to 80 bits, this line can be omitted.
;
fldcw [esp+PREV_CW] ; restore caller's control word
jmp retry ; start the whole thing over
invalid_numer:
;
; The next line restores the users control word. If the incoming
; control word had the underflow exception masked and precision
; control set to 80 bits, this line can be omitted.
;
fldcw [esp + PREV_CW]
fdivp st(1), st ; use of hardware is OK.
ret
fdiv_main_routine ENDP
public __fdiv_fpr
defpe __fdiv_fpr
sub esp, STACK_SIZE
jmp dword ptr dispatch_table[eax*4]
label0:
fdiv st,st(0) ; D8 F0 FDIV ST,ST(0)
add esp, STACK_SIZE
ret
label1:
add esp, STACK_SIZE
int ILLEGAL_OPC
label2:
fdivr st,st(0) ; D8 F8 FDIVR ST,ST(0)
add esp, STACK_SIZE
ret
label3:
add esp, STACK_SIZE
int ILLEGAL_OPC
label4:
fdiv st(0),st ; DC F8/D8 F0 FDIV ST(0),ST
add esp, STACK_SIZE
ret
label5:
fdivp st(0),st ; DE F8 FDIVP ST(0),ST
add esp, STACK_SIZE
ret
label6:
fdivr st(0),st ; DC F0/DE F0 FDIVR ST(0),ST
add esp, STACK_SIZE
ret
label7:
fdivrp st(0),st ; DE F0 FDIVRP ST(0),ST
add esp, STACK_SIZE
ret
label8:
fdiv_st 1, 0
ret
label9:
add esp, STACK_SIZE
int ILLEGAL_OPC
label10:
fdivr_st 1, 0
ret
label11:
add esp, STACK_SIZE
int ILLEGAL_OPC
label12:
fdiv_sti 1, 0
ret
label13:
fdivp_sti 1, 0
ret
label14:
fdivr_sti 1, 0
ret
label15:
fdivrp_sti 1, 0
ret
label16:
fdiv_st 2, 1
ret
label17:
add esp, STACK_SIZE
int ILLEGAL_OPC
label18:
fdivr_st 2, 1
ret
label19:
add esp, STACK_SIZE
int ILLEGAL_OPC
label20:
fdiv_sti 2, 1
ret
label21:
fdivp_sti 2, 1
ret
label22:
fdivr_sti 2, 1
ret
label23:
fdivrp_sti 2, 1
ret
label24:
fdiv_st 3, 2
ret
label25:
add esp, STACK_SIZE
int ILLEGAL_OPC
label26:
fdivr_st 3, 2
ret
label27:
add esp, STACK_SIZE
int ILLEGAL_OPC
label28:
fdiv_sti 3, 2
ret
label29:
fdivp_sti 3, 2
ret
label30:
fdivr_sti 3, 2
ret
label31:
fdivrp_sti 3, 2
ret
label32:
fdiv_st 4, 3
ret
label33:
add esp, STACK_SIZE
int ILLEGAL_OPC
label34:
fdivr_st 4, 3
ret
label35:
add esp, STACK_SIZE
int ILLEGAL_OPC
label36:
fdiv_sti 4, 3
ret
label37:
fdivp_sti 4, 3
ret
label38:
fdivr_sti 4, 3
ret
label39:
fdivrp_sti 4, 3
ret
label40:
fdiv_st 5, 4
ret
label41:
add esp, STACK_SIZE
int ILLEGAL_OPC
label42:
fdivr_st 5, 4
ret
label43:
add esp, STACK_SIZE
int ILLEGAL_OPC
label44:
fdiv_sti 5, 4
ret
label45:
fdivp_sti 5, 4
ret
label46:
fdivr_sti 5, 4
ret
label47:
fdivrp_sti 5, 4
ret
label48:
fdiv_st 6, 5
ret
label49:
add esp, STACK_SIZE
int ILLEGAL_OPC
label50:
fdivr_st 6, 5
ret
label51:
add esp, STACK_SIZE
int ILLEGAL_OPC
label52:
fdiv_sti 6, 5
ret
label53:
fdivp_sti 6, 5
ret
label54:
fdivr_sti 6, 5
ret
label55:
fdivrp_sti 6, 5
ret
label56:
fdiv_st 7, 6
ret
label57:
add esp, STACK_SIZE
int ILLEGAL_OPC
label58:
fdivr_st 7, 6
ret
label59:
add esp, STACK_SIZE
int ILLEGAL_OPC
label60:
fdiv_sti 7, 6
ret
label61:
fdivp_sti 7, 6
ret
label62:
fdivr_sti 7, 6
ret
label63:
fdivrp_sti 7, 6
ret
__fdiv_fpr ENDP
__fdivp_sti_st PROC NEAR
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?