|
|
subttl emfcom.asm - Comparison Instructions page ;******************************************************************************* ;emfcom.asm - Comparison Instructions ; ; Microsoft Confidential ; ; Copyright (c) Microsoft Corporation 1991 ; All Rights Reserved ; ;Purpose: ; FCOM,FCOMP,FCOMPP,FUCOM,FUCOMP,FUCOMPP,FTST,FXAM instructions ; ;Revision History: ; ; [] 09/05/91 TP Initial 32-bit version. ; ;*******************************************************************************
;******************************************************************************* ;Dispatch table for compare ; ;One operand has been loaded into ecx:ebx:esi ("source"), the other is ;pointed to by edi ("dest"). ; ;Tag of source is shifted. Tag values are as follows: .erre TAG_SNGL eq 0 ;SINGLE: low 32 bits are zero .erre TAG_VALID eq 1 .erre TAG_ZERO eq 2 .erre TAG_SPCL eq 3 ;NAN, Infinity, Denormal, Empty ;Any special case routines not found in this file are in emarith.asm tFcomDisp label dword ;Source (reg) Dest (*[di] = ST) dd ComDouble ;single single dd ComDouble ;single double dd ComDestZero ;single zero dd ComSpclDest ;single special dd ComDouble ;double single dd ComDouble ;double double dd ComDestZero ;double zero dd ComSpclDest ;double special dd ComSrcZero ;zero single dd ComSrcZero ;zero double dd ComEqual ;zero zero dd ComSpclDest ;zero special dd ComSpclSource ;special single dd ComSpclSource ;special double dd ComSpclSource ;special zero dd ComBothSpcl ;special special
EM_ENTRY eFICOMP16 eFICOMP16: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone push offset ComOpLoaded jmp Load16Int ;Returns to ComOpLoaded
EM_ENTRY eFICOM16 eFICOM16: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComOpLoaded jmp Load16Int ;Returns to ComOpLoaded
EM_ENTRY eFICOMP32 eFICOMP32: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone push offset ComOpLoaded jmp Load32Int ;Returns to ComOpLoaded
EM_ENTRY eFICOM32 eFICOM32: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComOpLoaded jmp Load32Int ;Returns to ComOpLoaded
EM_ENTRY eFCOMP32 eFCOMP32: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone push offset ComOpLoaded jmp Load32Real ;Returns to ComOpLoaded
EM_ENTRY eFCOM32 eFCOM32: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComOpLoaded jmp Load32Real ;Returns to ComOpLoaded
EM_ENTRY eFCOMP64 eFCOMP64: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone push offset ComOpLoaded jmp Load64Real ;Returns to ComOpLoaded
EM_ENTRY eFCOM64 eFCOM64: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComOpLoaded jmp Load64Real ;Returns to ComOpLoaded
EM_ENTRY eFUCOMPP eFUCOMPP: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComPop2 jmp eFUCOM0
EM_ENTRY eFUCOMP eFUCOMP: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone jmp eFUCOM0
EM_ENTRY eFUCOM eFUCOM: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 eFUCOM0: ;esi = pointer to st(i) from instruction field ;edi = [CURstk] mov ecx,EMSEG:[esi].ExpSgn mov ebx,EMSEG:[esi].lManHi mov esi,EMSEG:[esi].lManLo mov dl,40H ;Flag FUCOM - Look for SNAN jmp UComOpLoaded
EM_ENTRY eFCOMPP eFCOMPP: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset ComPop2 jmp eFCOM0
EM_ENTRY eFCOMP eFCOMP: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 push offset PopWhenDone jmp eFCOM0
EM_ENTRY eFCOM eFCOM: and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 eFCOM0: ;esi = pointer to st(i) from instruction field ;edi = [CURstk] mov ecx,EMSEG:[esi].ExpSgn mov ebx,EMSEG:[esi].lManHi mov esi,EMSEG:[esi].lManLo
ComOpLoaded: ; mov EMSEG:[UpdateCCodes],1 mov dl,0 ;flag FCOM - Look for any NAN UComOpLoaded: mov ebp,offset tFcomDisp mov al,cl mov ah,EMSEG:[edi].bTag test ax,ZEROorSPCL * 100H + ZEROorSPCL jnz TwoOpDispatch
;.erre ComDouble eq $ ;Fall into ComDouble
;********* ComDouble: ;********* ; ;ebx:esi = op1 mantissa ;ecx = op1 sign in bit 15, exponent in high half ;edi = pointer to op2 mov eax,EMSEG:[edi].ExpSgn and ax,bSign shl 8 ;Keep sign only and cx,bSign shl 8 cmp ah,ch ;Are signs the same? jnz StBigger cmp eax,ecx ;Are exponents the same? jl StSmaller jg StBigger cmp EMSEG:[edi].lManHi,ebx ;Compare mantissas jnz MantDif cmp EMSEG:[edi].lManLo,esi ;Set flags for ST - src jz ComEqual MantDif: adc al,al ;Copy CY flag to bit 0 rol ah,1 ;Rotate sign to bit 0 xor al,ah ;Flip saved CY bit if negative mov EMSEG:[SWcc],al ;Set condition code ret
StSmaller: not ah StBigger: ;ah = sign of ST ;ch = sign of other operand ;ST is bigger if it is positive (smaller if it is negative). ;Use the sign bit directly as the "less than" bit C0. .erre C0 eq 1 shr ah,7 ;Bring sign down to bit 0, clear CY mov EMSEG:[SWcc],ah ;Bit set if ST smaller (negative) ret
ComEqual: mov EMSEG:[SWcc],CCequal ret
PopWhenDone: .erre bTAG_NOPOP eq -1 inc cl ;OK to pop? jz ComPopX ;No - had unmasked Invalid Operation
POPSTret
ComPop2: .erre bTAG_NOPOP eq -1 inc cl ;OK to pop? jz ComPopX ;No - had unmasked Invalid Operation mov esi,EMSEG:[CURstk] mov EMSEG:[esi].bTag,bTAG_EMPTY add esi,Reg87Len*2 cmp esi,ENDstk ;JWM je PopOneOver ja PopTwoOver mov EMSEG:[esi-Reg87Len].bTag,bTAG_EMPTY mov EMSEG:[CURstk],esi ComPopX: ret
PopOneOver: mov EMSEG:[CURstk],BEGstk ;JWM ifdef NT386 mov EMSEG:[INITstk].bTAG,bTAG_EMPTY else mov EMSEG:[XINITstk].bTAG,bTAG_EMPTY endif ret
PopTwoOver: mov EMSEG:[CURstk],BEGstk+Reg87Len ;JWM ifdef NT386 mov EMSEG:[BEGstk].bTAG,bTAG_EMPTY else mov EMSEG:[XBEGstk].bTAG,bTAG_EMPTY endif ret
;******************************************************************************* ;Special cases for FCOM/FUCOM. ;These don't share with those in emarith.asm because NANs are treated ;differently. ComDestZero: ;ST is zero, so Src is bigger if it is positive (smaller if it is negative). ;Use the sign bit directly as the "less than" bit C0. not ch ;C0 is 1 if ST < Src .erre C0 eq 1 shr ch,7 ;Bring sign down to bit 0 mov EMSEG:[SWcc],ch ;Bit set if Src smaller (negative) ret
ComSrcZero: ;ST is bigger if it is positive (smaller if it is negative). ;Use the sign bit directly as the "less than" bit C0. mov al,EMSEG:[edi].bSgn .erre C0 eq 1 shr al,7 ;Bring sign down to bit 0 mov EMSEG:[SWcc],al ;Bit set if ST smaller (negative) ret
ComSpclSource: cmp cl,bTAG_NAN jz ComSrcNAN cmp cl,bTAG_INF jz ComDestZero cmp cl,bTAG_DEN jz ComDenormal ;Must be empty ComEmpty: mov EMSEG:[CURerr],Invalid+StackFlag jmp ComChkMask
ComSrcNAN: shl edx,24 ;Move dl to high byte test ebx,edx ;See if we report error with this NAN ComChkNAN: jnz Incomp ComInvalid: mov EMSEG:[CURerr],Invalid ;Flag the error ComChkMask: test EMSEG:[CWmask],Invalid ;Is exception masked? jnz Incomp mov cl,bTAG_NOPOP ;Unmasked, don't pop stack Incomp: mov EMSEG:[SWcc],CCincomprable ret
ComSpclDest: mov al,EMSEG:[edi].bTag cmp al,bTAG_INF jz ComSrcZero cmp al,bTAG_Empty jz ComEmpty cmp al,bTAG_DEN jz ComDenormal ;Must be NAN ComDestNAN: test EMSEG:[edi].bMan7,dl ;See if we report error with this NAN jmp ComChkNAN
ComBothSpcl: mov al,EMSEG:[edi].bTag cmp cl,bTAG_EMPTY jz ComEmpty cmp al,bTAG_EMPTY jz ComEmpty cmp cl,bTAG_NAN jz ComSrcNAN cmp al,bTAG_NAN jz ComDestNAN mov ah,cl cmp ax,(bTAG_INF shl 8) + bTag_INF ;Are both Infinity? jz ComDouble ;If so, compare their signs ;Must have at least one denormal ComDenormal: or EMSEG:[CURerr],Denormal jmp ComDouble
;*******************************************************************************
XAM_Unsupported equ 0 XAM_NAN equ C0 XAM_Norm equ C2 XAM_Inf equ C2+C0 XAM_Zero equ C3 XAM_Empty equ C3+C0 XAM_Den equ C3+C2
tXamTag label byte .erre TAG_SNGL eq $-tXamTag db XAM_Norm ;TAG_SNGL .erre TAG_VALID eq $-tXamTag db XAM_Norm ;TAG_VALID .erre TAG_ZERO eq $-tXamTag db XAM_Zero ;TAG_ZERO .erre TAG_EMPTY eq $-tXamTag db XAM_Empty ;TAG_EMPTY db 0 db 0 db 0 .erre TAG_INF eq $-tXamTag db XAM_Inf ;TAG_INF db 0 db 0 db 0 .erre TAG_NAN eq $-tXamTag db XAM_NAN ;TAG_NAN db 0 db 0 db 0 .erre TAG_DEN eq $-tXamTag db XAM_Den ;TAG_DEN
EM_ENTRY eFXAM eFXAM: ;edi = [CURstk] and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 mov eax,EMSEG:[edi].ExpSgn ;Get sign and tag mov bl,ah ;Save sign and bl,bSign ;Keep only sign bit and eax,0FH ;Save low 4 bits of tag mov al,tXamTag[eax] ;Lookup cond. codes for this tag .erre C1 eq 2 ;Bit 1 .erre bSign eq 80H ;Bit 7 shr bl,7-1 ;Move sign bit to CC C1 or al,bl mov EMSEG:[SWcc],al ret
;*******************************************************************************
EM_ENTRY eFTST eFTST: ;edi = [CURstk] and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3 mov eax,EMSEG:[edi].ExpSgn cmp al,bTAG_ZERO jz ComEqual ja TestSpcl ;Either single or double, non-zero. Just check sign. TestSign: shr ah,7 ;Bring sign down to bit 0 mov EMSEG:[SWcc],ah ;Bit set if negative ret
TestSpcl: cmp al,bTAG_INF jz TestSign ;Normal test for Infinity cmp al,bTAG_EMPTY jz ComEmpty cmp al,bTAG_NAN jz ComInvalid ;Must be denormal mov EMSEG:[CURerr],Denormal jmp TestSign
|