ReactOS 0.4.15-dev-7953-g1f49173
fpu.h File Reference
#include "opcodes.h"
Include dependency graph for fpu.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define FPU_CHECK()
 
#define FPU_INDEX(i)   ((State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS)
 
#define FPU_ST(i)   State->FpuRegisters[FPU_INDEX(i)]
 
#define FPU_GET_TAG(i)   ((State->FpuTag >> (FPU_INDEX(i) * 2)) & 3)
 
#define FPU_SET_TAG(i, t)
 
#define FPU_UPDATE_TAG(i)   FPU_SET_TAG((i), Fast486FpuGetValueTag(&FPU_ST(i)))
 
#define FPU_SAVE_LAST_INST()
 
#define FPU_SAVE_LAST_OPERAND()
 
#define FPU_REAL4_BIAS   0x7F
 
#define FPU_REAL8_BIAS   0x3FF
 
#define FPU_REAL10_BIAS   0x3FFF
 
#define FPU_MAX_EXPONENT   0x7FFE
 
#define FPU_MANTISSA_HIGH_BIT   0x8000000000000000ULL
 
#define FPU_INDEFINITE_MANTISSA   0xC000000000000000ULL
 
#define FPU_REAL4_INFINITY   0x7F800000
 
#define FPU_REAL4_INDEFINITE   0xFFC00000
 
#define FPU_REAL8_INFINITY   0x7FF0000000000000ULL
 
#define FPU_REAL8_INDEFINITE   0xFFF8000000000000ULL
 
#define FPU_IS_NORMALIZED(x)   (FPU_IS_ZERO(x) || (((x)->Mantissa & FPU_MANTISSA_HIGH_BIT) != 0ULL))
 
#define FPU_IS_ZERO(x)   ((x)->Mantissa == 0ULL)
 
#define FPU_IS_NAN(x)   ((x)->Exponent == (FPU_MAX_EXPONENT + 1))
 
#define FPU_IS_INFINITY(x)   (FPU_IS_NAN(x) && ((x)->Mantissa == FPU_MANTISSA_HIGH_BIT))
 
#define FPU_IS_POS_INF(x)   (FPU_IS_INFINITY(x) && !(x)->Sign)
 
#define FPU_IS_NEG_INF(x)   (FPU_IS_INFINITY(x) && (x)->Sign)
 
#define FPU_IS_INDEFINITE(x)   (FPU_IS_NAN(x) && !FPU_IS_INFINITY(x))
 
#define INVERSE_NUMBERS_COUNT   50
 

Enumerations

enum  { FPU_SINGLE_PRECISION = 0 , FPU_DOUBLE_PRECISION = 2 , FPU_DOUBLE_EXT_PRECISION = 3 }
 
enum  { FPU_TAG_VALID = 0 , FPU_TAG_ZERO = 1 , FPU_TAG_SPECIAL = 2 , FPU_TAG_EMPTY = 3 }
 
enum  { FPU_ROUND_NEAREST = 0 , FPU_ROUND_DOWN = 1 , FPU_ROUND_UP = 2 , FPU_ROUND_TRUNCATE = 3 }
 

Functions

 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeD8)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeD9)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDA)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDB)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDC)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDD)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDE)
 
 FAST486_OPCODE_HANDLER (Fast486FpuOpcodeDF)
 

Macro Definition Documentation

◆ FPU_CHECK

#define FPU_CHECK ( )
Value:
if (State->ControlRegisters[FAST486_REG_CR0] & (FAST486_CR0_EM | FAST486_CR0_TS)) \
{ \
Fast486Exception(State, FAST486_EXCEPTION_NM); \
return; \
}
#define FAST486_CR0_EM
Definition: fast486.h:48
#define FAST486_CR0_TS
Definition: fast486.h:49

Definition at line 31 of file fpu.h.

◆ FPU_GET_TAG

#define FPU_GET_TAG (   i)    ((State->FpuTag >> (FPU_INDEX(i) * 2)) & 3)

Definition at line 39 of file fpu.h.

◆ FPU_INDEFINITE_MANTISSA

#define FPU_INDEFINITE_MANTISSA   0xC000000000000000ULL

Definition at line 60 of file fpu.h.

◆ FPU_INDEX

#define FPU_INDEX (   i)    ((State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS)

Definition at line 36 of file fpu.h.

◆ FPU_IS_INDEFINITE

#define FPU_IS_INDEFINITE (   x)    (FPU_IS_NAN(x) && !FPU_IS_INFINITY(x))

Definition at line 72 of file fpu.h.

◆ FPU_IS_INFINITY

#define FPU_IS_INFINITY (   x)    (FPU_IS_NAN(x) && ((x)->Mantissa == FPU_MANTISSA_HIGH_BIT))

Definition at line 69 of file fpu.h.

◆ FPU_IS_NAN

#define FPU_IS_NAN (   x)    ((x)->Exponent == (FPU_MAX_EXPONENT + 1))

Definition at line 68 of file fpu.h.

◆ FPU_IS_NEG_INF

#define FPU_IS_NEG_INF (   x)    (FPU_IS_INFINITY(x) && (x)->Sign)

Definition at line 71 of file fpu.h.

◆ FPU_IS_NORMALIZED

#define FPU_IS_NORMALIZED (   x)    (FPU_IS_ZERO(x) || (((x)->Mantissa & FPU_MANTISSA_HIGH_BIT) != 0ULL))

Definition at line 66 of file fpu.h.

◆ FPU_IS_POS_INF

#define FPU_IS_POS_INF (   x)    (FPU_IS_INFINITY(x) && !(x)->Sign)

Definition at line 70 of file fpu.h.

◆ FPU_IS_ZERO

#define FPU_IS_ZERO (   x)    ((x)->Mantissa == 0ULL)

Definition at line 67 of file fpu.h.

◆ FPU_MANTISSA_HIGH_BIT

#define FPU_MANTISSA_HIGH_BIT   0x8000000000000000ULL

Definition at line 59 of file fpu.h.

◆ FPU_MAX_EXPONENT

#define FPU_MAX_EXPONENT   0x7FFE

Definition at line 58 of file fpu.h.

◆ FPU_REAL10_BIAS

#define FPU_REAL10_BIAS   0x3FFF

Definition at line 57 of file fpu.h.

◆ FPU_REAL4_BIAS

#define FPU_REAL4_BIAS   0x7F

Definition at line 55 of file fpu.h.

◆ FPU_REAL4_INDEFINITE

#define FPU_REAL4_INDEFINITE   0xFFC00000

Definition at line 62 of file fpu.h.

◆ FPU_REAL4_INFINITY

#define FPU_REAL4_INFINITY   0x7F800000

Definition at line 61 of file fpu.h.

◆ FPU_REAL8_BIAS

#define FPU_REAL8_BIAS   0x3FF

Definition at line 56 of file fpu.h.

◆ FPU_REAL8_INDEFINITE

#define FPU_REAL8_INDEFINITE   0xFFF8000000000000ULL

Definition at line 64 of file fpu.h.

◆ FPU_REAL8_INFINITY

#define FPU_REAL8_INFINITY   0x7FF0000000000000ULL

Definition at line 63 of file fpu.h.

◆ FPU_SAVE_LAST_INST

#define FPU_SAVE_LAST_INST ( )
Value:
{ \
State->FpuLastInstPtr = State->SavedInstPtr; \
State->FpuLastCodeSel = State->SegmentRegs[FAST486_REG_CS].Selector; \
}

Definition at line 45 of file fpu.h.

◆ FPU_SAVE_LAST_OPERAND

#define FPU_SAVE_LAST_OPERAND ( )
Value:
{ \
State->FpuLastOpPtr.Long = ModRegRm.MemoryAddress; \
State->FpuLastDataSel = (State->PrefixFlags & FAST486_PREFIX_SEG) \
? State->SegmentOverride : FAST486_REG_DS; \
}
#define FAST486_PREFIX_SEG
Definition: fast486.h:98

Definition at line 49 of file fpu.h.

◆ FPU_SET_TAG

