ReactOS  0.4.14-dev-98-gb0d4763
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.

◆ 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,
87  FPU_TAG_SPECIAL = 2,
88  FPU_TAG_EMPTY = 3
89 };

◆ 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 {
94  FPU_ROUND_DOWN = 1,
95  FPU_ROUND_UP = 2,
97 };

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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
static VOID FASTCALL Fast486FpuFromSingleReal(PFAST486_STATE State, ULONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:533
FAST486_GEN_REGS Register
Definition: common.h:76
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
unsigned int ULONG
Definition: retypes.h:1
#define FPU_GET_TAG(i)
Definition: fpu.h:39
BOOLEAN Memory
Definition: common.h:77

◆ 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)
2072  || FPU_GET_TAG(ModRegRm.SecondRegister) == 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);
2084  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
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);
2110  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
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 */
2408  (LONGLONG)Value.Exponent - (LONGLONG)FPU_REAL10_BIAS,
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 */
2547  if (!Fast486FpuCalculateCosine(State, &Number, &Number)) break;
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:85
static const FAST486_FPU_DATA_REG FpuL2Ten
Definition: fpu.c:45
#define FPU_IS_NORMALIZED(x)
Definition: fpu.h:66
#define FPU_IS_ZERO(x)
Definition: fpu.h:67
static BOOLEAN FASTCALL Fast486FpuSaveEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1768
static VOID FASTCALL Fast486FpuFromSingleReal(PFAST486_STATE State, ULONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:533
#define FPU_IS_INDEFINITE(x)
Definition: fpu.h:72
static const FAST486_FPU_DATA_REG FpuLgTwo
Definition: fpu.c:51
static const FAST486_FPU_DATA_REG FpuZero
Definition: fpu.c:36
static VOID FASTCALL Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1217
FAST486_GEN_REGS Register
Definition: common.h:76
int32_t INT
Definition: typedefs.h:56
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
static BOOLEAN FASTCALL Fast486FpuCalculateLogBase2(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1265
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
short SHORT
Definition: pedump.c:59
#define FPU_CHECK()
Definition: fpu.h:31
static BOOLEAN FASTCALL Fast486FpuToSingleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONG Result)
Definition: fpu.c:554
static BOOLEAN FASTCALL Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_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:426
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
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 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 Fast486FpuMultiply(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1000
#define FPU_IS_INFINITY(x)
Definition: fpu.h:69
uint64_t ULONGLONG
Definition: typedefs.h:65
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
#define FPU_MANTISSA_HIGH_BIT
Definition: fpu.h:59
#define FPU_REAL4_INDEFINITE
Definition: fpu.h:62
#define FPU_REAL10_BIAS
Definition: fpu.h:57
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
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
static const FAST486_FPU_DATA_REG FpuLnTwo
Definition: fpu.c:54
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
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
static const FAST486_FPU_DATA_REG FpuPi
Definition: fpu.c:42
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
unsigned short USHORT
Definition: pedump.c:61
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
static const FAST486_FPU_DATA_REG FpuOne
Definition: fpu.c:39
unsigned int ULONG
Definition: retypes.h:1
#define FPU_GET_TAG(i)
Definition: fpu.h:39
static BOOLEAN FASTCALL Fast486FpuCalculateSquareRoot(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1557
ULONG MemoryAddress
Definition: common.h:81
static BOOLEAN FASTCALL Fast486FpuCalculateCosine(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Operand, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:1470
static BOOLEAN FASTCALL Fast486FpuLoadEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1725
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 FpuL2E
Definition: fpu.c:48
static const FAST486_FPU_DATA_REG FpuHalfPi
Definition: fpu.c:60
BOOLEAN Memory
Definition: common.h:77

◆ 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 */
2777  Fast486FpuCompare(State, &FPU_ST(0), &FPU_ST(1));
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
FAST486_GEN_REGS Register
Definition: common.h:76
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
long LONG
Definition: pedump.c:60
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
unsigned int * PULONG
Definition: retypes.h:1
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_GET_TAG(i)
Definition: fpu.h:39
BOOLEAN Memory
Definition: common.h:77

◆ 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 
2872  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
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 
2925  if (!Fast486ReadMemory(State,
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:85
unsigned char * PUCHAR
Definition: retypes.h:3
FAST486_GEN_REGS Register
Definition: common.h:76
long LONG
Definition: pedump.c:60
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
static BOOLEAN FASTCALL Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
uint64_t ULONGLONG
Definition: typedefs.h:65
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FAST486_FPU_DEFAULT_CONTROL
Definition: fast486.h:105
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
unsigned int * PULONG
Definition: retypes.h:1
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
unsigned int ULONG
Definition: retypes.h:1
#define FPU_GET_TAG(i)
Definition: fpu.h:39
ULONG MemoryAddress
Definition: common.h:81
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN Memory
Definition: common.h:77

◆ 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  {
3080  ULONGLONG Value;
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 */
3101  if (!Fast486ReadMemory(State,
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
static VOID FASTCALL Fast486FpuFromDoubleReal(PFAST486_STATE State, ULONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:631
#define TRUE
Definition: types.h:120
FAST486_GEN_REGS Register
Definition: common.h:76
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
unsigned char BOOLEAN
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
uint64_t ULONGLONG
Definition: typedefs.h:65
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_GET_TAG(i)
Definition: fpu.h:39
ULONG MemoryAddress
Definition: common.h:81
BOOLEAN Memory
Definition: common.h:77

◆ 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  {
3176  ULONGLONG Value;
3177  FAST486_FPU_DATA_REG MemoryData;
3178 
3179  Fast486FpuExceptionCheck(State);
3182 
3183  if (!Fast486ReadMemory(State,
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 */
3261  if (!Fast486ReadMemory(State,
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)
3364  || FPU_GET_TAG(ModRegRm.SecondRegister) == 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);
3376  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
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);
3390  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
static VOID FASTCALL Fast486FpuFromDoubleReal(PFAST486_STATE State, ULONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:631
#define TRUE
Definition: types.h:120
static BOOLEAN FASTCALL Fast486FpuSaveEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1768
FAST486_GEN_REGS Register
Definition: common.h:76
int32_t INT
Definition: typedefs.h:56
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
#define FPU_REAL8_INDEFINITE
Definition: fpu.h:64
static VOID FASTCALL Fast486FpuCompare(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand)
Definition: fpu.c:943
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
static BOOLEAN FASTCALL Fast486FpuToDoubleReal(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PULONGLONG Result)
Definition: fpu.c:652
#define FPU_CHECK()
Definition: fpu.h:31
unsigned char BOOLEAN
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
uint64_t ULONGLONG
Definition: typedefs.h:65
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
#define FAST486_NUM_FPU_REGS
Definition: fast486.h:44
#define FPU_GET_TAG(i)
Definition: fpu.h:39
ULONG MemoryAddress
Definition: common.h:81
static BOOLEAN FASTCALL Fast486FpuLoadEnvironment(PFAST486_STATE State, INT Segment, ULONG Address, BOOLEAN Size)
Definition: fpu.c:1725
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN Memory
Definition: common.h:77

◆ 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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
FAST486_GEN_REGS Register
Definition: common.h:76
short SHORT
Definition: pedump.c:59
#define FPU_INDEFINITE_MANTISSA
Definition: fpu.h:60
#define FPU_CHECK()
Definition: fpu.h:31
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
#define FPU_MAX_EXPONENT
Definition: fpu.h:58
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
static VOID FASTCALL Fast486FpuArithmeticOperation(PFAST486_STATE State, INT Operation, PFAST486_FPU_DATA_REG Operand, BOOLEAN TopDestination)
Definition: fpu.c:1484
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_GET_TAG(i)
Definition: fpu.h:39
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN Memory
Definition: common.h:77

◆ 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 
3568  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
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 
3622  if (!Fast486ReadMemory(State,
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  {
3643  LONGLONG Value;
3644  FAST486_FPU_DATA_REG Temp;
3645 
3646  if (!Fast486ReadMemory(State,
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 
3705  if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
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)
3765  || FPU_GET_TAG(ModRegRm.SecondRegister) == 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);
3777  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
3778 
3779  break;
3780  }
3781 
3782  /* FSTP */
3783  case 2:
3784  case 3:
3785  {
3786  FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0);
3787  FPU_UPDATE_TAG(ModRegRm.SecondRegister);
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 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FPU_ST(i)
Definition: fpu.h:37
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:85
FAST486_GEN_REGS Register
Definition: common.h:76
#define FPU_UPDATE_TAG(i)
Definition: fpu.h:44
short SHORT
Definition: pedump.c:59
#define FPU_CHECK()
Definition: fpu.h:31
static BOOLEAN FASTCALL Fast486FpuToInteger(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PLONGLONG Result)
Definition: fpu.c:467
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
#define FPU_SAVE_LAST_INST()
Definition: fpu.h:45
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
static BOOLEAN FASTCALL Fast486FpuToPackedBcd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG Value, PUCHAR Result)
Definition: fpu.c:747
unsigned char UCHAR
Definition: xmlstorage.h:181
static VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:444
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
static VOID FASTCALL Fast486FpuFromPackedBcd(PFAST486_STATE State, PUCHAR Value, PFAST486_FPU_DATA_REG Result)
Definition: fpu.c:726
#define FPU_SET_TAG(i, t)
Definition: fpu.h:40
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
unsigned short USHORT
Definition: pedump.c:61
#define FPU_SAVE_LAST_OPERAND()
Definition: fpu.h:49
#define FPU_GET_TAG(i)
Definition: fpu.h:39
ULONG MemoryAddress
Definition: common.h:81
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN Memory
Definition: common.h:77