page ,132 subttl emlssng.asm - Load/Store Single Precision Numbers ;*** ;emlssng.asm - Load/Store Single Precision Numbers ; ; Copyright (c) 1984-89, Microsoft Corporation ; ;Purpose: ; Load/Store Single Precision Numbers ; ; This Module contains Proprietary Information of Microsoft ; Corporation and should be treated as Confidential. ; ;Revision History: ; See emulator.hst ; ;******************************************************************************* ProfBegin LSSNG ;*********************************************************************; ; ; ; Load Single Real ; ; ; ;*********************************************************************; ; ; Subroutine converts single in regs to internal at ES:SI pub eFLDsr LDUS2AX ; get lower mantissa part MOV DI,AX ; 2 keep lower mantissa in DX LDUS2AX ; get upper exponent/sign part MOV DL,AL ; 2 copy most sig. mantissa byte ROL AX,1 ; 2 sign to AL, exponent to AH AND AL,1 ; 4 clear all flags except sign ROR AL,1 ; 2 get sign in right position XCHG AL,AH ; AX, DI, DL: operand one PUSHST ; 64 allocate another register pub SingleToInternal OR DL,80H ; Set leading bit of mantissa XOR DH,DH ; Set Tag to valid non-zero CMP AL,SexpMax ; Is Number NAN or Inf? JE short SNANorInf if fastSP OR AH,Single ; Set single Precision flag endif CMP AL,SexpMin ; Is Number Zero or Denormal JE short SZeroOrDenorm ; Otherwise number is valid non-zero MOV Flag[esi],AH ; Store sign SUB AL,SexpBias ; Unbias the exponent CBW pub SStoreExpnTag MOV Expon[esi],AX ; Store Exponent MOV Tag[esi],DH ; Store Tag MOV MB7[esi],DL ; Store Mantissa MOV MB5[esi],DI ife fastSP XOR AX,AX ; Clear low order bytes of Mantissa MOV MB4[esi],AL MOV MB2[esi],AX MOV MB0[esi],AX endif RET pub SNANorInf MOV Flag[esi],AH ; Store sign MOV AX,IexpMax - IexpBias ; Set exponent to internal max MOV DH,Special ; Set Tag to show NAN or Inf CMP DL,80H ; If anything other than leading bit JNE short SStoreExpnTag ; is set number is NAN (not Inf) OR DI,DI JNE short SStoreExpnTag OR DH,ZROorINF ; Set Tag to show Inf JMP SStoreExpnTag pub SZeroorDenorm MOV Flag[esi],AH ; Store sign CMP DL,80H ; If anything other than leading bit JNE short SDenormal ; is set number is Denormal OR DI,DI JNE short SDenormal MOV AX,IexpMin - IexpBias ; Set exponent to internal min OR DH,ZROorINF ; Set Tag to show 0 JMP SStoreExpnTag pub SDenormal OR [CURerr],Denormal ; Set Denormal Exception SUB AL,SexpBias ; unbias the Exponent CBW INC AX pub SNormalize DEC AX SHL DI,1 RCL DL,1 OR DL,DL JNS SNormalize JMP SStoreExpnTag page ;************************************************************; ; ; ; Store Single Real ; ; ; ;************************************************************; pub SSpecial ; number is NAN or INF or Zero TEST CL,Special ; NAN or INF? JNE short SSNANorINF XOR AX,AX ; Number is Zero MOV BX,AX JMP STRUNC pub SSNANorINF TEST CL,ZROorINF JNE short SInf MOV BX,MB5[esi] ; Number is a NAN MOV AL,MB7[esi] MOV AH,Flag[esi] ; Pick up Sign SHL AX,1 ; Destroy leading bit, Sign to CF MOV AH,SexpMax RCR AX,1 JMP STRUNC pub SInf MOV AH,Flag[esi] JMP SSignedInfinity pub JMPSOver JMP SOver pub JMPSUnder JMP SUnder ; ES:SI: memory address of single ; stores and misc. operations; first setup register values as follows: ; AX: TOS flags (for DOUB and SIGN flags) ; SI: TOS address (offset) pub eFSTsr mov edi,esi ; ES:DI = store address MOV esi,[CURstk] ; 14 load TOS address MOV AX,Flag[esi] ; 21 get TOS flags (sign, double) ; convert internal at DS:SI to single ; DS:SI = TOS, ES:DI = memory, CH = operation (POP), BP = old ES value MOV CL,Tag[esi] ; See if number is NAN or Inf or Zero OR CL,CL JNZ short SSpecial MOV CL,Flag[esi] ; Pick up sign & single precision flag MOV AX,Expon[esi] CMP AX,SexpMax - SexpBias JGE short JMPSOver CMP AX,SexpMin - SexpBias JLE short JMPSUnder ADD AL,SexpBias ; Bias the Exponent MOV AH,MB7[esi] ; Pick up MSB of Mantissa XCHG AH,AL SHL AL,1 ; Shift mantissa to destroy leading integer bit SHL CL,1 ; Get sign into CF RCR AX,1 ; Pack sign, exp, & MSB if fastSP TEST CL,Single*2 ; if number was single rounding is not needed JZ SS1 MOV BX,MB5[esi] JMP SHORT STRUNC SS1: endif MOV DX,MB0[esi] ; DL Will be the sticky bit OR DX,MB2[esi] ; DH will be round and the rest of sticky OR DL,DH XOR DH,DH MOV BX,MB5[esi] OR DX,MB3[esi] JZ short STRUNC ; If no Round or Sticky result is exact OR [CURerr],Precision pub SRound ; single in AX:BX:DX MOV CL,[CWcntl] ; Need to know Rounding Control SHR CL,1 SHR CL,1 SHR CL,1 JC short StDOWNorCHOP24 SHR CL,1 JC short StUP24 pub StNEAR24 CMP DX,8000H ; How are round and sticky bits? JB short STRUNC ; No round, so truncate JA short SINC ; Round and sticky so round up TEST BL,1 ; Round and no sticky, is last bit even? JZ short STRUNC ; Yes, so truncate. pub SINC MOV DL,AL ; Increment mantissa ADD BX,1 ADC AX,0 XOR DL,AL ; See if we overflowed a bit into the exponent JNS short STRUNC ; If not number is now correct so go store MOV DX,AX ; Exponent was incremented, see if it overflowed SHL DX,1 CMP DH,SexpMax JE short SOver pub StCHOP24 STRUNC: XCHG AX,BX STAX2US MOV AX,BX STAX2US pub SStoreExit RET pub StDOWNorCHOP24 SHR CL,1 JC short StCHOP24 pub StDOWN24 OR AH,AH ; Test the sign JS short SINC JMP short STRUNC pub StUP24 OR AH,AH ; Test the sign JS short STRUNC JMP short SINC pub SOver ; Number overflowed Single Precision range. ; Result returned depends upon rounding control OR [CURerr],Overflow + Precision MOV CL,[CWcntl] SHR CL,1 SHR CL,1 SHR CL,1 JC short StMOvDNorCHP24 SHR CL,1 JC short StMOvUP24 StMOvNEAR24: ; Masked Overflow Near Rounding pub SSignedInfinity ; Return signed infinity MOV BX,[IEEEinfinityS + 2] AND AH,Sign ; Overstore the proper sign OR BH,AH MOV AX,[IEEEinfinityS] STAX2US MOV AX,BX STAX2US JMP SStoreExit pub StMOvDNorCHP24 SHR CL,1 JC short StMOvCHOP24 pub StMOvDOWN24 ; Masked Overflow Down Rounding TEST AH,Sign ; Positive goes to biggest JNZ short SSignedInfinity StMOvCHOP24: ; Masked Overflow Chop Rounding pub SSignedBiggest MOV BX,[IEEEbiggestS + 2] AND AH,Sign ; Overstore the proper sign OR AH,BH MOV AL,BL STAX2US MOV AX,[IEEEbiggestS] STAX2US JMP SStoreExit pub StMOvUP24 ; Masked Overflow Up Rounding TEST AH,Sign ; Negative goes to biggest JZ short SSignedInfinity JMP SSignedBiggest pub SUnder ; Masked Underflow - Try to denormalize OR [CURerr],Underflow+Precision NEG AX ; Convert exponent (which is too small) ADD AX,SexpMin-SexpBias+1 ; To a positive shift count CMP AX,24 ; Is shift more than mantissa precision JGE short Szero XCHG CX,AX ifdef i386 movzx ecx,cx ; (ecx) = zero-extended loop count endif MOV DX,MB0[esi] ; Pick up Insignif bytes for sticky bit OR DX,MB2[esi] MOV AL,DL OR AL,DH MOV DX,MB4[esi] MOV BX,MB6[esi] OR AL,AL JZ short SSHIFTR OR DL,1 ; Set the sticky bit pub SSHIFTR SHR BX,1 RCR DX,1 JNC short SSLOOP OR DL,1 pub SSLOOP LOOP SSHIFTR XCHG AH,CH ; Restore operation to CH MOV AH,Flag[esi] ; Pick up sign AND AH,Sign ; Mask to sign only MOV AL,BH ; Biased exponent for a denormal is 0 MOV BH,BL MOV BL,DH MOV DH,DL XOR DL,DL JMP SRound pub Szero XOR AX,AX MOV BX,AX JMP STRUNC ; Go store single and exit ProfEnd LSSNG