#define FPU_SET_TAG (   i,
  t 
)
Value:
{ \
State->FpuTag &= ~((1 << (FPU_INDEX(i) * 2)) | (1 << ((FPU_INDEX(i) * 2) + 1))); \
State->FpuTag |= ((t) & 3) << (FPU_INDEX(i) * 2); \
}
#define FPU_INDEX(i)
Definition: fpu.h:36
GLdouble GLdouble t
Definition: gl.h:2047
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248

Definition at line 40 of file fpu.h.

◆ FPU_ST

#define FPU_ST (   i)    State->FpuRegisters[FPU_INDEX(i)]

Definition at line 37 of file fpu.h.

◆ FPU_UPDATE_TAG

#define FPU_UPDATE_TAG (   i)    FPU_SET_TAG((i), Fast486FpuGetValueTag(&FPU_ST(i)))

Definition at line 44 of file fpu.h.

◆ INVERSE_NUMBERS_COUNT

#define INVERSE_NUMBERS_COUNT   50

Definition at line 74 of file fpu.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
FPU_SINGLE_PRECISION 
FPU_DOUBLE_PRECISION 
FPU_DOUBLE_EXT_PRECISION 

Definition at line 76 of file fpu.h.

77{
81};
@ FPU_DOUBLE_PRECISION
Definition: fpu.h:79
@ FPU_SINGLE_PRECISION
Definition: fpu.h:78
@ FPU_DOUBLE_EXT_PRECISION
Definition: fpu.h:80

◆ anonymous enum

anonymous enum
Enumerator
FPU_TAG_VALID 
FPU_TAG_ZERO 
FPU_TAG_SPECIAL 
FPU_TAG_EMPTY 

Definition at line 83 of file fpu.h.

84{
85 FPU_TAG_VALID = 0,
86 FPU_TAG_ZERO = 1,
89};
@ FPU_TAG_VALID
Definition: fpu.h:85
@ FPU_TAG_SPECIAL
Definition: fpu.h:87
@ FPU_TAG_EMPTY
Definition: fpu.h:88
@ FPU_TAG_ZERO
Definition: fpu.h:86

◆ anonymous enum

anonymous enum
Enumerator
FPU_ROUND_NEAREST 
FPU_ROUND_DOWN 
FPU_ROUND_UP 
FPU_ROUND_TRUNCATE 

Definition at line 91 of file fpu.h.

92{
95 FPU_ROUND_UP = 2,
97};
@ FPU_ROUND_UP
Definition: fpu.h:95
@ FPU_ROUND_TRUNCATE
Definition: fpu.h:96
@ FPU_ROUND_NEAREST
Definition: fpu.h:93
@ FPU_ROUND_DOWN
Definition: fpu.h:94

Function Documentation

◆ FAST486_OPCODE_HANDLER() [1/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeD8  )

Definition at line 1808 of file fpu.c.

