|
|
/*++
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
fpufragp.h
Abstract: Private include file for the 487 emulator portion of the Fragment Library
Author:
04-Oct-1995 BarryBo, Created
Revision History:
--*/
#ifndef FPUFRAGP_H
#define FPUFRAGP_H
//
// ALPHA, PPC and INTEL have the same bit-patterns for QNAN/SNAN/INDEFINITE.
// MIPS has different representations. NATIVE_NAN_IS_INTEL_FORMAT
// is used to distinguish between the different representations.
//
#if defined(_ALPHA_) || defined(_PPC_)
#define NATIVE_NAN_IS_INTEL_FORMAT 1
#elif defined(_MIPS_)
#define NATIVE_NAN_IS_INTEL_FORMAT 0
#else
#error Unknown machine type
#endif
// Macros to access the register stack
#define ST(i) ((cpu->FpTop+(i)) & 0x07)
#define PUSHFLT(x) { \
INT Top; \ Top = (cpu->FpTop-1) & 0x07; \ cpu->FpTop = Top; \ x = cpu->FpST0 = &cpu->FpStack[Top];\ }
#define INCFLT { \
INT Top; \ Top = (cpu->FpTop+1) & 0x07; \ cpu->FpTop = Top; \ cpu->FpST0 = &cpu->FpStack[Top]; \ }
#define POPFLT { cpu->FpST0->Tag = TAG_EMPTY; INCFLT; }
// Values for cpu->FpReg[].Tag
#define TAG_VALID 0 // value specified by Intel
#define TAG_ZERO 1 // value specified by Intel
#define TAG_SPECIAL 2 // value specified by Intel, indicates SpecialTag is set
#define TAG_EMPTY 3 // value specified by Intel
#define TAG_MAX 4 // value after the highest legal tag value
// Values for cpu->FpReg[].SpecialTag, valid only when Tag==TAG_SPECIAL
#define TAG_SPECIAL_DENORM 0 // private value for NPX emulator
#define TAG_SPECIAL_INFINITY 1 // private value for NPX emulator
#define TAG_SPECIAL_SNAN 2 // private value for NPX emulator
#define TAG_SPECIAL_QNAN 3 // private value for NPX emulator
#define TAG_SPECIAL_INDEF 4 // private value for NPX emulator
// Does a register hold a QNAN, SNAN, or INDEFINITE?
#define IS_TAG_NAN(FpReg) \
((FpReg)->Tag == TAG_SPECIAL && (FpReg)->TagSpecial >= TAG_SPECIAL_SNAN)
// Common types used for jump tables in the 487 emulator
typedef VOID (*NpxFunc0)(PCPUDATA); typedef VOID (*NpxFunc1)(PCPUDATA, PFPREG Fp); typedef VOID (*NpxFunc2)(PCPUDATA cpu, PFPREG l, PFPREG r); typedef VOID (*NpxFunc3)(PCPUDATA cpu, PFPREG dest, PFPREG l, PFPREG r); typedef VOID (*NpxComFunc)(PCPUDATA cpu, PFPREG l, PFPREG r, BOOL fUnordered); typedef VOID (*NpxPutIntelR4)(FLOAT *pIntelReal, PFPREG Fp); typedef VOID (*NpxPutIntelR8)(DOUBLE *pIntelReal, PFPREG Fp); typedef VOID (*NpxPutIntelR10)(PBYTE r10, PFPREG Fp); typedef VOID (*NpxLoadIntelR10ToR8)(PCPUDATA cpu, PBYTE r10, PFPREG FpReg); typedef VOID (*NpxPutI2)(PCPUDATA cpu, SHORT *pop1, PFPREG Fp); typedef VOID (*NpxPutI4)(PCPUDATA cpu, LONG *pop1, PFPREG Fp); typedef VOID (*NpxPutI8)(PCPUDATA cpu, LONGLONG *pop1, PFPREG Fp);
// Macros to declare functions for those common types
#define NPXFUNC0(name) VOID name(PCPUDATA cpu)
#define NPXFUNC1(name) VOID name(PCPUDATA cpu, PFPREG Fp)
#define NPXFUNC2(name) VOID name(PCPUDATA cpu, PFPREG l, PFPREG r)
#define NPXFUNC3(name) VOID name(PCPUDATA cpu, PFPREG dest, PFPREG l, PFPREG r)
#define NPXCOMFUNC(name) VOID name(PCPUDATA cpu, PFPREG l, PFPREG r, BOOL fUnordered)
#define NPXPUTINTELR4(name) VOID name(FLOAT *pIntelReal, PFPREG Fp)
#define NPXPUTINTELR8(name) VOID name(DOUBLE *pIntelReal, PFPREG Fp)
#define NPXPUTINTELR10(name) VOID name(PBYTE r10, PFPREG Fp)
#define NPXLOADINTELR10TOR8(name) VOID name(PCPUDATA cpu, PBYTE r10, PFPREG Fp)
#define NPXPUTI2(name) VOID name(PCPUDATA cpu, SHORT *pop1, PFPREG Fp)
#define NPXPUTI4(name) VOID name(PCPUDATA cpu, LONG *pop1, PFPREG Fp)
#define NPXPUTI8(name) VOID name(PCPUDATA cpu, LONGLONG *pop1, PFPREG Fp)
extern const BYTE R8PositiveInfinityVal[8]; extern const BYTE R8NegativeInfinityVal[8]; #define R8PositiveInfinity *(DOUBLE *)R8PositiveInfinityVal
#define R8NegativeInfinity *(DOUBLE *)R8NegativeInfinityVal
VOID GetIntelR4(PFPREG Fp, FLOAT *pIntelReal);
#if NATIVE_NAN_IS_INTEL_FORMAT
#define GetIntelR8(Fp, pIntelReal) \
(Fp)->r64 = *(UNALIGNED DOUBLE *)(pIntelReal); \ SetTag(Fp);
#define PutIntelR4(pIntelReal, Fp) \
*(UNALIGNED FLOAT *)pIntelReal = (FLOAT)(Fp)->r64;
#define PutIntelR8(pIntelReal, Fp) \
*(UNALIGNED DOUBLE *)pIntelReal = (Fp)->r64;
#else
VOID GetIntelR8( PFPREG Fp, DOUBLE *pIntelReal );
extern NpxPutIntelR4 PutIntelR4Table[TAG_MAX]; extern NpxPutIntelR8 PutIntelR8Table[TAG_MAX];
#define PutIntelR4(pIntelReal, Fp) \
(*PutIntelR4Table[(Fp)->Tag])((pIntelReal), (Fp))
#define PutIntelR8(pIntelReal, Fp) \
(*PutIntelR8Table[(Fp)->Tag])((pIntelReal), (Fp))
#endif
extern const NpxPutIntelR10 PutIntelR10Table[TAG_MAX]; #define PutIntelR10(pIntelReal, Fp) (*PutIntelR10Table[(Fp)->Tag])((pIntelReal), (Fp))
VOID SetTag( PFPREG FpReg );
VOID ComputeR10Tag( USHORT *r10, PFPREG FpReg );
VOID ChopR10ToR8( PBYTE r10, PFPREG FpReg, USHORT R10Exponent );
VOID LoadIntelR10ToR8( PCPUDATA cpu, PBYTE r10, PFPREG FpReg );
BOOL HandleSnan( PCPUDATA cpu, PFPREG FpReg );
BOOL HandleStackEmpty( PCPUDATA cpu, PFPREG FpReg );
VOID UpdateFpExceptionFlags( PCPUDATA cpu );
VOID SetIndefinite( PFPREG FpReg );
BOOL HandleInvalidOp( PCPUDATA cpu );
VOID FpControlPreamble( PCPUDATA cpu );
VOID FpArithPreamble( PCPUDATA cpu );
VOID FpArithDataPreamble( PCPUDATA cpu, PVOID FpData );
VOID HandleStackFull( PCPUDATA cpu, PFPREG FpReg );
#endif //FPUFRAGP_H
|