subttl emstore.asm - FST, FSTP, FIST, FISTP instructions page ;******************************************************************************* ;emstore.asm - FST, FSTP, FIST, FISTP instructions ; ; Microsoft Confidential ; ; Copyright (c) Microsoft Corporation 1991 ; All Rights Reserved ; ;Purpose: ; FST, FSTP, FIST, FISTP instructions ;Inputs: ; edi = [CURstk] ; dseg:esi = pointer to memory destination ; ;Revision History: ; ; [] 09/05/91 TP Initial 32-bit version. ; ;******************************************************************************* ;****** EM_ENTRY eFSTP eFSTP: ;****** ; edi = [CURstk] ; esi = pointer to st(i) from instruction field cmp EMSEG:[edi].bTag,bTAG_EMPTY jz short efstp_StackError ;UNDONE: temporary hack to preserve condition codes mov ax,[esp+4].OldStatus mov EMSEG:[StatusWord],ax ;UNDONE: end of hack ;A common use of this instruction is FSTP st(0) just to pop the stack. ;We check for this case and optimize it. cmp esi,edi jz short JustPop ;Copy the register mov eax,EMSEG:[edi].ExpSgn mov EMSEG:[esi].ExpSgn,eax mov eax,EMSEG:[edi].lManHi mov EMSEG:[esi].lManHi,eax mov eax,EMSEG:[edi].lManLo mov EMSEG:[esi].lManLo,eax JustPop: POPSTret edi efstp_StackError: mov EMSEG:[CURerr],Invalid+StackFlag ret ;****** EM_ENTRY eFST eFST: ;****** ; edi = [CURstk] ; esi = pointer to st(i) from instruction field cmp EMSEG:[edi].bTag,bTAG_EMPTY jz StackError ;In emarith.asm ;Copy the register mov eax,EMSEG:[edi].ExpSgn mov EMSEG:[esi].ExpSgn,eax mov eax,EMSEG:[edi].lManHi mov EMSEG:[esi].lManHi,eax mov eax,EMSEG:[edi].lManLo mov EMSEG:[esi].lManLo,eax DontPop: ret ;Come here if the instruction wants to pop the stack PopStackChk: jc DontPop ;Get unmasked error? PopStack: mov edi,EMSEG:[CURstk] POPSTret edi StoreSpcl64: cmp cl,bTAG_DEN jz Denorm64 .erre bTAG_NAN lt bTAG_EMPTY .erre bTAG_NAN gt bTAG_INF cmp cl,bTAG_NAN mov ecx,DexpMax shl 16 ;Insert special exponent for NAN/Inf. jb StoreIEEE64 ;Go handle infinity ja Empty64 ;Have a NAN. test ebx,1 shl 30 ;Check for SNAN jnz StoreIEEE64 ;Go store QNAN or ebx,1 shl 30 ;Make SNAN into a QNAN mov EMSEG:[CURerr],Invalid ;Flag the exception test EMSEG:[CWmask],Invalid ;Is it masked? jnz StoreIEEE64 ;If so, update with masked response stc ;Don't pop stack ret Empty64: ;It's empty--signal invalid operation mov EMSEG:[CURerr],StackFlag+Invalid test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing64 ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov dword ptr dseg:[esi],0 mov dword ptr dseg:[esi+4],0FFF80000H ;64-bit IEEE indefinite ret ;CY clear Denorm64: mov EMSEG:[CURerr],Denormal test EMSEG:[CWmask],Denormal ;Is it masked? jnz NormStore64 ;If so, ignore denormalization DoNothing64: stc ;Don't pop stack ret ;***************** ;Store Double Real ;***************** EM_ENTRY eFSTP64 eFSTP64: push offset PopStackChk ;Return here after store EM_ENTRY eFST64 eFST64: mov EMSEG:[PrevDataOff],esi ;Save operand pointer mov ebx,EMSEG:[edi].lManHi mov ecx,EMSEG:[edi].ExpSgn mov edi,EMSEG:[edi].lManLo ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl ;memory destination is dseg:esi mov al,ch ;Save sign bit cmp cl,bTAG_ZERO .erre bTAG_VALID lt bTAG_ZERO .erre bTAG_SNGL lt bTAG_ZERO jz short SignAndStore64 ;Just set sign and exit ja StoreSpcl64 NormStore64: ;Note that we could have a denormal exception at this point. ;Thus any additional exceptions must OR into [CURerr], not MOV. xor cx,cx add ecx,(DexpBias-TexpBias) shl 16 ;Correct bias jl short Under64 cmp ecx,DexpMax shl 16 ;Exponent too big? jge Over64 test edi,(1 shl 11) - 1 ;Any bits to round? jz short StoreIEEE64 Round64: or EMSEG:[CURerr],Precision ;Set flag on inexact result test EMSEG:[CWcntl],RoundControl ;Check rounding control bits .erre RCnear eq 0 jnz NotNearest64 ;Not just round-to-nearest test edi,1 shl 10 ;Check rounding bit jz short StoreIEEE64 ;If zero, don't round up test edi,(3 shl 10)-1 ;Test LSB and sticky bits jnz RoundUp64b StoreIEEE64: or ecx, ecx ;now that value is rounded, je short Under64 ;check exponent for underflow StoreIEEE64Continue: and ebx,not (1 shl 31) ;Clear MSB--it's implied in IEEE64 shrd edi,ebx,11 shr ebx,11 ;Move mantissa down shl ecx,4 ;Exponent up to position or ebx,ecx ;Combine exponent SignAndStore64: and al,bSign ;Just sign bit shl eax,24 ;Sign to MSB or ebx,eax ;Combine sign mov dseg:[esi],edi mov dseg:[esi+4],ebx ;CY clear indicate no error ret SetUnderflow: or EMSEG:[CURerr],Underflow ;Unmasked underflow--do nothing DoNothing: stc ;Indicate nothing was done ret Under64: dec cl ; Is cx == 1? jz short StoreIEEE64Continue ; Yes, we've alread been here test EMSEG:[CWmask],Underflow ;Is underflow masked? jz SetUnderflow ;No, do nothing more ;Produce masked underflow response ;Note that the underflow exception does not occur if the number can be ;represented exactly as a denormal. sar ecx,16 ;Bring exponent down cmp ecx,DexpMin-52 ;Allow for shift down to rounding bit jl BigUnder64 ;Too small, just make it zero .erre DexpMin eq 0 neg ecx ;Use as shift count inc ecx ;Shift by at least one xor edx,edx ;Place for sticky bits cmp cl,32 ;Long shift? jb ShortDenorm neg edi ;CY set if non-zero sbb edx,edx ;-1 if bits shifted off, else zero mov edi,ebx xor ebx,ebx ;32-bit right shift ShortDenorm: ;Shift count is modulo-32 shrd edx,edi,cl shrd edi,ebx,cl shr ebx,cl cmp edx,1 ;CY set if zero, else clear sbb edx,edx ;Zero if bits shifted off, else -1 inc edx ;1 if bits shifted off, else zero or edi,edx ;Collapse sticky bits into edi mov ecx, 1 ;Biased exponent is zero, put 1 into CL (noticed by Under64) test edi,(1 shl 11) - 1 ;Any bits to round? jz StoreIEEE64 ;If not, no exception or EMSEG:[CURerr],Underflow jmp Round64 Over64: test EMSEG:[CWmask],Overflow ;Is overflow masked? jz SetOverflow ;No, do nothing more ;Produce masked overflow response or EMSEG:[CURerr],Overflow+Precision mov ebx,DexpMax shl 20 xor edi,edi ;ebx:edi = positive infinity mov ah,EMSEG:[CWcntl] ;Get rounding control ;Return max value if RCup bit = 1 and -, or RCdown bit = 1 and + ;i.e., RCup & sign OR RCdown & not sign .erre RCchop eq RCup + RCdown ;Always return max value .erre RCnear eq 0 ;Never return max value sar al,7 ;Expand sign through whole byte .erre (RCdown and bSign) eq 0 ;Don't want to change real sign xor al,RCdown ;Flip sign for RCdown bit and ah,al ;RCup & sign OR RCdown & not sign test ah,RoundControl ;Look only at RC bits jz SignAndStore64 ;Return infinity dec ebx dec edi ;Max value == infinity-1 jmp SignAndStore64 SetOverflow: or EMSEG:[CURerr],Overflow stc ;Indicate nothing was done ret BigUnder64: or EMSEG:[CURerr],Underflow+Precision xor ebx,ebx mov edi,ebx ;Set it to zero mov ecx,ebx ;Including exponent NotNearest64: ;We want to increase the magnitude if RCup and +, or RCdown and - mov ah,EMSEG:[CWcntl] ;Get rounding control sar al,7 ;Expand sign through whole byte .erre (not RCup and RoundControl) eq RCdown xor ah,al ;Flip rounding bits if negative and ah,RoundControl cmp ah,RCup jnz StoreIEEE64 ;No, chop it RoundUp64b: mov EMSEG:[SWcc],RoundUp add edi,1 shl 11 ;Round up adc ebx,0 jnc StoreIEEE64 add ecx,1 shl 16 ;Mantissa overflowed, bump exponent cmp ecx,DexpMax shl 16 ;Exponent too big? jge Over64 jmp StoreIEEE64 ;******************************************************************************* StoreSpcl32: cmp cl,bTAG_DEN jz Denorm32 .erre bTAG_NAN lt bTAG_EMPTY .erre bTAG_NAN gt bTAG_INF cmp cl,bTAG_NAN mov ecx,SexpMax shl 16 ;Insert special exponent jb StoreIEEE32 ja Empty64 ;Have a NAN. test ebx,1 shl 30 ;Check for SNAN jnz StoreIEEE32 ;Go store QNAN or ebx,1 shl 30 ;Make SNAN into a QNAN mov EMSEG:[CURerr],Invalid ;Flag the exception test EMSEG:[CWmask],Invalid ;Is it masked? jnz StoreIEEE32 ;If so, update with masked response stc ;Don't pop stack ret Empty32: ;It's empty--signal invalid operation mov EMSEG:[CURerr],StackFlag+Invalid test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing32 ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov dword ptr dseg:[esi],0FFC00000H ;32-bit IEEE indefinite ret ;CY clear Denorm32: mov EMSEG:[CURerr],Denormal test EMSEG:[CWmask],Denormal ;Is it masked? jnz NormStore32 ;If so, ignore denormalization DoNothing32: stc ;Don't pop stack ret ;***************** ;Store Single Real ;***************** EM_ENTRY eFSTP32 eFSTP32: push offset PopStackChk ;Return here after store EM_ENTRY eFST32 eFST32: mov EMSEG:[PrevDataOff],esi ;Save operand pointer mov ebx,EMSEG:[edi].lManHi mov ecx,EMSEG:[edi].ExpSgn mov edi,EMSEG:[edi].lManLo ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl ;memory destination is dseg:esi mov al,ch ;Save sign bit cmp cl,bTAG_ZERO .erre bTAG_VALID lt bTAG_ZERO .erre bTAG_SNGL lt bTAG_ZERO jz SignAndStore32 ;Just set sign and exit ja StoreSpcl32 NormStore32: ;Note that we could have a denormal exception at this point. ;Thus any additional exceptions must OR into [CURerr], not MOV. xor cx,cx add ecx,(SexpBias-TexpBias) shl 16 ;Correct bias jle Under32 cmp ecx,SexpMax shl 16 ;Exponent too big? jge Over32 ;See if we need to round mov edx,ebx ;Get low bits and edx,(1 shl 8) - 1 ;Mask to last 8 bits or edx,edi ;Throwing away any bits? jz StoreIEEE32 ;Result will not be exact--check rounding mode Round32: or EMSEG:[CURerr],Precision ;Set flag on inexact result test EMSEG:[CWcntl],RoundControl ;Check rounding control bits .erre RCnear eq 0 jnz NotNearest32 ;Not just round-to-nearest test bl,1 shl 7 ;Round bit set? jz StoreIEEE32 mov edx,ebx and edx,(3 shl 7)-1 ;Mask to LSB and sticky bits or edx,edi ;Combine with remaining sticky bits jz StoreIEEE32 mov EMSEG:[SWcc],RoundUp add ebx,1 shl 8 ;Round up jc AddOneExp32 StoreIEEE32: and ebx,not (1 shl 31) ;Clear MSB--it's implied in IEEE32 shr ebx,8 ;Move mantissa down shl ecx,7 ;Exponent up to position or ebx,ecx ;Combine exponent SignAndStore32: and al,bSign ;Just sign bit shl eax,24 ;Sign to MSB or ebx,eax ;Combine sign mov dseg:[esi],ebx ;CY clear indicate no error ret Under32: test EMSEG:[CWmask],Underflow ;Is underflow masked? jz SetUnderflow ;No, do nothing more ;Produce masked underflow response ;Note that the underflow exception does not occur if the number can be ;represented exactly as a denormal. sar ecx,16 ;Bring exponent down cmp ecx,SexpMin-23 ;Allow for shift down to rounding bit jl BigUnder32 ;Too small, just make it zero .erre SexpMin eq 0 neg ecx ;Use as shift count inc ecx ;Shift by at least one xor edx,edx ;Place for sticky bits shrd edx,ebx,cl shr ebx,cl xor ecx,ecx ;Biased exponent is zero or edi,edx ;Combine sticky bits mov edx,ebx ;Get low bits and edx,(1 shl 8) - 1 ;Mask to last 8 bits or edx,edi ;Throwing away any bits? jz StoreIEEE32 or EMSEG:[CURerr],Underflow jmp Round32 AddOneExp32: add ecx,1 shl 16 ;Mantissa overflowed, bump exponent cmp ecx,SexpMax shl 16 ;Exponent too big? jl StoreIEEE32 Over32: test EMSEG:[CWmask],Overflow ;Is overflow masked? jz SetOverflow ;No, do nothing more ;Produce masked overflow response or EMSEG:[CURerr],Overflow+Precision mov ebx,SexpMax shl 23 mov ah,EMSEG:[CWcntl] ;Get rounding control ;Return max value if RCup bit = 1 and -, or RCdown bit = 1 and + ;i.e., RCup & sign OR RCdown & not sign .erre RCchop eq RCup + RCdown ;Always return max value .erre RCnear eq 0 ;Never return max value sar al,7 ;Expand sign through whole byte .erre (RCdown and bSign) eq 0 ;Don't want to change real sign xor al,RCdown ;Flip sign for RCdown bit and ah,al ;RCup & sign OR RCdown & not sign test ah,RoundControl ;Look only at RC bits jz SignAndStore32 ;Return infinity dec ebx ;Max value == infinity-1 jmp SignAndStore32 BigUnder32: or EMSEG:[CURerr],Underflow+Precision xor ebx,ebx ;Set it to zero xor ecx,ecx ;Exponent too NotNearest32: ;We want to increase the magnitude if RCup and +, or RCdown and - mov ah,EMSEG:[CWcntl] ;Get rounding control sar al,7 ;Expand sign through whole byte .erre (not RCup and RoundControl) eq RCdown xor ah,al ;Flip rounding bits if negative and ah,RoundControl cmp ah,RCup jnz StoreIEEE32 ;No, chop it mov EMSEG:[SWcc],RoundUp add ebx,1 shl 8 ;Round up jnc StoreIEEE32 jmp AddOneExp32 ;******************************************************************************* StoreSpcl32Int: cmp cl,bTAG_DEN jz NormStore32Int ;Ignore denormal cmp cl,bTAG_EMPTY jnz Over32Int ;All other specials are invalid mov EMSEG:[CURerr],StackFlag+Invalid jmp Invalid32Int DoNothing32Int: stc ;Don't pop stack ret CheckMax32: ja Over32Int test al,bSign ;Is it negative? jnz Store32Int ;If so, answer is OK Over32Int: ;Overflow on integer store is invalid according to IEEE mov EMSEG:[CURerr],Invalid ;Must remove precision exception Invalid32Int: test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing32Int ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov dword ptr dseg:[esi],80000000H ;32-bit integer indefinite ret ;CY clear ;****************** ;Store Long Integer ;****************** EM_ENTRY eFISTP32 eFISTP32: push offset PopStackChk ;Return here after store EM_ENTRY eFIST32 eFIST32: mov EMSEG:[PrevDataOff],esi ;Save operand pointer mov ebx,EMSEG:[edi].lManHi mov ecx,EMSEG:[edi].ExpSgn mov edi,EMSEG:[edi].lManLo ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl ;memory destination is dseg:esi mov al,ch ;Save sign bit cmp cl,bTAG_ZERO .erre bTAG_VALID lt bTAG_ZERO .erre bTAG_SNGL lt bTAG_ZERO jz Store32Int ;Just store zero and exit ja StoreSpcl32Int NormStore32Int: xor edx,edx sar ecx,16 ;Bring exponent down cmp ecx,-1 ;Is it less than 1? jle Under32Int cmp ecx,31 jg Over32Int sub ecx,31 neg ecx ;cl = amount to shift right shrd edx,edi,cl shrd edi,ebx,cl ;Collect round and sticky bits shr ebx,cl ;Align integer ;See if we need to round mov ecx,edi or ecx,edx ;Throwing away any bits? jz StoreIEEE32Int ;Result will not be exact--check rounding mode Round32Int: mov EMSEG:[CURerr],Precision ;Set flag on inexact result test EMSEG:[CWcntl],RoundControl ;Check rounding control bits .erre RCnear eq 0 jnz NotNearest32Int ;Not just round-to-nearest ;To perform "round even" when the round bit is set and the sticky bits ;are zero, we treat the LSB as if it were a sticky bit. Thus if the LSB ;is set, that will always force a round up (to even) if the round bit is ;set. If the LSB is zero, then the sticky bits remain zero and we always ;round down. bt ebx,0 ;Look at LSB (for round even) adc edx,-1 ;CY set if sticky bits <>0 adc edi,(1 shl 31)-1 ;CY set if round up jnc StoreIEEE32Int mov EMSEG:[SWcc],RoundUp inc ebx jz Over32Int StoreIEEE32Int: cmp ebx,1 shl 31 ;Check for max value jae CheckMax32 SignAndStore32Int: shl eax,24 ;Sign to MSB cdq ;Extend sign through edx xor ebx,edx ;Complement sub ebx,edx ; and increment if negative clc Store32Int: mov dseg:[esi],ebx ;CY clear indicates no error ret Under32Int: ;ZF set if exponent is -1 xchg edx,edi ;32-bit right shift xchg edi,ebx ;ebx = 0 now jz Round32Int ;If exponent was -1, ready to round mov EMSEG:[CURerr],Precision ;Set flag on inexact result NotNearest32Int: ;We want to increase the magnitude if RCup and +, or RCdown and - mov ah,EMSEG:[CWcntl] ;Get rounding control sar al,7 ;Expand sign through whole byte .erre (not RCup and RoundControl) eq RCdown xor ah,al ;Flip rounding bits if negative and ah,RoundControl cmp ah,RCup ;Rounding up? jnz StoreIEEE32Int ;No, chop it mov EMSEG:[SWcc],RoundUp inc ebx jnc StoreIEEE32Int jmp Over32Int ;******************************************************************************* StoreSpcl16Int: cmp cl,bTAG_DEN jz NormStore16Int ;Ignore denormal cmp cl,bTAG_EMPTY jnz Over16Int ;All other specials are invalid mov EMSEG:[CURerr],StackFlag+Invalid jmp Invalid16Int DoNothing16Int: stc ;Don't pop stack ret CheckMax16: ja Over16Int test al,bSign ;Is it negative? jnz Store16Int ;If so, answer is OK Over16Int: ;Overflow on integer store is invalid according to IEEE mov EMSEG:[CURerr],Invalid Invalid16Int: test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing16Int ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov word ptr dseg:[esi],8000H ;16-bit integer indefinite ret ;CY clear ;******************* ;Store Short Integer ;******************* EM_ENTRY eFISTP16 eFISTP16: push offset PopStackChk ;Return here after store EM_ENTRY eFIST16 eFIST16: mov EMSEG:[PrevDataOff],esi ;Save operand pointer mov ebx,EMSEG:[edi].lManHi mov ecx,EMSEG:[edi].ExpSgn mov edi,EMSEG:[edi].lManLo ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl ;memory destination is dseg:esi mov al,ch ;Save sign bit cmp cl,bTAG_ZERO .erre bTAG_VALID lt bTAG_ZERO .erre bTAG_SNGL lt bTAG_ZERO jz Store16Int ;Just store zero and exit ja StoreSpcl16Int NormStore16Int: xor edx,edx sar ecx,16 ;Bring exponent down cmp ecx,-1 ;Is it less than 1? jle Under16Int cmp ecx,15 jg Over16Int sub ecx,31 neg ecx ;cl = amount to shift right shrd edx,edi,cl shrd edi,ebx,cl ;Collect round and sticky bits shr ebx,cl ;Align integer ;See if we need to round mov ecx,edi or ecx,edx ;Throwing away any bits? jz StoreIEEE16Int ;Result will not be exact--check rounding mode Round16Int: mov EMSEG:[CURerr],Precision ;Set flag on inexact result test EMSEG:[CWcntl],RoundControl ;Check rounding control bits .erre RCnear eq 0 jnz NotNearest16Int ;Not just round-to-nearest ;To perform "round even" when the round bit is set and the sticky bits ;are zero, we treat the LSB as if it were a sticky bit. Thus if the LSB ;is set, that will always force a round up (to even) if the round bit is ;set. If the LSB is zero, then the sticky bits remain zero and we always ;round down. bt ebx,0 ;Look at LSB (for round even) adc edx,-1 ;CY set if sticky bits <>0 adc edi,(1 shl 31)-1 ;CY set if round up jnc StoreIEEE16Int mov EMSEG:[SWcc],RoundUp inc ebx StoreIEEE16Int: cmp ebx,1 shl 15 ;Check for max value jae CheckMax16 SignAndStore16Int: shl eax,24 ;Sign to MSB cdq ;Extend sign through edx xor ebx,edx ;Complement sub ebx,edx ; and increment if negative clc Store16Int: mov dseg:[esi],bx ;CY clear indicates no error ret Under16Int: ;ZF set if exponent is -1 xchg edx,edi ;16-bit right shift xchg edi,ebx ;ebx = 0 now jz Round16Int ;If exponent was -1, ready to round mov EMSEG:[CURerr],Precision ;Set flag on inexact result NotNearest16Int: ;We want to increase the magnitude if RCup and +, or RCdown and - mov ah,EMSEG:[CWcntl] ;Get rounding control sar al,7 ;Expand sign through whole byte .erre (not RCup and RoundControl) eq RCdown xor ah,al ;Flip rounding bits if negative and ah,RoundControl cmp ah,RCup ;Rounding up? jnz StoreIEEE16Int ;No, chop it mov EMSEG:[SWcc],RoundUp inc ebx jnc StoreIEEE16Int jmp Over16Int ;******************************************************************************* ;****************** ;Store Quad Integer ;****************** EM_ENTRY eFISTP64 eFISTP64: mov EMSEG:[PrevDataOff],esi ;Save operand pointer call RoundToInteger jc Invalid64Int ;Have integer in ebx:edi ;Sign in ch cmp ebx,1 shl 31 ;Check for max value jae CheckMax64 or ch,ch ;Check sign jns Store64Int ;64-bit negation not ebx neg edi sbb ebx,-1 Store64Int: mov dseg:[esi],edi mov dseg:[esi+4],ebx jmp PopStack CheckMax64: ja Over64Int test al,bSign ;Is it negative? jnz Store64Int ;If so, answer is OK Over64Int: ;Overflow on integer store is invalid according to IEEE mov EMSEG:[CURerr],Invalid Invalid64Int: test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing80 ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov dword ptr dseg:[esi],0 mov dword ptr dseg:[esi+4],80000000H ;64-bit integer indefinite jmp PopStack ;******************************************************************************* Empty80: ;It's empty--signal invalid operation mov EMSEG:[CURerr],StackFlag+Invalid test EMSEG:[CWmask],Invalid ;Is it masked? jz DoNothing80 ;No--leave memory unchanged ;Store Indefinite ;For FSTP, we go ahead and do the pop even though it's empty mov dword ptr dseg:[esi],0 mov dword ptr dseg:[esi+4],0C0000000H mov word ptr dseg:[esi+8],0FFFFH ;80-bit IEEE indefinite jmp PopStack DoNothing80: ret ;*************** ;Store Temp Real ;*************** EM_ENTRY eFSTP80 eFSTP80: mov EMSEG:[PrevDataOff],esi ;Save operand pointer mov eax,EMSEG:[edi].ExpSgn cmp al,bTAG_EMPTY jz Empty80 push offset PopStack StoreTempReal: mov ebx,EMSEG:[edi].lManHi mov edi,EMSEG:[edi].lManLo ;mantissa in ebx:edi, exponent in high eax, sign in ah bit 7, tag in al ;memory destination is dseg:esi mov ecx,eax ;get copy of sign and tag shr ecx,16 ;Bring exponent down cmp al,bTAG_ZERO jz StoreIEEE80 ;Skip bias if zero add ecx,IexpBias-TexpBias ;Correct bias cmp al,bTAG_DEN jz Denorm80 StoreIEEE80: and eax,bSign shl 8 or ecx,eax ;Combine sign with exponent mov dseg:[esi],edi mov dseg:[esi+4],ebx mov dseg:[esi+8],cx ; jmp PopStack ret Denorm80: ;Must change it to a denormal dec ecx neg ecx ;Use as shift count cmp cl,32 ;Long shift? jae LongDenorm shrd edi,ebx,cl shr ebx,cl xor ecx,ecx ;Exponent is zero jmp StoreIEEE80 LongDenorm: ;edi must be zero if we have 32 bits to shift xchg ebx,edi ;32-bit right shift shr edi,cl ;shift count is modulo-32 xor ecx,ecx ;Exponent is zero jmp StoreIEEE80