1809{
1810 FAST486_MOD_REG_RM ModRegRm;
1811 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1812#ifndef FAST486_NO_FPU
1813 PFAST486_FPU_DATA_REG Operand;
1814 FAST486_FPU_DATA_REG MemoryData;
1815#endif
1816
1817 TOGGLE_ADSIZE(AddressSize);
1818
1819 /* Get the operands */
1820 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1821 {
1822 /* Exception occurred */
1823 return;
1824 }
1825
1826 FPU_CHECK();
1827
1828#ifndef FAST486_NO_FPU
1829
1830 Fast486FpuExceptionCheck(State);
1832
1833 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
1834 {
1835 /* Raise the invalid operation exception */
1836 State->FpuStatus.Ie = TRUE;
1837
1838 if (State->FpuControl.Im)
1839 {
1840 /* Return the indefinite NaN */
1841 FPU_ST(0).Sign = TRUE;
1842 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
1843 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA;
1844
1846 }
1847
1848 return;
1849 }
1850
1851 if (ModRegRm.Memory)
1852 {
1853 /* Load the source operand from memory */
1854 ULONG Value;
1855
1856 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1857 {
1858 /* Exception occurred */
1859 return;
1860 }
1861
1862 Fast486FpuFromSingleReal(State, Value, &MemoryData);
1863 Operand = &MemoryData;
1864
1866 }
1867 else
1868 {
1869 if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
1870 {
1871 /* Raise the invalid operation exception */
1872 State->FpuStatus.Ie = TRUE;
1873
1874 if (State->FpuControl.Im)
1875 {
1876 /* Return the indefinite NaN */
1877 FPU_ST(0).Sign = TRUE;
1878 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
1879 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA;
1880
1882 }
1883
1884 return;
1885 }
1886
1887 /* Load the source operand from an FPU register */
1888 Operand = &FPU_ST(ModRegRm.SecondRegister);
1889 }
1890
1891 /* Perform the requested operation */
1892 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, TRUE);
1893
1894#endif
1895}
unsigned char BOOLEAN
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
static VOID FASTCALL Fast486FpuFromSingleReal(PFAST486_STATE State, ULONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:533
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
#define FPU_GET_TAG(i)
Definition: fpu.h:39
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FPU_ST(i)
Definition: fpu.h:37
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
BOOLEAN Memory
Definition: common.h:77
FAST486_GEN_REGS Register
Definition: common.h:76
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

◆ FAST486_OPCODE_HANDLER() [2/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeD9  )

Definition at line 1897 of file fpu.c.

1898{
1899 FAST486_MOD_REG_RM ModRegRm;
1900 BOOLEAN OperandSize, AddressSize;
1901
1902 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1903 TOGGLE_OPSIZE(OperandSize);
1904 TOGGLE_ADSIZE(AddressSize);
1905
1906 /* Get the operands */
1907 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1908 {
1909 /* Exception occurred */
1910 return;
1911 }
1912
1913 FPU_CHECK();
1914
1915#ifndef FAST486_NO_FPU
1916
1917 if (ModRegRm.Memory)
1918 {
1919 switch (ModRegRm.Register)
1920 {
1921 /* FLD */
1922 case 0:
1923 {
1924 ULONG Value;
1925 FAST486_FPU_DATA_REG MemoryData;
1926
1927 Fast486FpuExceptionCheck(State);
1930
1931 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1932 {
1933 /* Exception occurred */
1934 return;
1935 }
1936
1937 Fast486FpuFromSingleReal(State, Value, &MemoryData);
1938 Fast486FpuPush(State, &MemoryData);
1939
1940 break;
1941 }
1942
1943 /* FST */
1944 case 2:
1945 /* FSTP */
1946 case 3:
1947 {
1949
1950 Fast486FpuExceptionCheck(State);
1953
1954 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
1955 {
1956 /* Raise the invalid operation exception */
1957 State->FpuStatus.Ie = TRUE;
1958
1959 if (!State->FpuControl.Im)
1960 {
1961 return;
1962 }
1963 }
1964 else if (!Fast486FpuToSingleReal(State, &FPU_ST(0), &Value))
1965 {
1966 /* Exception occurred */
1967 return;
1968 }
1969
1970 if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
1971 {
1972 /* Exception occurred */
1973 return;
1974 }
1975
1976 if (ModRegRm.Register == 3) Fast486FpuPop(State);
1977 break;
1978 }
1979
1980 /* FLDENV */
1981 case 4:
1982 {
1984 (State->PrefixFlags & FAST486_PREFIX_SEG)
1985 ? State->SegmentOverride : FAST486_REG_DS,
1986 ModRegRm.MemoryAddress,
1987 OperandSize);
1988 break;
1989 }
1990
1991 /* FLDCW */
1992 case 5:
1993 {
1994 Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &State->FpuControl.Value);
1995 break;
1996 }
1997
1998 /* FSTENV */
1999 case 6:
2000 {
2002 (State->PrefixFlags & FAST486_PREFIX_SEG)
2003 ? State->SegmentOverride : FAST486_REG_DS,
2004 ModRegRm.MemoryAddress,
2005 OperandSize);
2006 break;
2007 }
2008
2009 /* FSTCW */
2010 case 7:
2011 {
2012 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->FpuControl.Value);
2013 break;
2014 }
2015
2016 /* Invalid */
2017 default:
2018 {
2019 Fast486Exception(State, FAST486_EXCEPTION_UD);
2020 return;
2021 }
2022 }
2023 }
2024 else
2025 {
2026 switch ((ModRegRm.Register << 3) | ModRegRm.SecondRegister)
2027 {
2028 /* FLD */
2029 case 0x00:
2030 case 0x01:
2031 case 0x02:
2032 case 0x03:
2033 case 0x04:
2034 case 0x05:
2035 case 0x06:
2036 case 0x07:
2037 {
2038 Fast486FpuExceptionCheck(State);
2040
2041 if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
2042 {
2043 /* Raise the invalid operation exception */
2044 State->FpuStatus.Ie = TRUE;
2045
2046 if (!State->FpuControl.Im)
2047 {
2048 return;
2049 }
2050 }
2051
2052 Fast486FpuPush(State, &FPU_ST(ModRegRm.SecondRegister));
2053 break;
2054 }
2055
2056 /* FXCH */
2057 case 0x08:
2058 case 0x09:
2059 case 0x0A:
2060 case 0x0B:
2061 case 0x0C:
2062 case 0x0D:
2063 case 0x0E:
2064 case 0x0F:
2065 {
2066 FAST486_FPU_DATA_REG Temp;
2067
2068 Fast486FpuExceptionCheck(State);
2070
2071 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2073 {
2074 State->FpuStatus.Ie = TRUE;
2075 break;
2076 }
2077
2078 /* Exchange */
2079 Temp = FPU_ST(0);
2080 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
2081 FPU_ST(ModRegRm.SecondRegister) = Temp;
2082
2083 FPU_UPDATE_TAG(0);
2085
2086 break;
2087 }
2088
2089 /* FNOP */
2090 case 0x10:
2091 {
2092 /* Do nothing */
2093 break;
2094 }
2095
2096 /* FSTP */
2097 case 0x18:
2098 case 0x19:
2099 case 0x1A:
2100 case 0x1B:
2101 case 0x1C:
2102 case 0x1D:
2103 case 0x1E:
2104 case 0x1F:
2105 {
2106 Fast486FpuExceptionCheck(State);
2108
2109 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
2111
2112 Fast486FpuPop(State);
2113 break;
2114 }
2115
2116 /* FCHS */
2117 case 0x20:
2118 {
2119 Fast486FpuExceptionCheck(State);
2121
2122 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2123 {
2124 State->FpuStatus.Ie = TRUE;
2125 break;
2126 }
2127
2128 /* Invert the sign */
2129 FPU_ST(0).Sign = !FPU_ST(0).Sign;
2130
2131 break;
2132 }
2133
2134 /* FABS */
2135 case 0x21:
2136 {
2137 Fast486FpuExceptionCheck(State);
2139
2140 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2141 {
2142 State->FpuStatus.Ie = TRUE;
2143 break;
2144 }
2145
2146 /* Set the sign to positive */
2147 FPU_ST(0).Sign = FALSE;
2148
2149 break;
2150 }
2151
2152 /* FTST */
2153 case 0x24:
2154 {
2155 Fast486FpuExceptionCheck(State);
2157
2159 break;
2160 }
2161
2162 /* FXAM */
2163 case 0x25:
2164 {
2165 Fast486FpuExceptionCheck(State);
2167
2168 /* The sign bit goes in C1, even if the register's empty */
2169 State->FpuStatus.Code1 = FPU_ST(0).Sign;
2170
2171 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2172 {
2173 State->FpuStatus.Code0 = 1;
2174 State->FpuStatus.Code2 = 0;
2175 State->FpuStatus.Code3 = 1;
2176 }
2177 else if (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)
2178 {
2179 if (FPU_IS_INFINITY(&FPU_ST(0)))
2180 {
2181 State->FpuStatus.Code0 = 1;
2182 State->FpuStatus.Code2 = 1;
2183 State->FpuStatus.Code3 = 0;
2184 }
2185 else
2186 {
2187 State->FpuStatus.Code0 = 1;
2188 State->FpuStatus.Code2 = 0;
2189 State->FpuStatus.Code3 = 0;
2190 }
2191 }
2192 else if (FPU_GET_TAG(0) == FPU_TAG_ZERO)
2193 {
2194 State->FpuStatus.Code0 = 0;
2195 State->FpuStatus.Code2 = 0;
2196 State->FpuStatus.Code3 = 1;
2197 }
2198 else
2199 {
2200 if (FPU_IS_NORMALIZED(&FPU_ST(0)))
2201 {
2202 State->FpuStatus.Code0 = 0;
2203 State->FpuStatus.Code2 = 1;
2204 State->FpuStatus.Code3 = 0;
2205 }
2206 else
2207 {
2208 State->FpuStatus.Code0 = 0;
2209 State->FpuStatus.Code2 = 1;
2210 State->FpuStatus.Code3 = 1;
2211 }
2212 }
2213
2214 break;
2215 }
2216
2217 /* FLD1 */
2218 case 0x28:
2219 /* FLDL2T */
2220 case 0x29:
2221 /* FLDL2E */
2222 case 0x2A:
2223 /* FLDPI */
2224 case 0x2B:
2225 /* FLDLG2 */
2226 case 0x2C:
2227 /* FLDLN2 */
2228 case 0x2D:
2229 /* FLDZ */
2230 case 0x2E:
2231 {
2232 PCFAST486_FPU_DATA_REG Constants[] =
2233 {
2234 &FpuOne,
2235 &FpuL2Ten,
2236 &FpuL2E,
2237 &FpuPi,
2238 &FpuLgTwo,
2239 &FpuLnTwo,
2240 &FpuZero
2241 };
2242
2243 Fast486FpuExceptionCheck(State);
2245
2246 Fast486FpuPush(State, Constants[ModRegRm.SecondRegister]);
2247 break;
2248 }
2249
2250 /* F2XM1 */
2251 case 0x30:
2252 {
2253 Fast486FpuExceptionCheck(State);
2255
2256 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2257 {
2258 State->FpuStatus.Ie = TRUE;
2259 break;
2260 }
2261
2262 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2263 {
2264 State->FpuStatus.De = TRUE;
2265
2266 if (!State->FpuControl.Dm)
2267 {
2268 break;
2269 }
2270 }
2271
2273 FPU_UPDATE_TAG(0);
2274
2275 break;
2276 }
2277
2278 /* FYL2X */
2279 case 0x31:
2280 {
2281 FAST486_FPU_DATA_REG Logarithm;
2282
2283 Fast486FpuExceptionCheck(State);
2285
2287 {
2288 State->FpuStatus.Ie = TRUE;
2289 break;
2290 }
2291
2292 if (!Fast486FpuCalculateLogBase2(State, &FPU_ST(0), &Logarithm))
2293 {
2294 /* Exception occurred */
2295 break;
2296 }
2297
2298 if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1)))
2299 {
2300 /* Exception occurred */
2301 break;
2302 }
2303
2304 /* Pop the stack so that the result ends up in ST0 */
2305 Fast486FpuPop(State);
2306 FPU_UPDATE_TAG(0);
2307
2308 break;
2309 }
2310
2311 /* FPTAN */
2312 case 0x32:
2313 {
2314 FAST486_FPU_DATA_REG Sine;
2315 FAST486_FPU_DATA_REG Cosine;
2316 ULONGLONG Quadrant;
2317
2318 Fast486FpuExceptionCheck(State);
2320
2321 /* Compute the sine */
2322 if (!Fast486FpuCalculateSine(State, &FPU_ST(0), &Sine)) break;
2323
2324 /* Normalize the angle */
2326 &FPU_ST(0),
2327 &FpuHalfPi,
2328 FALSE,
2329 NULL,
2330 (PLONGLONG)&Quadrant))
2331 {
2332 break;
2333 }
2334
2335 /* Normalize the quadrant number */
2336 Quadrant &= 3;
2337
2338 /* Find the cosine by calculating sqrt(1 - sin(x) ^ 2) */
2339 if (!Fast486FpuMultiply(State, &Sine, &Sine, &Cosine)) break;
2340 if (!Fast486FpuSubtract(State, &FpuOne, &Cosine, &Cosine)) break;
2341 if (!Fast486FpuCalculateSquareRoot(State, &Cosine, &Cosine)) break;
2342
2343 /* Adjust the sign of the cosine */
2344 if (Quadrant == 1 || Quadrant == 2) Cosine.Sign = TRUE;
2345
2346 /* Divide the sine by the cosine to get the tangent */
2347 if (!Fast486FpuDivide(State, &Sine, &Cosine, &FPU_ST(0))) break;
2348 FPU_UPDATE_TAG(0);
2349
2350 /* Push 1.00 */
2351 Fast486FpuPush(State, &FpuOne);
2352 break;
2353 }
2354
2355 /* FPATAN */
2356 case 0x33:
2357 {
2358 Fast486FpuExceptionCheck(State);
2360
2362 &FPU_ST(1),
2363 &FPU_ST(0),
2364 &FPU_ST(1)))
2365 {
2366 break;
2367 }
2368
2369 FPU_UPDATE_TAG(1);
2370
2371 Fast486FpuPop(State);
2372 break;
2373 }
2374
2375 /* FXTRACT */
2376 case 0x34:
2377 {
2378 FAST486_FPU_DATA_REG Value = FPU_ST(0);
2379
2380 Fast486FpuExceptionCheck(State);
2382
2384 {
2385 State->FpuStatus.Ie = TRUE;
2386 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) State->FpuStatus.Sf = TRUE;
2387 break;
2388 }
2389
2390 if (FPU_IS_ZERO(&Value))
2391 {
2392 /* The exponent of zero is negative infinity */
2393 FPU_ST(0).Sign = TRUE;
2394 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
2395 FPU_ST(0).Mantissa = FPU_MANTISSA_HIGH_BIT;
2396 }
2397 else if (FPU_IS_INFINITY(&Value))
2398 {
2399 /* The exponent of infinity is positive infinity */
2400 FPU_ST(0).Sign = FALSE;
2401 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
2402 FPU_ST(0).Mantissa = FPU_MANTISSA_HIGH_BIT;
2403 }
2404 else
2405 {
2406 /* Store the unbiased exponent in ST0 */
2409 &FPU_ST(0));
2410 }
2411
2412 /* Now push the mantissa as a real number, with the original sign */
2413 Value.Exponent = FPU_REAL10_BIAS;
2414 Fast486FpuPush(State, &Value);
2415
2416 break;
2417 }
2418
2419 /* FPREM1 */
2420 case 0x35:
2421 /* FPREM */
2422 case 0x38:
2423 {
2424 LONGLONG Quotient;
2425
2426 Fast486FpuExceptionCheck(State);
2428
2430 {
2431 State->FpuStatus.Ie = TRUE;
2432 break;
2433 }
2434
2436 &FPU_ST(0),
2437 &FPU_ST(1),
2438 ModRegRm.Register == 6, /* TRUE if it's FPREM1 */
2439 &FPU_ST(0),
2440 &Quotient))
2441 {
2442 FPU_UPDATE_TAG(0);
2443
2444 /* Return the lowest 3 bits of the quotient in C1, C3, C0 */
2445 State->FpuStatus.Code1 = Quotient & 1;
2446 State->FpuStatus.Code3 = (Quotient >> 1) & 1;
2447 State->FpuStatus.Code0 = (Quotient >> 2) & 1;
2448 }
2449
2450 break;
2451 }
2452
2453 /* FDECSTP */
2454 case 0x36:
2455 {
2456 State->FpuStatus.Top--;
2457 break;
2458 }
2459
2460 /* FINCSTP */
2461 case 0x37:
2462 {
2463 State->FpuStatus.Top++;
2464 break;
2465 }
2466
2467 /* FYL2XP1 */
2468 case 0x39:
2469 {
2470 FAST486_FPU_DATA_REG Value, Logarithm;
2471
2472 Fast486FpuExceptionCheck(State);
2474
2476 {
2477 State->FpuStatus.Ie = TRUE;
2478 break;
2479 }
2480
2481 if (!Fast486FpuAdd(State, &FPU_ST(0), &FpuOne, &Value))
2482 {
2483 /* Exception occurred */
2484 break;
2485 }
2486
2487 if (!Fast486FpuCalculateLogBase2(State, &Value, &Logarithm))
2488 {
2489 /* Exception occurred */
2490 break;
2491 }
2492
2493 if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1)))
2494 {
2495 /* Exception occurred */
2496 break;
2497 }
2498
2499 /* Pop the stack so that the result ends up in ST0 */
2500 Fast486FpuPop(State);
2501 FPU_UPDATE_TAG(0);
2502
2503 break;
2504 }
2505
2506 /* FSQRT */
2507 case 0x3A:
2508 {
2509 Fast486FpuExceptionCheck(State);
2511
2513 FPU_UPDATE_TAG(0);
2514
2515 break;
2516 }
2517
2518 /* FSINCOS */
2519 case 0x3B:
2520 {
2521 FAST486_FPU_DATA_REG Number = FPU_ST(0);
2522
2523 Fast486FpuExceptionCheck(State);
2525
2526 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2527 {
2528 State->FpuStatus.Ie = TRUE;
2529 break;
2530 }
2531
2532 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2533 {
2534 State->FpuStatus.De = TRUE;
2535
2536 if (!State->FpuControl.Dm)
2537 {
2538 break;
2539 }
2540 }
2541
2542 /* Replace FP0 with the sine */
2543 if (!Fast486FpuCalculateSine(State, &Number, &FPU_ST(0))) break;
2544 FPU_UPDATE_TAG(0);
2545
2546 /* Push the cosine */
2548 Fast486FpuPush(State, &Number);
2549
2550 break;
2551 }
2552
2553 /* FRNDINT */
2554 case 0x3C:
2555 {
2556 LONGLONG Result = 0LL;
2557
2558 Fast486FpuExceptionCheck(State);
2560
2561 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2562 {
2563 State->FpuStatus.Ie = TRUE;
2564 break;
2565 }
2566
2567 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2568 {
2569 State->FpuStatus.De = TRUE;
2570
2571 if (!State->FpuControl.Dm)
2572 {
2573 break;
2574 }
2575 }
2576
2577 /* Do nothing if it's too big to not be an integer */
2578 if (FPU_ST(0).Exponent >= FPU_REAL10_BIAS + 63) break;
2579
2580 /* Perform the rounding */
2583
2584 State->FpuStatus.Pe = TRUE;
2585 break;
2586 }
2587
2588 /* FSCALE */
2589 case 0x3D:
2590 {
2591 LONGLONG Scale;
2592 LONGLONG UnbiasedExp = (LONGLONG)((SHORT)FPU_ST(0).Exponent) - FPU_REAL10_BIAS;
2593 INT OldRoundingMode = State->FpuControl.Rc;
2594
2595 Fast486FpuExceptionCheck(State);
2597
2599 {
2600 State->FpuStatus.Ie = TRUE;
2601 break;
2602 }
2603
2604 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2605 {
2606 State->FpuStatus.De = TRUE;
2607
2608 if (!State->FpuControl.Dm)
2609 {
2610 break;
2611 }
2612 }
2613
2614 State->FpuControl.Rc = FPU_ROUND_TRUNCATE;
2615
2616 if (!Fast486FpuToInteger(State, &FPU_ST(1), &Scale))
2617 {
2618 /* Exception occurred */
2619 State->FpuControl.Rc = OldRoundingMode;
2620 break;
2621 }
2622
2623 State->FpuControl.Rc = OldRoundingMode;
2624
2625 /* Adjust the unbiased exponent */
2626 UnbiasedExp += Scale;
2627
2628 /* Check for underflow */
2629 if (UnbiasedExp < -1023)
2630 {
2631 /* Raise the underflow exception */
2632 State->FpuStatus.Ue = TRUE;
2633
2634 if (State->FpuControl.Um)
2635 {
2636 /* Make the result zero */
2637 FPU_ST(0) = FpuZero;
2638 FPU_UPDATE_TAG(0);
2639 }
2640
2641 break;
2642 }
2643
2644 /* Check for overflow */
2645 if (UnbiasedExp > 1023)
2646 {
2647 /* Raise the overflow exception */
2648 State->FpuStatus.Oe = TRUE;
2649
2650 if (State->FpuControl.Om)
2651 {
2652 /* Make the result infinity */
2653 FPU_ST(0).Mantissa = FPU_MANTISSA_HIGH_BIT;
2654 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
2655 FPU_UPDATE_TAG(0);
2656 }
2657
2658 break;
2659 }
2660
2661 FPU_ST(0).Exponent = (USHORT)(UnbiasedExp + FPU_REAL10_BIAS);
2662 FPU_UPDATE_TAG(0);
2663
2664 break;
2665 }
2666
2667 /* FSIN */
2668 case 0x3E:
2669 {
2670 Fast486FpuExceptionCheck(State);
2672
2673 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2674 {
2675 State->FpuStatus.Ie = TRUE;
2676 break;
2677 }
2678
2679 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2680 {
2681 State->FpuStatus.De = TRUE;
2682
2683 if (!State->FpuControl.Dm)
2684 {
2685 break;
2686 }
2687 }
2688
2690 FPU_UPDATE_TAG(0);
2691
2692 break;
2693 }
2694
2695 /* FCOS */
2696 case 0x3F:
2697 {
2698 Fast486FpuExceptionCheck(State);
2700
2701 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2702 {
2703 State->FpuStatus.Ie = TRUE;
2704 break;
2705 }
2706
2707 if (!FPU_IS_NORMALIZED(&FPU_ST(0)))
2708 {
2709 State->FpuStatus.De = TRUE;
2710
2711 if (!State->FpuControl.Dm)
2712 {
2713 break;
2714 }
2715 }
2716
2718 FPU_UPDATE_TAG(0);
2719
2720 break;
2721 }
2722
2723 /* Invalid */
2724 default:
2725 {
2726 Fast486Exception(State, FAST486_EXCEPTION_UD);
2727 return;
2728 }
2729 }
2730 }
2731
2732#endif
2733}
#define FALSE
Definition: types.h:117
static BOOLEAN FASTCALL Fast486FpuAdd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:773
static BOOLEAN FASTCALL Fast486FpuMultiply(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1000
static BOOLEAN FASTCALL Fast486FpuToSingleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONG Result)
Definition: fpu.c:554
static const FAST486_FPU_DATA_REG FpuOne
Definition: fpu.c:39
static BOOLEAN FASTCALL Fast486FpuCalculateSine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1390
static const FAST486_FPU_DATA_REG FpuLgTwo
Definition: fpu.c:51
static BOOLEAN FASTCALL Fast486FpuCalculateSquareRoot(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1557
static BOOLEAN FASTCALL Fast486FpuCalculateCosine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1470
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
static const FAST486_FPU_DATA_REG FpuZero
Definition: fpu.c:36
static BOOLEAN FASTCALL Fast486FpuCalculateArcTangent(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Numerator, PCFAST486_FPU_DATA_REG Denominator, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1613
static VOID FASTCALL Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1217
static const FAST486_FPU_DATA_REG FpuL2E
Definition: fpu.c:48
static BOOLEAN FASTCALL Fast486FpuCalculateLogBase2(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1265
static const FAST486_FPU_DATA_REG FpuLnTwo
Definition: fpu.c:54
static BOOLEAN FASTCALL Fast486FpuLoadEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1725
static BOOLEAN FASTCALL Fast486FpuRemainder(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, BOOLEAN RoundToNearest, PFAST486_FPU_DATA_REG Result OPTIONAL, PLONGLONG Quotient OPTIONAL)
Definition: fpu.c:1352
static BOOLEAN FASTCALL Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
static const FAST486_FPU_DATA_REG FpuL2Ten
Definition: fpu.c:45
static BOOLEAN FASTCALL Fast486FpuSubtract(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:928
static BOOLEAN FASTCALL Fast486FpuDivide(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1105
static const FAST486_FPU_DATA_REG FpuHalfPi
Definition: fpu.c:60
static BOOLEAN FASTCALL Fast486FpuSaveEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1768
static const FAST486_FPU_DATA_REG FpuPi
Definition: fpu.c:42
#define FPU_REAL4_INDEFINITE
Definition: fpu.h:62
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
#define FPU_IS_ZERO(x)
Definition: fpu.h:67
#define FPU_IS_NORMALIZED(x)
Definition: fpu.h:66
#define FPU_IS_INDEFINITE(x)
Definition: fpu.h:72
#define FPU_IS_INFINITY(x)
Definition: fpu.h:69
#define FPU_MANTISSA_HIGH_BIT
Definition: fpu.h:59
#define FPU_REAL10_BIAS
Definition: fpu.h:57
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
short SHORT
Definition: pedump.c:59
unsigned short USHORT
Definition: pedump.c:61
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
ULONG MemoryAddress
Definition: common.h:81
#define LL
Definition: tui.h:167
int64_t LONGLONG
Definition: typedefs.h:68
int32_t INT
Definition: typedefs.h:58
uint64_t ULONGLONG
Definition: typedefs.h:67
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

◆ FAST486_OPCODE_HANDLER() [3/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDA  )

Definition at line 2735 of file fpu.c.

2736{
2737 FAST486_MOD_REG_RM ModRegRm;
2738 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2739#ifndef FAST486_NO_FPU
2740 LONG Value;
2741 FAST486_FPU_DATA_REG MemoryData;
2742#endif
2743
2744 TOGGLE_ADSIZE(AddressSize);
2745
2746 /* Get the operands */
2747 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2748 {
2749 /* Exception occurred */
2750 return;
2751 }
2752
2753 FPU_CHECK();
2754
2755#ifndef FAST486_NO_FPU
2756
2757 Fast486FpuExceptionCheck(State);
2759
2760 if (!ModRegRm.Memory)
2761 {
2762 /* The only valid opcode in this case is FUCOMPP (0xDA 0xE9) */
2763 if ((ModRegRm.Register != 5) && (ModRegRm.SecondRegister != 1))
2764 {
2765 Fast486Exception(State, FAST486_EXCEPTION_UD);
2766 return;
2767 }
2768
2769 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY))
2770 {
2771 /* Raise the invalid operation exception*/
2772 State->FpuStatus.Ie = TRUE;
2773 return;
2774 }
2775
2776 /* Compare */
2778
2779 /* Pop twice */
2780 Fast486FpuPop(State);
2781 Fast486FpuPop(State);
2782
2783 return;
2784 }
2785
2787
2788 /* Load the source operand from memory */
2789 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, (PULONG)&Value))
2790 {
2791 /* Exception occurred */
2792 return;
2793 }
2794
2795 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
2796 {
2797 /* Raise the invalid operation exception */
2798 State->FpuStatus.Ie = TRUE;
2799
2800 if (State->FpuControl.Im)
2801 {
2802 /* Return the indefinite NaN */
2803 FPU_ST(0).Sign = TRUE;
2804 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
2805 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA;
2806
2808 }
2809
2810 return;
2811 }
2812
2813 Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
2814
2815 /* Perform the requested operation */
2816 Fast486FpuArithmeticOperation(State, ModRegRm.Register, &MemoryData, TRUE);
2817
2818#endif
2819}
long LONG
Definition: pedump.c:60
uint32_t * PULONG
Definition: typedefs.h:59

◆ FAST486_OPCODE_HANDLER() [4/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDB  )

Definition at line 2821 of file fpu.c.

2822{
2823 FAST486_MOD_REG_RM ModRegRm;
2824 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2825
2826 TOGGLE_ADSIZE(AddressSize);
2827
2828 /* Get the operands */
2829 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2830 {
2831 /* Exception occurred */
2832 return;
2833 }
2834
2835 FPU_CHECK();
2836
2837#ifndef FAST486_NO_FPU
2838
2839 if (ModRegRm.Memory)
2840 {
2841 Fast486FpuExceptionCheck(State);
2844
2845 switch (ModRegRm.Register)
2846 {
2847 /* FILD */
2848 case 0:
2849 {
2850 LONG Value;
2851 FAST486_FPU_DATA_REG Temp;
2852
2853 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, (PULONG)&Value))
2854 {
2855 /* Exception occurred */
2856 return;
2857 }
2858
2860 Fast486FpuPush(State, &Temp);
2861
2862 break;
2863 }
2864
2865 /* FIST */
2866 case 2:
2867 /* FISTP */
2868 case 3:
2869 {
2870 LONGLONG Temp = 0;
2871
2873 {
2874 /* Raise the invalid operation exception */
2875 State->FpuStatus.Ie = TRUE;
2876
2877 if (!State->FpuControl.Im)
2878 {
2879 return;
2880 }
2881 }
2882
2883 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
2884 {
2885 /* Exception occurred */
2886 return;
2887 }
2888
2889 /* Check if it can fit in a signed 32-bit integer */
2890 if ((LONGLONG)((LONG)Temp) != Temp)
2891 {
2892 State->FpuStatus.Ie = TRUE;
2893
2894 if (State->FpuControl.Im)
2895 {
2896 Temp = 0x80000000LL;
2897 }
2898 else
2899 {
2900 return;
2901 }
2902 }
2903
2904 if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, (ULONG)((LONG)Temp)))
2905 {
2906 /* Exception occurred */
2907 return;
2908 }
2909
2910 if (ModRegRm.Register == 3)
2911 {
2912 /* Pop the FPU stack too */
2913 Fast486FpuPop(State);
2914 }
2915
2916 break;
2917 }
2918
2919 /* FLD */
2920 case 5:
2921 {
2922 FAST486_FPU_DATA_REG Value;
2923 UCHAR Buffer[10];
2924
2926 (State->PrefixFlags & FAST486_PREFIX_SEG)
2927 ? State->SegmentOverride : FAST486_REG_DS,
2928 ModRegRm.MemoryAddress,
2929 FALSE,
2930 Buffer,
2931 sizeof(Buffer)))
2932 {
2933 /* Exception occurred */
2934 return;
2935 }
2936
2937 Value.Mantissa = *((PULONGLONG)Buffer);
2938 Value.Exponent = *((PUSHORT)&Buffer[8]) & (FPU_MAX_EXPONENT + 1);
2939 Value.Sign = *((PUCHAR)&Buffer[9]) >> 7;
2940
2941 Fast486FpuPush(State, &Value);
2942 break;
2943 }
2944
2945 /* FSTP */
2946 case 7:
2947 {
2948 UCHAR Buffer[10];
2949
2950 if (FPU_GET_TAG(0) != FPU_TAG_EMPTY)
2951 {
2952 *((PULONGLONG)Buffer) = FPU_ST(0).Mantissa;
2953 *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = FPU_ST(0).Exponent
2954 | (FPU_ST(0).Sign ? 0x8000 : 0);
2955 }
2956 else
2957 {
2958 /* Raise the invalid operation exception */
2959 State->FpuStatus.Ie = TRUE;
2960
2961 if (State->FpuControl.Im)
2962 {
2964 *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = 0x8000 | (FPU_MAX_EXPONENT + 1);
2965 }
2966 else
2967 {
2968 return;
2969 }
2970 }
2971
2973 (State->PrefixFlags & FAST486_PREFIX_SEG)
2974 ? State->SegmentOverride : FAST486_REG_DS,
2975 ModRegRm.MemoryAddress,
2976 Buffer,
2977 sizeof(Buffer)))
2978 {
2979 /* Exception occurred */
2980 return;
2981 }
2982
2983 Fast486FpuPop(State);
2984 break;
2985 }
2986
2987 /* Invalid */
2988 default:
2989 {
2990 Fast486Exception(State, FAST486_EXCEPTION_UD);
2991 return;
2992 }
2993 }
2994 }
2995 else
2996 {
2997 /* Only a few of these instructions have any meaning on a 487 */
2998 switch ((ModRegRm.Register << 3) | ModRegRm.SecondRegister)
2999 {
3000 /* FCLEX */
3001 case 0x22:
3002 {
3003 /* Clear exception data */
3004 State->FpuStatus.Ie =
3005 State->FpuStatus.De =
3006 State->FpuStatus.Ze =
3007 State->FpuStatus.Oe =
3008 State->FpuStatus.Ue =
3009 State->FpuStatus.Pe =
3010 State->FpuStatus.Sf =
3011 State->FpuStatus.Es =
3012 State->FpuStatus.Busy = FALSE;
3013
3014 break;
3015 }
3016
3017 /* FINIT */
3018 case 0x23:
3019 {
3020 /* Restore the state */
3021 State->FpuControl.Value = FAST486_FPU_DEFAULT_CONTROL;
3022 State->FpuStatus.Value = 0;
3023 State->FpuTag = 0xFFFF;
3024
3025 break;
3026 }
3027
3028 /* FENI */
3029 case 0x20:
3030 /* FDISI */
3031 case 0x21:
3032 /* FSETPM */
3033 case 0x24:
3034 /* FRSTPM */
3035 case 0x25:
3036 {
3037 /* These do nothing */
3038 break;
3039 }
3040
3041 /* Invalid */
3042 default:
3043 {
3044 Fast486Exception(State, FAST486_EXCEPTION_UD);
3045 return;
3046 }
3047 }
3048 }
3049
3050#endif
3051}
Definition: bufpool.h:45
#define FAST486_FPU_DEFAULT_CONTROL
Definition: fast486.h:105
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
uint16_t * PUSHORT
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
unsigned char UCHAR
Definition: xmlstorage.h:181

◆ FAST486_OPCODE_HANDLER() [5/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDC  )

Definition at line 3053 of file fpu.c.

3054{
3055 FAST486_MOD_REG_RM ModRegRm;
3056 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3057#ifndef FAST486_NO_FPU
3058 PFAST486_FPU_DATA_REG Operand;
3059 FAST486_FPU_DATA_REG MemoryData;
3060#endif
3061
3062 TOGGLE_ADSIZE(AddressSize);
3063
3064 /* Get the operands */
3065 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3066 {
3067 /* Exception occurred */
3068 return;
3069 }
3070
3071 FPU_CHECK();
3072
3073#ifndef FAST486_NO_FPU
3074
3075 Fast486FpuExceptionCheck(State);
3077
3078 if (ModRegRm.Memory)
3079 {
3081
3082 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3083 {
3084 /* Raise the invalid operation exception */
3085 State->FpuStatus.Ie = TRUE;
3086
3087 if (State->FpuControl.Im)
3088 {
3089 /* Return the indefinite NaN */
3090 FPU_ST(0).Sign = TRUE;
3091 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
3092 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA;
3093
3095 }
3096
3097 return;
3098 }
3099
3100 /* Load the source operand from memory */
3102 (State->PrefixFlags & FAST486_PREFIX_SEG)
3103 ? State->SegmentOverride : FAST486_REG_DS,
3104 ModRegRm.MemoryAddress,
3105 FALSE,
3106 &Value,
3107 sizeof(ULONGLONG)))
3108 {
3109 /* Exception occurred */
3110 return;
3111 }
3112
3113 Fast486FpuFromDoubleReal(State, Value, &MemoryData);
3114 Operand = &MemoryData;
3115
3117 }
3118 else
3119 {
3120 /* Load the destination operand from an FPU register */
3121 Operand = &FPU_ST(ModRegRm.SecondRegister);
3122
3123 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3124 || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3125 {
3126 /* Raise the invalid operation exception */
3127 State->FpuStatus.Ie = TRUE;
3128
3129 if (State->FpuControl.Im)
3130 {
3131 /* Return the indefinite NaN */
3132 Operand->Sign = TRUE;
3133 Operand->Exponent = FPU_MAX_EXPONENT + 1;
3134 Operand->Mantissa = FPU_INDEFINITE_MANTISSA;
3135
3137 }
3138
3139 return;
3140 }
3141 }
3142
3143 /* Perform the requested operation */
3144 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory);
3145
3146#endif
3147}
static VOID FASTCALL Fast486FpuFromDoubleReal(PFAST486_STATE State, ULONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:631

◆ FAST486_OPCODE_HANDLER() [6/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDD  )

Definition at line 3149 of file fpu.c.

3150{
3151 FAST486_MOD_REG_RM ModRegRm;
3152 BOOLEAN OperandSize, AddressSize;
3153
3154 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3155 TOGGLE_OPSIZE(OperandSize);
3156 TOGGLE_ADSIZE(AddressSize);
3157
3158 /* Get the operands */
3159 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3160 {
3161 /* Exception occurred */
3162 return;
3163 }
3164
3165 FPU_CHECK();
3166
3167#ifndef FAST486_NO_FPU
3168
3169 if (ModRegRm.Memory)
3170 {
3171 switch (ModRegRm.Register)
3172 {
3173 /* FLD */
3174 case 0:
3175 {
3177 FAST486_FPU_DATA_REG MemoryData;
3178
3179 Fast486FpuExceptionCheck(State);
3182
3184 (State->PrefixFlags & FAST486_PREFIX_SEG)
3185 ? State->SegmentOverride : FAST486_REG_DS,
3186 ModRegRm.MemoryAddress,
3187 FALSE,
3188 &Value,
3189 sizeof(ULONGLONG)))
3190 {
3191 /* Exception occurred */
3192 return;
3193 }
3194
3195 Fast486FpuFromDoubleReal(State, Value, &MemoryData);
3196 Fast486FpuPush(State, &MemoryData);
3197
3198 break;
3199 }
3200
3201 /* FST */
3202 case 2:
3203 /* FSTP */
3204 case 3:
3205 {
3207
3208 Fast486FpuExceptionCheck(State);
3211
3212 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3213 {
3214 /* Raise the invalid operation exception */
3215 State->FpuStatus.Ie = TRUE;
3216
3217 if (!State->FpuControl.Im)
3218 {
3219 return;
3220 }
3221 }
3222 else if (!Fast486FpuToDoubleReal(State, &FPU_ST(0), &Value))
3223 {
3224 /* Exception occurred */
3225 return;
3226 }
3227
3229 (State->PrefixFlags & FAST486_PREFIX_SEG)
3230 ? State->SegmentOverride : FAST486_REG_DS,
3231 ModRegRm.MemoryAddress,
3232 &Value,
3233 sizeof(ULONGLONG)))
3234 {
3235 /* Exception occurred */
3236 return;
3237 }
3238
3239 if (ModRegRm.Register == 3) Fast486FpuPop(State);
3240 break;
3241 }
3242
3243 /* FRSTOR */
3244 case 4:
3245 {
3246 INT i;
3247 UCHAR AllRegs[80];
3248
3249 /* Save the environment */
3251 (State->PrefixFlags & FAST486_PREFIX_SEG)
3252 ? State->SegmentOverride : FAST486_REG_DS,
3253 ModRegRm.MemoryAddress,
3254 OperandSize))
3255 {
3256 /* Exception occurred */
3257 return;
3258 }
3259
3260 /* Load the registers */
3262 (State->PrefixFlags & FAST486_PREFIX_SEG)
3263 ? State->SegmentOverride : FAST486_REG_DS,
3264 ModRegRm.MemoryAddress + (OperandSize + 1) * 14,
3265 FALSE,
3266 AllRegs,
3267 sizeof(AllRegs)))
3268 {
3269 /* Exception occurred */
3270 return;
3271 }
3272
3273 for (i = 0; i < FAST486_NUM_FPU_REGS; i++)
3274 {
3275 State->FpuRegisters[i].Mantissa = *((PULONGLONG)&AllRegs[i * 10]);
3276 State->FpuRegisters[i].Exponent = *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x7FFF;
3277
3278 if (*((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) & 0x8000)
3279 {
3280 State->FpuRegisters[i].Sign = TRUE;
3281 }
3282 else
3283 {
3284 State->FpuRegisters[i].Sign = FALSE;
3285 }
3286 }
3287
3288 break;
3289 }
3290
3291 /* FSAVE */
3292 case 6:
3293 {
3294 INT i;
3295 UCHAR AllRegs[80];
3296
3297 /* Save the environment */
3299 (State->PrefixFlags & FAST486_PREFIX_SEG)
3300 ? State->SegmentOverride : FAST486_REG_DS,
3301 ModRegRm.MemoryAddress,
3302 OperandSize))
3303 {
3304 /* Exception occurred */
3305 return;
3306 }
3307
3308 /* Save the registers */
3309 for (i = 0; i < FAST486_NUM_FPU_REGS; i++)
3310 {
3311 *((PULONGLONG)&AllRegs[i * 10]) = State->FpuRegisters[i].Mantissa;
3312 *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) = State->FpuRegisters[i].Exponent;
3313
3314 if (State->FpuRegisters[i].Sign)
3315 {
3316 *((PUSHORT)&AllRegs[(i * 10) + sizeof(ULONGLONG)]) |= 0x8000;
3317 }
3318 }
3319
3321 (State->PrefixFlags & FAST486_PREFIX_SEG)
3322 ? State->SegmentOverride : FAST486_REG_DS,
3323 ModRegRm.MemoryAddress + (OperandSize + 1) * 14,
3324 AllRegs,
3325 sizeof(AllRegs));
3326
3327 break;
3328 }
3329
3330 /* FSTSW */
3331 case 7:
3332 {
3333 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->FpuStatus.Value);
3334 break;
3335 }
3336
3337 /* Invalid */
3338 default:
3339 {
3340 Fast486Exception(State, FAST486_EXCEPTION_UD);
3341 }
3342 }
3343 }
3344 else
3345 {
3346 switch (ModRegRm.Register)
3347 {
3348 /* FFREE */
3349 case 0:
3350 {
3352 break;
3353 }
3354
3355 /* FXCH */
3356 case 1:
3357 {
3358 FAST486_FPU_DATA_REG Temp;
3359
3361 Fast486FpuExceptionCheck(State);
3362
3363 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3365 {
3366 State->FpuStatus.Ie = TRUE;
3367 break;
3368 }
3369
3370 /* Exchange */
3371 Temp = FPU_ST(0);
3372 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
3373 FPU_ST(ModRegRm.SecondRegister) = Temp;
3374
3375 FPU_UPDATE_TAG(0);
3377
3378 break;
3379 }
3380
3381 /* FST */
3382 case 2:
3383 /* FSTP */
3384 case 3:
3385 {
3387 Fast486FpuExceptionCheck(State);
3388
3389 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
3391
3392 if (ModRegRm.Register == 3) Fast486FpuPop(State);
3393 break;
3394 }
3395
3396 /* FUCOM */
3397 case 4:
3398 /* FUCOMP */
3399 case 5:
3400 {
3402 Fast486FpuExceptionCheck(State);
3403
3404 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3405 || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3406 {
3407 State->FpuStatus.Ie = TRUE;
3408 return;
3409 }
3410
3412 if (ModRegRm.Register == 5) Fast486FpuPop(State);
3413
3414 break;
3415 }
3416
3417 /* Invalid */
3418 default:
3419 {
3420 Fast486Exception(State, FAST486_EXCEPTION_UD);
3421 }
3422 }
3423 }
3424
3425#endif
3426}
#define FAST486_NUM_FPU_REGS
Definition: fast486.h:44
static BOOLEAN FASTCALL Fast486FpuToDoubleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONGLONG Result)
Definition: fpu.c:652
#define FPU_REAL8_INDEFINITE
Definition: fpu.h:64

◆ FAST486_OPCODE_HANDLER() [7/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDE  )

Definition at line 3428 of file fpu.c.

3429{
3430 FAST486_MOD_REG_RM ModRegRm;
3431 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3432#ifndef FAST486_NO_FPU
3433 PFAST486_FPU_DATA_REG Operand;
3434 FAST486_FPU_DATA_REG MemoryData;
3435#endif
3436
3437 TOGGLE_ADSIZE(AddressSize);
3438
3439 /* Get the operands */
3440 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3441 {
3442 /* Exception occurred */
3443 return;
3444 }
3445
3446 FPU_CHECK();
3447
3448#ifndef FAST486_NO_FPU
3449
3451 Fast486FpuExceptionCheck(State);
3452
3453 if (ModRegRm.Memory)
3454 {
3455 SHORT Value;
3456
3457 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3458 {
3459 /* Raise the invalid operation exception */
3460 State->FpuStatus.Ie = TRUE;
3461
3462 if (State->FpuControl.Im)
3463 {
3464 /* Return the indefinite NaN */
3465 FPU_ST(0).Sign = TRUE;
3466 FPU_ST(0).Exponent = FPU_MAX_EXPONENT + 1;
3467 FPU_ST(0).Mantissa = FPU_INDEFINITE_MANTISSA;
3468
3470 }
3471
3472 return;
3473 }
3474
3475 /* Load the source operand from memory */
3476 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
3477 {
3478 /* Exception occurred */
3479 return;
3480 }
3481
3482 Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
3483 Operand = &MemoryData;
3484
3486 }
3487 else
3488 {
3489 /* FCOMPP check */
3490 if ((ModRegRm.Register == 3) && (ModRegRm.SecondRegister != 1))
3491 {
3492 /* Invalid */
3493 Fast486Exception(State, FAST486_EXCEPTION_UD);
3494 return;
3495 }
3496
3497 /* Load the destination operand from a register */
3498 Operand = &FPU_ST(ModRegRm.SecondRegister);
3499
3500 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3501 || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
3502 {
3503 /* Raise the invalid operation exception, if unmasked */
3504 State->FpuStatus.Ie = TRUE;
3505 return;
3506 }
3507 }
3508
3509 /* Perform the requested operation */
3510 Fast486FpuArithmeticOperation(State, ModRegRm.Register, Operand, ModRegRm.Memory);
3511 if (!ModRegRm.Memory) Fast486FpuPop(State);
3512
3513#endif
3514}

◆ FAST486_OPCODE_HANDLER() [8/8]

FAST486_OPCODE_HANDLER ( Fast486FpuOpcodeDF  )

Definition at line 3516 of file fpu.c.

3517{
3518 FAST486_MOD_REG_RM ModRegRm;
3519 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3520
3521 TOGGLE_ADSIZE(AddressSize);
3522
3523 /* Get the operands */
3524 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3525 {
3526 /* Exception occurred */
3527 return;
3528 }
3529
3530 FPU_CHECK();
3531
3532#ifndef FAST486_NO_FPU
3533
3535 Fast486FpuExceptionCheck(State);
3536
3537 if (ModRegRm.Memory)
3538 {
3540
3541 switch (ModRegRm.Register)
3542 {
3543 /* FILD */
3544 case 0:
3545 {
3546 SHORT Value;
3547 FAST486_FPU_DATA_REG Temp;
3548
3549 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
3550 {
3551 /* Exception occurred */
3552 return;
3553 }
3554
3556 Fast486FpuPush(State, &Temp);
3557
3558 break;
3559 }
3560
3561 /* FIST */
3562 case 2:
3563 /* FISTP */
3564 case 3:
3565 {
3566 LONGLONG Temp = 0LL;
3567
3569 {
3570 /* Raise the invalid operation exception */
3571 State->FpuStatus.Ie = TRUE;
3572
3573 if (!State->FpuControl.Im)
3574 {
3575 return;
3576 }
3577 }
3578
3579 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
3580 {
3581 /* Exception occurred */
3582 return;
3583 }
3584
3585 /* Check if it can fit in a signed 16-bit integer */
3586 if ((LONGLONG)((SHORT)Temp) != Temp)
3587 {
3588 /* Raise the invalid operation exception */
3589 State->FpuStatus.Ie = TRUE;
3590
3591 if (State->FpuControl.Im)
3592 {
3593 Temp = 0x8000LL;
3594 }
3595 else
3596 {
3597 return;
3598 }
3599 }
3600
3601 if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, (USHORT)((SHORT)Temp)))
3602 {
3603 /* Exception occurred */
3604 return;
3605 }
3606
3607 if (ModRegRm.Register == 3)
3608 {
3609 /* Pop the FPU stack too */
3610 Fast486FpuPop(State);
3611 }
3612
3613 break;
3614 }
3615
3616 /* FBLD */
3617 case 4:
3618 {
3619 FAST486_FPU_DATA_REG Value;
3620 UCHAR Buffer[10];
3621
3623 (State->PrefixFlags & FAST486_PREFIX_SEG)
3624 ? State->SegmentOverride : FAST486_REG_DS,
3625 ModRegRm.MemoryAddress,
3626 FALSE,
3627 Buffer,
3628 sizeof(Buffer)))
3629 {
3630 /* Exception occurred */
3631 return;
3632 }
3633
3635 Fast486FpuPush(State, &Value);
3636
3637 break;
3638 }
3639
3640 /* FILD (64-bit int) */
3641 case 5:
3642 {
3644 FAST486_FPU_DATA_REG Temp;
3645
3647 (State->PrefixFlags & FAST486_PREFIX_SEG)
3648 ? State->SegmentOverride : FAST486_REG_DS,
3649 ModRegRm.MemoryAddress,
3650 FALSE,
3651 &Value,
3652 sizeof(LONGLONG)))
3653 {
3654 /* Exception occurred */
3655 return;
3656 }
3657
3659 Fast486FpuPush(State, &Temp);
3660
3661 break;
3662 }
3663
3664 /* FBSTP */
3665 case 6:
3666 {
3667 UCHAR Buffer[10] = {0};
3668
3669 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3670 {
3671 /* Raise the invalid operation exception */
3672 State->FpuStatus.Ie = TRUE;
3673
3674 if (!State->FpuControl.Im)
3675 {
3676 return;
3677 }
3678 }
3679 else if (!Fast486FpuToPackedBcd(State, &FPU_ST(0), Buffer))
3680 {
3681 /* Exception occurred */
3682 return;
3683 }
3684
3686 (State->PrefixFlags & FAST486_PREFIX_SEG)
3687 ? State->SegmentOverride : FAST486_REG_DS,
3688 ModRegRm.MemoryAddress,
3689 Buffer,
3690 sizeof(Buffer)))
3691 {
3692 /* Exception occurred */
3693 return;
3694 }
3695
3696 Fast486FpuPop(State);
3697 break;
3698 }
3699
3700 /* FISTP (64-bit int) */
3701 case 7:
3702 {
3703 LONGLONG Temp = 0LL;
3704
3706 {
3707 /* Raise the invalid operation exception */
3708 State->FpuStatus.Ie = TRUE;
3709
3710 if (!State->FpuControl.Im)
3711 {
3712 return;
3713 }
3714 }
3715
3716 if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
3717 {
3718 /* Exception occurred */
3719 return;
3720 }
3721
3723 (State->PrefixFlags & FAST486_PREFIX_SEG)
3724 ? State->SegmentOverride : FAST486_REG_DS,
3725 ModRegRm.MemoryAddress,
3726 &Temp,
3727 sizeof(LONGLONG)))
3728 {
3729 /* Exception occurred */
3730 return;
3731 }
3732
3733 /* Pop the FPU stack too */
3734 Fast486FpuPop(State);
3735
3736 break;
3737 }
3738
3739 /* Invalid */
3740 default:
3741 {
3742 Fast486Exception(State, FAST486_EXCEPTION_UD);
3743 }
3744 }
3745 }
3746 else
3747 {
3748 switch (ModRegRm.Register)
3749 {
3750 /* FFREEP */
3751 case 0:
3752 {
3754 Fast486FpuPop(State);
3755
3756 break;
3757 }
3758
3759 /* FXCH */
3760 case 1:
3761 {
3762 FAST486_FPU_DATA_REG Temp;
3763
3764 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
3766 {
3767 State->FpuStatus.Ie = TRUE;
3768 break;
3769 }
3770
3771 /* Exchange */
3772 Temp = FPU_ST(0);
3773 FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister);
3774 FPU_ST(ModRegRm.SecondRegister) = Temp;
3775
3776 FPU_UPDATE_TAG(0);
3778
3779 break;
3780 }
3781
3782 /* FSTP */
3783 case 2:
3784 case 3:
3785 {
3786 FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
3788 Fast486FpuPop(State);
3789
3790 break;
3791 }
3792
3793 /* FSTSW */
3794 case 4:
3795 {
3796 if (ModRegRm.SecondRegister != 0)
3797 {
3798 /* Invalid */
3799 Fast486Exception(State, FAST486_EXCEPTION_UD);
3800 return;
3801 }
3802
3803 /* Store the status word in AX */
3804 State->GeneralRegs[FAST486_REG_EAX].LowWord = State->FpuStatus.Value;
3805
3806 break;
3807 }
3808
3809 /* Invalid */
3810 default:
3811 {
3812 Fast486Exception(State, FAST486_EXCEPTION_UD);
3813 return;
3814 }
3815 }
3816 }
3817
3818#endif
3819}
static VOID FASTCALL Fast486FpuFromPackedBcd(PFAST486_STATE State, PUCHAR Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:726
static BOOLEAN FASTCALL Fast486FpuToPackedBcd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PUCHAR Result)
Definition: fpu.c:747