Previous 15994 Revisions Next

r14219 Thursday 26th January, 2012 at 23:36:05 UTC by Angelo Salese
x87 rewrite porting from Phil Bennett
[src/emu/cpu/i386]i386.c i386ops.h i386priv.h x87ops.c

src/emu/cpu/i386/i386priv.h
r14218r14219
44#define __I386_H__
55
66#include "i386.h"
7#include "../../../lib/softfloat/milieu.h"
8#include "../../../lib/softfloat/softfloat.h"
79
810#define I386OP(XX)      i386_##XX
911#define I486OP(XX)      i486_##XX
r14218r14219
140142
141143   X87_CTRL,
142144   X87_STATUS,
145   X87_TAG,
143146   X87_ST0,
144147   X87_ST1,
145148   X87_ST2,
r14218r14219
276279   UINT32 feature_flags;
277280   UINT64 tsc;
278281
282
279283   // FPU
280   X87_REG fpu_reg[8];
281   UINT16 fpu_control_word;
282   UINT16 fpu_status_word;
283   UINT16 fpu_tag_word;
284   UINT64 fpu_data_ptr;
285   UINT64 fpu_inst_ptr;
286   UINT16 fpu_opcode;
287   int fpu_top;
284   floatx80 x87_reg[8];
288285
286   UINT16 x87_cw;
287   UINT16 x87_sw;
288   UINT16 x87_tw;
289   UINT64 x87_data_ptr;
290   UINT64 x87_inst_ptr;
291   UINT16 x87_opcode;
292
293   void (*opcode_table_x87_d8[256])(i386_state *cpustate, UINT8 modrm);
294   void (*opcode_table_x87_d9[256])(i386_state *cpustate, UINT8 modrm);
295   void (*opcode_table_x87_da[256])(i386_state *cpustate, UINT8 modrm);
296   void (*opcode_table_x87_db[256])(i386_state *cpustate, UINT8 modrm);
297   void (*opcode_table_x87_dc[256])(i386_state *cpustate, UINT8 modrm);
298   void (*opcode_table_x87_dd[256])(i386_state *cpustate, UINT8 modrm);
299   void (*opcode_table_x87_de[256])(i386_state *cpustate, UINT8 modrm);
300   void (*opcode_table_x87_df[256])(i386_state *cpustate, UINT8 modrm);
301
302
289303   void (*opcode_table1_16[256])(i386_state *cpustate);
290304   void (*opcode_table1_32[256])(i386_state *cpustate);
291305   void (*opcode_table2_16[256])(i386_state *cpustate);
src/emu/cpu/i386/i386ops.h
r14218r14219
244244   { 0xDD,      OP_I386,               I386OP(escape),               I386OP(escape),            },
245245   { 0xDE,      OP_I386,               I386OP(escape),               I386OP(escape),            },
246246   { 0xDF,      OP_I386,               I386OP(escape),               I386OP(escape),            },
247   { 0xD8,      OP_FPU,                  I386OP(fpu_group_d8),         I386OP(fpu_group_d8),      },
248   { 0xD9,      OP_FPU,                  I386OP(fpu_group_d9),         I386OP(fpu_group_d9),      },
249   { 0xDA,      OP_FPU,                  I386OP(fpu_group_da),         I386OP(fpu_group_da),      },
250   { 0xDB,      OP_FPU,                  I386OP(fpu_group_db),         I386OP(fpu_group_db),      },
251   { 0xDC,      OP_FPU,                  I386OP(fpu_group_dc),         I386OP(fpu_group_dc),      },
252   { 0xDD,      OP_FPU,                  I386OP(fpu_group_dd),         I386OP(fpu_group_dd),      },
253   { 0xDE,      OP_FPU,                  I386OP(fpu_group_de),         I386OP(fpu_group_de),      },
254   { 0xDF,      OP_FPU,                  I386OP(fpu_group_df),         I386OP(fpu_group_df),      },
247   { 0xD8,      OP_FPU,                  I386OP(x87_group_d8),         I386OP(x87_group_d8),      },
248   { 0xD9,      OP_FPU,                  I386OP(x87_group_d9),         I386OP(x87_group_d9),      },
249   { 0xDA,      OP_FPU,                  I386OP(x87_group_da),         I386OP(x87_group_da),      },
250   { 0xDB,      OP_FPU,                  I386OP(x87_group_db),         I386OP(x87_group_db),      },
251   { 0xDC,      OP_FPU,                  I386OP(x87_group_dc),         I386OP(x87_group_dc),      },
252   { 0xDD,      OP_FPU,                  I386OP(x87_group_dd),         I386OP(x87_group_dd),      },
253   { 0xDE,      OP_FPU,                  I386OP(x87_group_de),         I386OP(x87_group_de),      },
254   { 0xDF,      OP_FPU,                  I386OP(x87_group_df),         I386OP(x87_group_df),      },
255255   { 0xE0,      OP_I386,               I386OP(loopne16),            I386OP(loopne32),         },
256256   { 0xE1,      OP_I386,               I386OP(loopz16),            I386OP(loopz32),         },
257257   { 0xE2,      OP_I386,               I386OP(loop16),               I386OP(loop32),            },
src/emu/cpu/i386/x87ops.c
r14218r14219
1// Intel x87 FPU opcodes
1/***************************************************************************
22
3// TODO:
4// - double check single precision opcodes;
5// - opcode cycles (every single CPU has different counting on it);
6// - clean-ups;
3    x87 FPU emulation
74
8#include "../../../lib/softfloat/milieu.h"
9#include "../../../lib/softfloat/softfloat.h"
5   TODO:
6    - 80-bit precision for F2XM1, FYL2X, FPATAN
7    - Cycle counts for all processors (currently using 486 counts)
8    - Precision-dependent cycle counts for divide instructions
9    - Last instruction, operand pointers etc.
10    - Fix FLDENV, FSTENV, FSAVE, FRSTOR and FPREM
11    - Status word C2 updates to reflect round up/down
12    - Handling of invalid and denormal numbers
13    - Remove redundant operand checks
14    - Exceptions
1015
11#define ST(x)   (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7])
12#define FPU_INFINITY_DOUBLE      U64(0x7ff0000000000000)
13#define FPU_INFINITY_SINGLE      (0x7f800000)
14#define FPU_SIGN_BIT_DOUBLE      U64(0x8000000000000000)
15#define FPU_SIGN_BIT_SINGLE      (0x80000000)
16#define FPU_MANTISSA_DOUBLE      U64(0x000fffffffffffff)
16***************************************************************************/
1717
18#include <math.h>
1819
19// FPU control word flags
20#define FPU_MASK_INVALID_OP         0x0001
21#define FPU_MASK_DENORMAL_OP      0x0002
22#define FPU_MASK_ZERO_DIVIDE      0x0004
23#define FPU_MASK_OVERFLOW         0x0008
24#define FPU_MASK_UNDERFLOW         0x0010
25#define FPU_MASK_PRECISION         0x0020
2620
27// FPU status word flags
28#define FPU_BUSY               0x8000
29#define FPU_C3                  0x4000
30#define FPU_STACK_TOP_MASK         0x3800
31#define FPU_C2                  0x0400
32#define FPU_C1                  0x0200
33#define FPU_C0                  0x0100
34#define FPU_ERROR_SUMMARY         0x0080
35#define FPU_STACK_FAULT            0x0040
36#define FPU_EXCEPTION_PRECISION      0x0020
37#define FPU_EXCEPTION_UNDERFLOW      0x0010
38#define FPU_EXCEPTION_OVERFLOW      0x0008
39#define FPU_EXCEPTION_ZERO_DIVIDE   0x0004
40#define FPU_EXCEPTION_DENORMAL_OP   0x0002
41#define FPU_EXCEPTION_INVALID_OP   0x0001
21/*************************************
22 *
23 * Defines
24 *
25 *************************************/
4226
27#define X87_SW_IE            0x0001
28#define X87_SW_DE            0x0002
29#define X87_SW_ZE            0x0004
30#define X87_SW_OE            0x0008
31#define X87_SW_UE            0x0010
32#define X87_SW_PE            0x0020
33#define X87_SW_SF            0x0040
34#define X87_SW_ES            0x0080
35#define X87_SW_C0            0x0100
36#define X87_SW_C1            0x0200
37#define X87_SW_C2            0x0400
38#define X87_SW_TOP_SHIFT      11
39#define X87_SW_TOP_MASK         7
40#define X87_SW_C3            0x4000
41#define X87_SW_BUSY            0x8000
4342
44/* return the 32 bit representation of value seen as a single precision floating point number */
45INLINE UINT32 FPU_SINGLE_INT32(X87_REG value)
43#define X87_CW_IM            0x0001
44#define X87_CW_DM            0x0002
45#define X87_CW_ZM            0x0004
46#define X87_CW_OM            0x0008
47#define X87_CW_UM            0x0010
48#define X87_CW_PM            0x0020
49#define X87_CW_PC_SHIFT         8
50#define X87_CW_PC_MASK         3
51#define X87_CW_PC_SINGLE      0
52#define X87_CW_PC_DOUBLE      2
53#define X87_CW_PC_EXTEND      3
54#define X87_CW_RC_SHIFT         10
55#define X87_CW_RC_MASK         3
56#define X87_CW_RC_NEAREST      0
57#define X87_CW_RC_DOWN         1
58#define X87_CW_RC_UP         2
59#define X87_CW_RC_ZERO         3
60
61#define X87_TW_MASK            3
62#define X87_TW_VALID         0
63#define X87_TW_ZERO            1
64#define X87_TW_SPECIAL         2
65#define X87_TW_EMPTY         3
66
67
68/*************************************
69 *
70 * Macros
71 *
72 *************************************/
73
74#define ST_TO_PHYS(x)         (((cpustate->x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK)
75#define ST(x)               (cpustate->x87_reg[ST_TO_PHYS(x)])
76#define X87_TW_FIELD_SHIFT(x)   ((x) << 1)
77#define X87_TAG(x)            ((cpustate->x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK)
78#define X87_RC               ((cpustate->x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK)
79#define X87_IS_ST_EMPTY(x)      (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY)
80#define X87_SW_C3_0            X87_SW_C0
81
82#define UNIMPLEMENTED         fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, cpustate->pc)
83
84
85/*************************************
86 *
87 * Constants
88 *
89 *************************************/
90
91static const floatx80 fx80_zero =   { 0x0000, U64(0x0000000000000000) };
92static const floatx80 fx80_one =   { 0x3fff, U64(0x8000000000000000) };
93
94static const floatx80 fx80_ninf   =   { 0xffff, U64(0x8000000000000000) };
95static const floatx80 fx80_inan   =   { 0xffff, U64(0xc000000000000000) };
96
97/* Maps x87 round modes to SoftFloat round modes */
98static const int x87_to_sf_rc[4] =
4699{
47   float fs=(float)value.f;
48   UINT32 v;
100    float_round_nearest_even,
101    float_round_down,
102    float_round_up,
103    float_round_to_zero,
104};
49105
50   v=*((UINT32 *)(&fs));
51   return v;
106
107/*************************************
108 *
109 * SoftFloat helpers
110 *
111 *************************************/
112
113extern flag floatx80_is_nan( floatx80 a );
114
115INLINE int floatx80_is_zero(floatx80 fx)
116{
117   return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0));
52118}
53119
54INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value)
120INLINE int floatx80_is_inf(floatx80 fx)
55121{
56   cpustate->fpu_top--;
57   if (cpustate->fpu_top < 0)
122   return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0));
123}
124
125INLINE int floatx80_is_denormal(floatx80 fx)
126{
127   return (((fx.high & 0x7fff) == 0) &&
128         ((fx.low & U64(0x8000000000000000)) == 0) &&
129         ((fx.low << 1) != 0));
130}
131
132INLINE floatx80 floatx80_abs(floatx80 fx)
133{
134   fx.high &= 0x7fff;
135   return fx;
136}
137
138INLINE double fx80_to_double(floatx80 fx)
139{
140   UINT64 d = floatx80_to_float64(fx);
141   return *(double*)&d;
142}
143
144INLINE floatx80 double_to_fx80(double in)
145{
146   return float64_to_floatx80(*(UINT64*)&in);
147}
148
149INLINE floatx80 READ80(i386_state *cpustate, UINT32 ea)
150{
151   floatx80 t;
152
153   t.low = READ64(cpustate, ea);
154   t.high = READ16(cpustate, ea + 8);
155
156   return t;
157}
158
159INLINE void WRITE80(i386_state *cpustate, UINT32 ea, floatx80 t)
160{
161   WRITE64(cpustate, ea, t.low);
162   WRITE16(cpustate, ea + 8, t.high);
163}
164
165
166/*************************************
167 *
168 * x87 stack handling
169 *
170 *************************************/
171
172INLINE void x87_set_stack_top(i386_state *cpustate, int top)
173{
174   cpustate->x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT);
175   cpustate->x87_sw |= (top << X87_SW_TOP_SHIFT);
176}
177
178INLINE void x87_set_tag(i386_state *cpustate, int reg, int tag)
179{
180   int shift = X87_TW_FIELD_SHIFT(reg);
181
182   cpustate->x87_tw &= ~(X87_TW_MASK << shift);
183   cpustate->x87_tw |= (tag << shift);
184}
185
186void x87_write_stack(i386_state *cpustate, int i, floatx80 value, int update_tag)
187{
188   ST(i) = value;
189
190   if (update_tag)
58191   {
59      cpustate->fpu_top = 7;
192      int tag;
193
194      if (floatx80_is_zero(value))
195      {
196         tag = X87_TW_ZERO;
197      }
198      else if (floatx80_is_inf(value) || floatx80_is_nan(value))
199      {
200         tag = X87_TW_SPECIAL;
201      }
202      else
203      {
204         tag = X87_TW_VALID;
205      }
206
207      x87_set_tag(cpustate, ST_TO_PHYS(i), tag);
60208   }
209}
61210
62   cpustate->fpu_reg[cpustate->fpu_top] = value;
211INLINE void x87_set_stack_underflow(i386_state *cpustate)
212{
213   cpustate->x87_sw |= X87_SW_C1 | X87_SW_IE | X87_SW_SF;
63214}
64215
65INLINE X87_REG FPU_POP(i386_state *cpustate)
216INLINE void x87_set_stack_overflow(i386_state *cpustate)
66217{
67   X87_REG value = cpustate->fpu_reg[cpustate->fpu_top];
218   cpustate->x87_sw &= ~X87_SW_C1;
219   cpustate->x87_sw |= X87_SW_IE | X87_SW_SF;
220}
68221
69   cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2);      // set FPU register tag to 3 (empty)
222int x87_inc_stack(i386_state *cpustate)
223{
224   int ret = 1;
70225
71   cpustate->fpu_top++;
72   if (cpustate->fpu_top > 7)
226   // Check for stack underflow
227   if (X87_IS_ST_EMPTY(0))
73228   {
74      cpustate->fpu_top = 0;
229      ret = 0;
230      x87_set_stack_underflow(cpustate);
231
232      // Don't update the stack if the exception is unmasked
233      if (~cpustate->x87_cw & X87_CW_IM)
234         return ret;
75235   }
76236
77   return value;
237   x87_set_tag(cpustate, ST_TO_PHYS(0), X87_TW_EMPTY);
238   x87_set_stack_top(cpustate, ST_TO_PHYS(1));
239   return ret;
78240}
79241
80INLINE INT64 X87_FROUND(i386_state *cpustate, X87_REG t)
242int x87_dec_stack(i386_state *cpustate)
81243{
82   switch((cpustate->fpu_control_word >> 10) & 3)
244   int ret = 1;
245
246   // Check for stack overflow
247   if (!X87_IS_ST_EMPTY(7))
83248   {
84      case 0: return (INT64)(t.f + 0.5); break; /* Nearest */
85      case 1: return (INT64)floor(t.f); break; /* Down */
86      case 2: return (INT64)ceil(t.f); break; /* Up */
87      case 3: return (INT64)t.f; break; /* Chop */
249      ret = 0;
250      x87_set_stack_overflow(cpustate);
251
252      // Don't update the stack if the exception is unmasked
253      if (~cpustate->x87_cw & X87_CW_IM)
254         return ret;
88255   }
89   return 0;
256
257   x87_set_stack_top(cpustate, ST_TO_PHYS(7));
258   return ret;
90259}
91260
92INLINE X87_REG READ80(i386_state *cpustate,UINT32 ea)
261
262/*************************************
263 *
264 * Exception handling
265 *
266 *************************************/
267
268int x87_check_exceptions(i386_state *cpustate)
93269{
94   X87_REG t;
95   floatx80 f;
270   /* Update the exceptions from SoftFloat */
271   if (float_exception_flags & float_flag_invalid)
272   {
273      cpustate->x87_sw |= X87_SW_IE;
274      float_exception_flags &= ~float_flag_invalid;
275   }
276   if (float_exception_flags & float_flag_overflow)
277   {
278      cpustate->x87_sw |= X87_SW_OE;
279      float_exception_flags &= ~float_flag_overflow;
280   }
281   if (float_exception_flags & float_flag_underflow)
282   {
283      cpustate->x87_sw |= X87_SW_UE;
284      float_exception_flags &= ~float_flag_underflow;
285   }
286   if (float_exception_flags & float_flag_inexact)
287   {
288      cpustate->x87_sw |= X87_SW_PE;
289      float_exception_flags &= ~float_flag_inexact;
290   }
96291
97   f.high = READ16(cpustate,ea+8);
98   f.low = READ64(cpustate,ea);
99/*   UINT16 begin;
100   INT64 exp;
101   INT64 mantissa;
102   UINT8 sign;
292   if ((cpustate->x87_sw & ~cpustate->x87_cw) & 0x3f)
293   {
294      // TODO
295      fatalerror("Unimplemented: unmasked x87 exception (CW:%.4x, SW:%.4x)", cpustate->x87_cw, cpustate->x87_sw);
296      return 0;
297   }
103298
104   t.i = READ64(cpustate,ea);
105   begin = READ16(cpustate,ea+8);
106   sign = (begin&0x8000) >> 15;
299   return 1;
300}
107301
108   if((t.i == FPU_SIGN_BIT_DOUBLE) && ((begin & 0x7fff) == 0x7fff))
302INLINE void x87_write_cw(i386_state *cpustate, UINT16 cw)
303{
304   cpustate->x87_cw = cw;
305
306   /* Update the SoftFloat rounding mode */
307   float_rounding_mode = x87_to_sf_rc[(cpustate->x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK];
308}
309
310void x87_reset(i386_state *cpustate)
311{
312   x87_write_cw(cpustate, 0x0037f);
313
314   cpustate->x87_sw = 0;
315   cpustate->x87_tw = 0xffff;
316
317   // TODO: FEA=0, FDS=0, FIP=0 FOP=0 FCS=0
318   cpustate->x87_data_ptr = 0;
319   cpustate->x87_inst_ptr = 0;
320   cpustate->x87_opcode = 0;
321}
322
323
324/*************************************
325 *
326 * Core arithmetic
327 *
328 *************************************/
329
330static floatx80 x87_add(i386_state *cpustate, floatx80 a, floatx80 b)
331{
332   floatx80 result = { 0 };
333
334   switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK)
109335   {
110      t.f = HUGE_VAL * (sign?(-1.0):(1.0));
111      return t;
336      case X87_CW_PC_SINGLE:
337      {
338         float32 a32 = floatx80_to_float32(a);
339         float32 b32 = floatx80_to_float32(b);
340         result = float32_to_floatx80(float32_add(a32, b32));
341         break;
342      }
343      case X87_CW_PC_DOUBLE:
344      {
345         float64 a64 = floatx80_to_float64(a);
346         float64 b64 = floatx80_to_float64(b);
347         result = float64_to_floatx80(float64_add(a64, b64));
348         break;
349      }
350      case X87_CW_PC_EXTEND:
351      {
352         result = floatx80_add(a, b);
353         break;
354      }
112355   }
113   
114   exp = (begin&0x7fff) - 16383;
115   exp = (exp > 0) ? (exp&0x3ff) : (-1)*(-exp&0x3ff);
116   exp += 1023;
117356
118   mantissa = (t.i >> 11) & (FPU_MANTISSA_DOUBLE);
357   return result;
358}
119359
120   if(t.i & 0x400)
121      mantissa++;
360static floatx80 x87_sub(i386_state *cpustate, floatx80 a, floatx80 b)
361{
362   floatx80 result = { 0 };
122363
123   t.i = ((UINT64)sign << 63)|((UINT64)exp << 52)|((UINT64)mantissa);*/
124   t.f = floatx80_to_float64(f);
364   switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK)
365   {
366      case X87_CW_PC_SINGLE:
367      {
368         float32 a32 = floatx80_to_float32(a);
369         float32 b32 = floatx80_to_float32(b);
370         result = float32_to_floatx80(float32_sub(a32, b32));
371         break;
372      }
373      case X87_CW_PC_DOUBLE:
374      {
375         float64 a64 = floatx80_to_float64(a);
376         float64 b64 = floatx80_to_float64(b);
377         result = float64_to_floatx80(float32_sub(a64, b64));
378         break;
379      }
380      case X87_CW_PC_EXTEND:
381      {
382         result = floatx80_sub(a, b);
383         break;
384      }
385   }
125386
126   return t;
387   return result;
127388}
128389
129INLINE void WRITE80(i386_state *cpustate,UINT32 ea, X87_REG t)
390static floatx80 x87_mul(i386_state *cpustate, floatx80 a, floatx80 b)
130391{
131   floatx80 f;
132/*   UINT16 sign = (t.i & FPU_SIGN_BIT_DOUBLE) ? 1 : 0;
133   INT64 exp = (t.i & FPU_INFINITY_DOUBLE) >> 52;
134   INT64 mantissa = (t.i & FPU_MANTISSA_DOUBLE) << 11;
135   INT16 begin;
392   floatx80 val = { 0 };
136393
137   if(t.f != 0)
394   switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK)
138395   {
139      mantissa |= FPU_SIGN_BIT_DOUBLE;
140      exp += (16383 - 1023);
396      case X87_CW_PC_SINGLE:
397      {
398         float32 a32 = floatx80_to_float32(a);
399         float32 b32 = floatx80_to_float32(b);
400         val = float32_to_floatx80(float32_mul(a32, b32));
401         break;
402      }
403      case X87_CW_PC_DOUBLE:
404      {
405         float64 a64 = floatx80_to_float64(a);
406         float64 b64 = floatx80_to_float64(b);
407         val = float64_to_floatx80(float64_mul(a64, b64));
408         break;
409      }
410      case X87_CW_PC_EXTEND:
411      {
412         val = floatx80_mul(a, b);
413         break;
414      }
141415   }
142416
143   begin = (sign<<15)|(INT16)(exp);
144   t.i = mantissa;*/
417   return val;
418}
145419
146   f = float64_to_floatx80(t.f);
147   WRITE64(cpustate,ea,f.low);
148   WRITE16(cpustate,ea+8,f.high);
420
421static floatx80 x87_div(i386_state *cpustate, floatx80 a, floatx80 b)
422{
423   floatx80 val = { 0 };
424
425   switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK)
426   {
427      case X87_CW_PC_SINGLE:
428      {
429         float32 a32 = floatx80_to_float32(a);
430         float32 b32 = floatx80_to_float32(b);
431         val = float32_to_floatx80(float32_div(a32, b32));
432         break;
433      }
434      case X87_CW_PC_DOUBLE:
435      {
436         float64 a64 = floatx80_to_float64(a);
437         float64 b64 = floatx80_to_float64(b);
438         val = float64_to_floatx80(float64_div(a64, b64));
439         break;
440      }
441      case X87_CW_PC_EXTEND:
442      {
443         val = floatx80_div(a, b);
444         break;
445      }
446   }
447   return val;
149448}
150449
151static void I386OP(fpu_group_d8)(i386_state *cpustate)      // Opcode 0xd8
450
451/*************************************
452 *
453 * Instructions
454 *
455 *************************************/
456
457/*************************************
458 *
459 * Add
460 *
461 *************************************/
462
463void x87_fadd_m32real(i386_state *cpustate, UINT8 modrm)
152464{
153   UINT8 modrm = FETCH(cpustate);
154   if (modrm < 0xc0)
465   floatx80 result;
466
467   if (X87_IS_ST_EMPTY(0))
155468   {
156      UINT32 ea = GetEA(cpustate,modrm);
157      UINT32 tmp32 = READ32(cpustate,ea);
158      float  src;
469      x87_set_stack_underflow(cpustate);
470      result = fx80_inan;
471   }
472   else
473   {
474      UINT32 ea = GetEA(cpustate, modrm);
475      UINT32 m32real = READ32(cpustate, ea);
159476
160      src = *((float *) &tmp32); /* must bypass type conversion */
477      floatx80 a = ST(0);
478      floatx80 b = float32_to_floatx80(m32real);
161479
162      switch ((modrm >> 3) & 0x7)
480      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
481      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
163482      {
164         case 0:    // FADD short
165         {
166            ST(0).f += src;
167            CYCLES(cpustate,8);
168            break;
169         }
483         cpustate->x87_sw |= X87_SW_IE;
484         result = fx80_inan;
485      }
486      else
487      {
488         result = x87_add(cpustate, a, b);
489      }
490   }
170491
171         case 1:    // FMUL short
172         {
173            ST(0).f *= src;
174            CYCLES(cpustate,8);
175            break;
176         }
492   if (x87_check_exceptions(cpustate))
493      x87_write_stack(cpustate, 0, result, TRUE);
177494
178         case 2:    // FCOM short
179         {
180            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
181            if(ST(0).f == src)
182               cpustate->fpu_status_word |= FPU_C3;
183            if(ST(0).f < src)
184               cpustate->fpu_status_word |= FPU_C0;
185            CYCLES(cpustate,4);
186            break;
187         }
495   CYCLES(cpustate, 8);
496}
188497
189         case 3:    // FCOMP short
190         {
191            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
192            if(ST(0).f == src)
193               cpustate->fpu_status_word |= FPU_C3;
194            if(ST(0).f < src)
195               cpustate->fpu_status_word |= FPU_C0;
196            FPU_POP(cpustate);
197            CYCLES(cpustate,4);
198            break;
199         }
498void x87_fadd_m64real(i386_state *cpustate, UINT8 modrm)
499{
500   floatx80 result;
200501
201         case 4:    // FSUB short
202         {
203            ST(0).f -= src;
204            CYCLES(cpustate,8);
205            break;
206         }
502   if (X87_IS_ST_EMPTY(0))
503   {
504      x87_set_stack_underflow(cpustate);
505      result = fx80_inan;
506   }
507   else
508   {
509      UINT32 ea = GetEA(cpustate, modrm);
510      UINT64 m64real = READ64(cpustate, ea);
207511
208         case 5:    // FSUBR short
209         {
210            ST(0).f = src - ST(0).f;
211            CYCLES(cpustate,8);
212            break;
213         }
512      floatx80 a = ST(0);
513      floatx80 b = float64_to_floatx80(m64real);
214514
215         case 6:  // FDIV
216         {
217            if(src == 0)
218            {
219               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
220                  ST(0).i |= FPU_INFINITY_DOUBLE;
221               else
222                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
223            }
224            else
225               ST(0).f = ST(0).f / src;
226            CYCLES(cpustate,73);
227            break;
228         }
515      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
516      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
517      {
518         cpustate->x87_sw |= X87_SW_IE;
519         result = fx80_inan;
520      }
521      else
522      {
523         result = x87_add(cpustate, a, b);
524      }
525   }
229526
230         case 7:  // FDIVR
231         {
232            if(src == 0)
233            {
234               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
235                  ST(0).i |= FPU_INFINITY_DOUBLE;
236               else
237                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
238            }
239            else
240               ST(0).f = src / ST(0).f;
241            CYCLES(cpustate,73);
242            break;
243         }
527   if (x87_check_exceptions(cpustate))
528      x87_write_stack(cpustate, 0, result, TRUE);
529
530   CYCLES(cpustate, 8);
531}
532
533void x87_fadd_st_sti(i386_state *cpustate, UINT8 modrm)
534{
535   floatx80 result;
536   int i = modrm & 7;
537
538   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
539   {
540      x87_set_stack_underflow(cpustate);
541      result = fx80_inan;
542   }
543   else
544   {
545      floatx80 a = ST(0);
546      floatx80 b = ST(i);
547
548      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
549      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
550      {
551         cpustate->x87_sw |= X87_SW_IE;
552         result = fx80_inan;
244553      }
554      else
555      {
556         result = x87_add(cpustate, a, b);
557      }
245558   }
559
560   if (x87_check_exceptions(cpustate))
561      x87_write_stack(cpustate, 0, result, TRUE);
562
563   CYCLES(cpustate, 8);
564}
565
566void x87_fadd_sti_st(i386_state *cpustate, UINT8 modrm)
567{
568   floatx80 result;
569   int i = modrm & 7;
570
571   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
572   {
573      x87_set_stack_underflow(cpustate);
574      result = fx80_inan;
575   }
246576   else
247577   {
248      switch (modrm & 0x3f)
578      floatx80 a = ST(0);
579      floatx80 b = ST(i);
580
581      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
582      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
249583      {
250         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // FADD
251         {
252            ST(0).f+=ST(modrm & 7).f;
253            CYCLES(cpustate,8);
254            break;
255         }
256         case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // FMUL
257         {
258            ST(0).f*=ST(modrm & 7).f;
259            CYCLES(cpustate,16);
260            break;
261         }
262         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: // FCOM
263         {
264            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
265            if(ST(0).f == ST(modrm & 7).f)
266               cpustate->fpu_status_word |= FPU_C3;
267            if(ST(0).f < ST(modrm & 7).f)
268               cpustate->fpu_status_word |= FPU_C0;
269            CYCLES(cpustate,4);
270            break;
271         }
584         cpustate->x87_sw |= X87_SW_IE;
585         result = fx80_inan;
586      }
587      else
588      {
589         result = x87_add(cpustate, a, b);
590      }
591   }
272592
273         case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // FCOMP
274         {
275            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
276            if(ST(0).f == ST(modrm & 7).f)
277               cpustate->fpu_status_word |= FPU_C3;
278            if(ST(0).f < ST(modrm & 7).f)
279               cpustate->fpu_status_word |= FPU_C0;
280            FPU_POP(cpustate);
281            CYCLES(cpustate,4);
282            break;
283         }
593   if (x87_check_exceptions(cpustate))
594      x87_write_stack(cpustate, i, result, TRUE);
284595
285         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // FSUB
286         {
287            ST(0).f-=ST(modrm & 7).f;
288            CYCLES(cpustate,8);
289            break;
290         }
596   CYCLES(cpustate, 8);
597}
291598
292         case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // FSUBR
293         {
294            ST(0).f = ST(modrm & 7).f - ST(0).f;
295            CYCLES(cpustate,8);
296            break;
297         }
599void x87_faddp(i386_state *cpustate, UINT8 modrm)
600{
601   floatx80 result;
602   int i = modrm & 7;
298603
299         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: // FDIV
300         {
301            if(ST(modrm & 7).f != 0.0)
302               ST(0).f/=ST(modrm & 7).f;
303            else
304            {
305               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
306                  ST(0).i |= FPU_INFINITY_DOUBLE;
307               else
308                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
309            }
310            CYCLES(cpustate,73);
311            break;
312         }
604   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
605   {
606      x87_set_stack_underflow(cpustate);
607      result = fx80_inan;
608   }
609   else
610   {
611      floatx80 a = ST(0);
612      floatx80 b = ST(i);
313613
314         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: // FDIVR
315         {
316            if(ST(0).f != 0.0)
317               ST(0).f = ST(modrm & 7).f / ST(0).f;
318            else
319            {
320               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
321                  ST(0).i |= FPU_INFINITY_DOUBLE;
322               else
323                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
324            }
325            CYCLES(cpustate,73);
326            break;
327         }
614      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
615      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
616      {
617         cpustate->x87_sw |= X87_SW_IE;
618         result = fx80_inan;
619      }
620      else
621      {
622         result = x87_add(cpustate, a, b);
623      }
624   }
328625
329         default:
330            fatalerror("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2);
626   if (x87_check_exceptions(cpustate))
627   {
628      x87_write_stack(cpustate, i, result, TRUE);
629      x87_inc_stack(cpustate);
630   }
631
632   CYCLES(cpustate, 8);
633}
634
635void x87_fiadd_m32int(i386_state *cpustate, UINT8 modrm)
636{
637   floatx80 result;
638
639   if (X87_IS_ST_EMPTY(0))
640   {
641      x87_set_stack_underflow(cpustate);
642      result = fx80_inan;
643   }
644   else
645   {
646      UINT32 ea = GetEA(cpustate, modrm);
647      INT32 m32int = READ32(cpustate, ea);
648
649      floatx80 a = ST(0);
650      floatx80 b = int32_to_floatx80(m32int);
651
652      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
653      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
654      {
655         cpustate->x87_sw |= X87_SW_IE;
656         result = fx80_inan;
331657      }
658      else
659      {
660         result = x87_add(cpustate, a, b);
661      }
662   }
332663
664   if (x87_check_exceptions(cpustate))
665      x87_write_stack(cpustate, 0, result, TRUE);
666
667   CYCLES(cpustate, 19);
668}
669
670void x87_fiadd_m16int(i386_state *cpustate, UINT8 modrm)
671{
672   floatx80 result;
673
674   if (X87_IS_ST_EMPTY(0))
675   {
676      x87_set_stack_underflow(cpustate);
677      result = fx80_inan;
333678   }
679   else
680   {
681      UINT32 ea = GetEA(cpustate, modrm);
682      INT16 m16int = READ16(cpustate, ea);
683
684      floatx80 a = ST(0);
685      floatx80 b = int32_to_floatx80(m16int);
686
687      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
688      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
689      {
690         cpustate->x87_sw |= X87_SW_IE;
691         result = fx80_inan;
692      }
693      else
694      {
695         result = x87_add(cpustate, a, b);
696      }
697   }
698
699   if (x87_check_exceptions(cpustate))
700      x87_write_stack(cpustate, 0, result, TRUE);
701
702   CYCLES(cpustate, 20);
334703}
335704
336static void I386OP(fpu_group_d9)(i386_state *cpustate)      // Opcode 0xd9
705
706/*************************************
707 *
708 * Subtract
709 *
710 *************************************/
711
712void x87_fsub_m32real(i386_state *cpustate, UINT8 modrm)
337713{
338   UINT8 modrm = FETCH(cpustate);
714   floatx80 result;
339715
340   if (modrm < 0xc0)
716   if (X87_IS_ST_EMPTY(0))
341717   {
342      UINT32 ea = GetEA(cpustate,modrm);
718      x87_set_stack_underflow(cpustate);
719      result = fx80_inan;
720   }
721   else
722   {
723      UINT32 ea = GetEA(cpustate, modrm);
724      UINT32 m32real = READ32(cpustate, ea);
343725
344      switch ((modrm >> 3) & 0x7)
726      floatx80 a = ST(0);
727      floatx80 b = float32_to_floatx80(m32real);
728
729      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
730      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
345731      {
346         case 0:         // FLD single-precision
347         {
348            UINT32 tmp32;
349            X87_REG t;
350            tmp32 = READ32(cpustate,ea);
351            t.f = *((float *) &tmp32); /* must bypass type conversion */
352            FPU_PUSH(cpustate,t);
353            CYCLES(cpustate,3);
354            break;
355         }
732         cpustate->x87_sw |= X87_SW_IE;
733         result = fx80_inan;
734      }
735      else
736      {
737         result = x87_sub(cpustate, a, b);
738      }
739   }
356740
357         case 2:         // FST single-precision
358         {
359            WRITE32(cpustate,ea,FPU_SINGLE_INT32(ST(0)));
360            CYCLES(cpustate,7);
361            break;
362         }
741   if (x87_check_exceptions(cpustate))
742      x87_write_stack(cpustate, 0, result, TRUE);
363743
364         case 3:         // FSTP
365         {
366            // st(0) -> ea
367            WRITE32(cpustate,ea,FPU_SINGLE_INT32(ST(0)));
368            FPU_POP(cpustate);
369            CYCLES(cpustate,7);
370            break;
371         }
744   CYCLES(cpustate, 8);
745}
372746
373         case 4:         // FLDENV
374         {
375            if( cpustate->operand_size )  // 32-bit real/protected mode
376            {
377               cpustate->fpu_control_word = READ16(cpustate,ea);
378               cpustate->fpu_status_word = READ16(cpustate,ea+4);
379               cpustate->fpu_tag_word = READ16(cpustate,ea+8);
380            }
381            else // 16-bit real/protected mode
382            {
383               cpustate->fpu_control_word = READ16(cpustate,ea);
384               cpustate->fpu_status_word = READ16(cpustate,ea+2);
385               cpustate->fpu_tag_word = READ16(cpustate,ea+4);
386            }
747void x87_fsub_m64real(i386_state *cpustate, UINT8 modrm)
748{
749   floatx80 result;
387750
388            cpustate->fpu_top = (cpustate->fpu_status_word>>11) & 7;
751   if (X87_IS_ST_EMPTY(0))
752   {
753      x87_set_stack_underflow(cpustate);
754      result = fx80_inan;
755   }
756   else
757   {
758      UINT32 ea = GetEA(cpustate, modrm);
759      UINT64 m64real = READ64(cpustate, ea);
389760
390            CYCLES(cpustate,(cpustate->cr[0] & 1) ? 34 : 44);
391            break;
392         }
761      floatx80 a = ST(0);
762      floatx80 b = float64_to_floatx80(m64real);
393763
394         case 5:         // FLDCW
395         {
396            cpustate->fpu_control_word = READ16(cpustate,ea);
397            CYCLES(cpustate,4);
398            break;
399         }
764      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
765      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
766      {
767         cpustate->x87_sw |= X87_SW_IE;
768         result = fx80_inan;
769      }
770      else
771      {
772         result = x87_sub(cpustate, a, b);
773      }
774   }
400775
401         case 6:         // FSTENV
402         {
403            logerror("x87 FSTENV triggered with mode = %d %02x %02x\n",(cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1,cpustate->cr[0],cpustate->operand_size);
404            switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
405            {
406               case 0:   // 16-bit real mode
407                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
408                  WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
409                  WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
410                  WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
411                  //WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
412                  WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
413                  //WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
414                  break;
415               case 1: // 16-bit protected mode
416                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
417                  WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
418                  WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
419                  WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
420                  WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
421                  WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
422                  WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
423                  break;
424               case 2: // 32-bit real mode
425                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
426                  WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
427                  WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
428                  WRITE16(cpustate,ea+12, cpustate->fpu_inst_ptr & 0xffff);
429                  //WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
430                  WRITE16(cpustate,ea+20, cpustate->fpu_data_ptr & 0xffff);
431                  //WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
432                  WRITE32(cpustate,ea+24, (cpustate->fpu_data_ptr>>16)<<12);
433                  break;
434               case 3: // 32-bit protected mode
435                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
436                  WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
437                  WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
438                  WRITE32(cpustate,ea+12, cpustate->fpu_inst_ptr);
439                  WRITE32(cpustate,ea+16, cpustate->fpu_opcode);
440                  WRITE32(cpustate,ea+20, cpustate->fpu_data_ptr);
441                  WRITE32(cpustate,ea+24, cpustate->fpu_inst_ptr);
442                  break;
443            }
776   if (x87_check_exceptions(cpustate))
777      x87_write_stack(cpustate, 0, result, TRUE);
444778
445            CYCLES(cpustate,(cpustate->cr[0] & 1) ? 56 : 67);
446            break;
447         }
779   CYCLES(cpustate, 8);
780}
448781
449         case 7:         // FSTCW
450         {
451            WRITE16(cpustate,ea, cpustate->fpu_control_word);
452            CYCLES(cpustate,3);
453            break;
454         }
782void x87_fsub_st_sti(i386_state *cpustate, UINT8 modrm)
783{
784   floatx80 result;
785   int i = modrm & 7;
455786
456         default:
457            fatalerror("I386: FPU Op D9 %02X at %08X", (modrm >> 3) & 0x7, cpustate->pc-2);
787   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
788   {
789      x87_set_stack_underflow(cpustate);
790      result = fx80_inan;
791   }
792   else
793   {
794      floatx80 a = ST(0);
795      floatx80 b = ST(i);
796
797      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
798      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
799      {
800         cpustate->x87_sw |= X87_SW_IE;
801         result = fx80_inan;
458802      }
803      else
804      {
805         result = x87_sub(cpustate, a, b);
806      }
459807   }
808
809   if (x87_check_exceptions(cpustate))
810      x87_write_stack(cpustate, 0, result, TRUE);
811
812   CYCLES(cpustate, 8);
813}
814
815void x87_fsub_sti_st(i386_state *cpustate, UINT8 modrm)
816{
817   floatx80 result;
818   int i = modrm & 7;
819
820   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
821   {
822      x87_set_stack_underflow(cpustate);
823      result = fx80_inan;
824   }
460825   else
461826   {
462      switch (modrm & 0x3f)
827      floatx80 a = ST(i);
828      floatx80 b = ST(0);
829
830      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
831      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
463832      {
464         // FLD
465         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
466         {
467            X87_REG t = ST(modrm & 7);
468            FPU_PUSH(cpustate,t);
469            CYCLES(cpustate,4);
470            break;
471         }
833         cpustate->x87_sw |= X87_SW_IE;
834         result = fx80_inan;
835      }
836      else
837      {
838         result = x87_sub(cpustate, a, b);
839      }
840   }
472841
473         // FXCH
474         case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
475         {
476            X87_REG t = ST(0);
477            ST(0) = ST(modrm & 7);
478            ST(modrm & 7) = t;
479            CYCLES(cpustate,4);
480            break;
481         }
842   if (x87_check_exceptions(cpustate))
843      x87_write_stack(cpustate, i, result, TRUE);
482844
483         case 0x10:      // FNOP
484         {
485            CYCLES(cpustate,3);
486            break;
487         }
845   CYCLES(cpustate, 8);
846}
488847
489         case 0x20:      // FCHS
490         {
491            ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
492            CYCLES(cpustate,6);
493            break;
494         }
848void x87_fsubp(i386_state *cpustate, UINT8 modrm)
849{
850   floatx80 result;
851   int i = modrm & 7;
495852
496         case 0x21:      // FABS
497         {
498            ST(0).f = fabs(ST(0).f);
499            CYCLES(cpustate,3);
500            break;
501         }
853   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
854   {
855      x87_set_stack_underflow(cpustate);
856      result = fx80_inan;
857   }
858   else
859   {
860      floatx80 a = ST(i);
861      floatx80 b = ST(0);
502862
863      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
864      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
865      {
866         cpustate->x87_sw |= X87_SW_IE;
867         result = fx80_inan;
868      }
869      else
870      {
871         result = x87_sub(cpustate, a, b);
872      }
873   }
503874
504         case 0x24:      // FTST
505         {
506            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
507            if(ST(0).f == 0.0)
508               cpustate->fpu_status_word |= FPU_C3;
509            if(ST(0).f < 0.0)
510               cpustate->fpu_status_word |= FPU_C0;
511            CYCLES(cpustate,4);
512            break;
513         }
875   if (x87_check_exceptions(cpustate))
876   {
877      x87_write_stack(cpustate, i, result, TRUE);
878      x87_inc_stack(cpustate);
879   }
514880
515         case 0x25:      // FXAM
516         {
517            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
518            if(!(cpustate->fpu_tag_word&(1<<cpustate->fpu_top)))
519            {
520               cpustate->fpu_status_word |= FPU_C3 | FPU_C0;
521               return;
522            }
523            else if(ST(0).f == 0.0)
524               cpustate->fpu_status_word |= FPU_C3;
525            else
526               cpustate->fpu_status_word |= FPU_C2;
527            if(ST(0).f < 0.0)
528               cpustate->fpu_status_word |= FPU_C1;
529            CYCLES(cpustate,8);
530            break;
531         }
881   CYCLES(cpustate, 8);
882}
532883
533         case 0x28:      // FLD1
534         {
535            X87_REG t;
536            t.f = 1.0;
537            FPU_PUSH(cpustate,t);
538            CYCLES(cpustate,4);
539            break;
540         }
884void x87_fisub_m32int(i386_state *cpustate, UINT8 modrm)
885{
886   floatx80 result;
541887
542         case 0x29:      // FLDL2T
543         {
544            X87_REG t;
545            t.f = 3.3219280948873623;
546            FPU_PUSH(cpustate,t);
547            CYCLES(cpustate,8);
548            break;
549         }
888   if (X87_IS_ST_EMPTY(0))
889   {
890      x87_set_stack_underflow(cpustate);
891      result = fx80_inan;
892   }
893   else
894   {
895      UINT32 ea = GetEA(cpustate, modrm);
896      INT32 m32int = READ32(cpustate, ea);
550897
551         case 0x2a:      // FLDL2E
552         {
553            X87_REG t;
554            t.f = 1.4426950408889634;
555            FPU_PUSH(cpustate,t);
556            CYCLES(cpustate,8);
557            break;
558         }
898      floatx80 a = ST(0);
899      floatx80 b = int32_to_floatx80(m32int);
559900
560         case 0x2b:      // FLDPI
561         {
562            X87_REG t;
563            t.f = 3.141592653589793;
564            FPU_PUSH(cpustate,t);
565            CYCLES(cpustate,8);
566            break;
567         }
901      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
902      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
903      {
904         cpustate->x87_sw |= X87_SW_IE;
905         result = fx80_inan;
906      }
907      else
908      {
909         result = x87_sub(cpustate, a, b);
910      }
911   }
568912
569         case 0x2c:      // FLDEG2
570         {
571            X87_REG t;
572            t.f = 0.3010299956639812;
573            FPU_PUSH(cpustate,t);
574            CYCLES(cpustate,8);
575            break;
576         }
913   if (x87_check_exceptions(cpustate))
914      x87_write_stack(cpustate, 0, result, TRUE);
577915
578         case 0x2d:      // FLDLN2
579         {
580            X87_REG t;
581            t.f = 0.693147180559945;
582            FPU_PUSH(cpustate,t);
583            CYCLES(cpustate,8);
584            break;
585         }
916   CYCLES(cpustate, 19);
917}
586918
587         case 0x2e:      // FLDZ
588         {
589            X87_REG t;
590            t.f = 0.0;
591            FPU_PUSH(cpustate,t);
592            /* TODO: tag moves? */
593            CYCLES(cpustate,4);
594            break;
595         }
919void x87_fisub_m16int(i386_state *cpustate, UINT8 modrm)
920{
921   floatx80 result;
596922
597         case 0x30:      // F2XM1
598         {
599            ST(0).f = pow(2.0,ST(0).f)-1.0;
600            CYCLES(cpustate,200);
601            break;
602         }
923   if (X87_IS_ST_EMPTY(0))
924   {
925      x87_set_stack_underflow(cpustate);
926      result = fx80_inan;
927   }
928   else
929   {
930      UINT32 ea = GetEA(cpustate, modrm);
931      INT16 m16int = READ16(cpustate, ea);
603932
604         case 0x31:      // FYL2X
605         {
606            ST(1).f *= (log(ST(0).f)/log(2.0));
607            FPU_POP(cpustate);
608            CYCLES(cpustate,250);
609            break;
610         }
933      floatx80 a = ST(0);
934      floatx80 b = int32_to_floatx80(m16int);
611935
612         case 0x32:      // FPTAN
613         {
614            X87_REG t;
615            t.f = 1.0;
616            ST(0).f = tan(ST(0).f);
617            FPU_PUSH(cpustate,t);
618            cpustate->fpu_status_word &= ~(FPU_C2);
619            /* TODO: source operand out-of-range */
620            CYCLES(cpustate,235);
621            break;
622         }
936      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
937      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
938      {
939         cpustate->x87_sw |= X87_SW_IE;
940         result = fx80_inan;
941      }
942      else
943      {
944         result = x87_sub(cpustate, a, b);
945      }
946   }
623947
624         case 0x33:      // FPATAN
625         {
626            ST(1).f = atan2(ST(1).f,ST(0).f);
627            FPU_POP(cpustate);
628            CYCLES(cpustate,250);
629            break;
630         }
948   if (x87_check_exceptions(cpustate))
949      x87_write_stack(cpustate, 0, result, TRUE);
631950
632         case 0x36:      // FPDECSTP
633         {
634            cpustate->fpu_top -= 1;
635            cpustate->fpu_top &= 7;
636            CYCLES(cpustate,1); // TODO
637            break;
638         }
951   CYCLES(cpustate, 20);
952}
639953
640         case 0x37:      // FPINCSTP
641         {
642            cpustate->fpu_top += 1;
643            cpustate->fpu_top &= 7;
644            CYCLES(cpustate,1); // TODO
645            break;
646         }
647954
648         case 0x38:      // FPREM
649         {
650            INT64 t;
955/*************************************
956 *
957 * Reverse Subtract
958 *
959 *************************************/
651960
652            if(ST(1).f == 0.0)
653            {
654               logerror("FPREM divide by zero");
655               break;
656            }
657            else
658               t = ST(0).f / ST(1).f;
659            ST(0).f = ST(0).f-(ST(1).i*t);
660            cpustate->fpu_status_word &= ~(FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3);
961void x87_fsubr_m32real(i386_state *cpustate, UINT8 modrm)
962{
963   floatx80 result;
661964
662            if(t & 4)
663               cpustate->fpu_status_word |= FPU_C0;
965   if (X87_IS_ST_EMPTY(0))
966   {
967      x87_set_stack_underflow(cpustate);
968      result = fx80_inan;
969   }
970   else
971   {
972      UINT32 ea = GetEA(cpustate, modrm);
973      UINT32 m32real = READ32(cpustate, ea);
664974
665            if(t & 2)
666               cpustate->fpu_status_word |= FPU_C3;
975      floatx80 a = float32_to_floatx80(m32real);
976      floatx80 b = ST(0);
667977
668            if(t & 1)
669               cpustate->fpu_status_word |= FPU_C1;
978      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
979      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
980      {
981         cpustate->x87_sw |= X87_SW_IE;
982         result = fx80_inan;
983      }
984      else
985      {
986         result = x87_sub(cpustate, a, b);
987      }
988   }
670989
671            CYCLES(cpustate,100);
672            break;
673         }
990   if (x87_check_exceptions(cpustate))
991      x87_write_stack(cpustate, 0, result, TRUE);
674992
675         case 0x3a:      // FSQRT
676         {
677            ST(0).f = sqrt(ST(0).f);
678            CYCLES(cpustate,83);
679            break;
680         }
993   CYCLES(cpustate, 8);
994}
681995
682         case 0x3b:      // FSINCOS
683         {
684            X87_REG t;
685            t.f = cos(ST(0).f);
686            ST(0).f = sin(ST(0).f);
687            FPU_PUSH(cpustate,t);
688            cpustate->fpu_status_word &= ~(FPU_C2);
689            /* TODO: source operand out-of-range */
690            CYCLES(cpustate,330);
691            break;
692         }
996void x87_fsubr_m64real(i386_state *cpustate, UINT8 modrm)
997{
998   floatx80 result;
693999
694         case 0x3c:      // FRNDINT
695         {
696            ST(0).f = (double)X87_FROUND(cpustate,ST(0));
697            CYCLES(cpustate,21);
698            break;
699         }
1000   if (X87_IS_ST_EMPTY(0))
1001   {
1002      x87_set_stack_underflow(cpustate);
1003      result = fx80_inan;
1004   }
1005   else
1006   {
1007      UINT32 ea = GetEA(cpustate, modrm);
1008      UINT64 m64real = READ64(cpustate, ea);
7001009
701         case 0x3d:      // FSCALE
702         {
703            ST(0).f *= pow(2.0,(INT64)(ST(1).f));
704            CYCLES(cpustate,30);
705            break;
706         }
1010      floatx80 a = float64_to_floatx80(m64real);
1011      floatx80 b = ST(0);
7071012
708         case 0x3e:      // FSIN
709         {
710            ST(0).f = sin(ST(0).f);
711            cpustate->fpu_status_word &= ~(FPU_C2);
712            /* TODO: source operand out-of-range */
713            CYCLES(cpustate,300);
714            break;
715         }
1013      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1014      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
1015      {
1016         cpustate->x87_sw |= X87_SW_IE;
1017         result = fx80_inan;
1018      }
1019      else
1020      {
1021         result = x87_sub(cpustate, a, b);
1022      }
1023   }
7161024
717         case 0x3f:      // FCOS
718         {
719            ST(0).f = cos(ST(0).f);
720            cpustate->fpu_status_word &= ~(FPU_C2);
721            /* TODO: source operand out-of-range */
722            CYCLES(cpustate,300);
723            break;
724         }
1025   if (x87_check_exceptions(cpustate))
1026      x87_write_stack(cpustate, 0, result, TRUE);
7251027
726         default:
727            fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
1028   CYCLES(cpustate, 8);
1029}
1030
1031void x87_fsubr_st_sti(i386_state *cpustate, UINT8 modrm)
1032{
1033   floatx80 result;
1034   int i = modrm & 7;
1035
1036   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1037   {
1038      x87_set_stack_underflow(cpustate);
1039      result = fx80_inan;
1040   }
1041   else
1042   {
1043      floatx80 a = ST(i);
1044      floatx80 b = ST(0);
1045
1046      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1047      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
1048      {
1049         cpustate->x87_sw |= X87_SW_IE;
1050         result = fx80_inan;
7281051      }
1052      else
1053      {
1054         result = x87_sub(cpustate, a, b);
1055      }
7291056   }
1057
1058   if (x87_check_exceptions(cpustate))
1059      x87_write_stack(cpustate, 0, result, TRUE);
1060
1061   CYCLES(cpustate, 8);
7301062}
7311063
732static void I386OP(fpu_group_da)(i386_state *cpustate)      // Opcode 0xda
1064void x87_fsubr_sti_st(i386_state *cpustate, UINT8 modrm)
7331065{
734   UINT8 modrm = FETCH(cpustate);
1066   floatx80 result;
1067   int i = modrm & 7;
7351068
736   if (modrm < 0xc0)
1069   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
7371070   {
738      UINT32 ea = GetEA(cpustate,modrm);
739      double t;
740      t = (double)READ32(cpustate,ea);
1071      x87_set_stack_underflow(cpustate);
1072      result = fx80_inan;
1073   }
1074   else
1075   {
1076      floatx80 a = ST(0);
1077      floatx80 b = ST(i);
7411078
742      switch ((modrm >> 3) & 0x7)
1079      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1080      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
7431081      {
744         case 0:   // FIADD
745            ST(0).f+=t;
746            CYCLES(cpustate,20);
747            break;
748         case 1:   // FIMUL
749            ST(0).f*=t;
750            CYCLES(cpustate,22);
751            break;
752         case 2:   // FICOM
753            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
754            if(ST(0).f == t)
755               cpustate->fpu_status_word |= FPU_C3;
756            if(ST(0).f < t)
757               cpustate->fpu_status_word |= FPU_C0;
1082         cpustate->x87_sw |= X87_SW_IE;
1083         result = fx80_inan;
1084      }
1085      else
1086      {
1087         result = x87_sub(cpustate, a, b);
1088      }
1089   }
7581090
759            CYCLES(cpustate,15);
760            break;
761         case 3:   // FICOMP
762            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
763            if(ST(0).f == t)
764               cpustate->fpu_status_word |= FPU_C3;
765            if(ST(0).f < t)
766               cpustate->fpu_status_word |= FPU_C0;
1091   if (x87_check_exceptions(cpustate))
1092      x87_write_stack(cpustate, i, result, TRUE);
7671093
768            FPU_POP(cpustate);
769            CYCLES(cpustate,15);
770            break;
1094   CYCLES(cpustate, 8);
1095}
7711096
772         case 4:   // FISUB
773            ST(0).f-=t;
774            CYCLES(cpustate,15);
775            break;
1097void x87_fsubrp(i386_state *cpustate, UINT8 modrm)
1098{
1099   floatx80 result;
1100   int i = modrm & 7;
7761101
777         case 5:   // FISUBR
778            ST(0).f = t - ST(0).f;
779            CYCLES(cpustate,15);
780            break;
1102   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1103   {
1104      x87_set_stack_underflow(cpustate);
1105      result = fx80_inan;
1106   }
1107   else
1108   {
1109      floatx80 a = ST(0);
1110      floatx80 b = ST(i);
7811111
782         case 6:   // FIDIV
783            if(t == 0.0)
784               ST(0).f/=t;
785            else
786            {
787               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
788                  ST(0).i |= FPU_INFINITY_DOUBLE;
789               else
790                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
791            }
792            CYCLES(cpustate,84);
793            break;
1112      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1113      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
1114      {
1115         cpustate->x87_sw |= X87_SW_IE;
1116         result = fx80_inan;
1117      }
1118      else
1119      {
1120         result = x87_sub(cpustate, a, b);
1121      }
1122   }
7941123
795         case 7:   // FIDIVR
796            if(ST(0).f == 0.0)
797               ST(0).f = t / ST(0).f;
798            else
799            {
800               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
801                  ST(0).i |= FPU_INFINITY_DOUBLE;
802               else
803                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
804            }
805            CYCLES(cpustate,84);
806            break;
1124   if (x87_check_exceptions(cpustate))
1125   {
1126      x87_write_stack(cpustate, i, result, TRUE);
1127      x87_inc_stack(cpustate);
1128   }
8071129
808         default:
809            fatalerror("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
1130   CYCLES(cpustate, 8);
1131}
1132
1133void x87_fisubr_m32int(i386_state *cpustate, UINT8 modrm)
1134{
1135   floatx80 result;
1136
1137   if (X87_IS_ST_EMPTY(0))
1138   {
1139      x87_set_stack_underflow(cpustate);
1140      result = fx80_inan;
1141   }
1142   else
1143   {
1144      UINT32 ea = GetEA(cpustate, modrm);
1145      INT32 m32int = READ32(cpustate, ea);
1146
1147      floatx80 a = int32_to_floatx80(m32int);
1148      floatx80 b = ST(0);
1149
1150      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1151      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
1152      {
1153         cpustate->x87_sw |= X87_SW_IE;
1154         result = fx80_inan;
8101155      }
1156      else
1157      {
1158         result = x87_sub(cpustate, a, b);
1159      }
8111160   }
1161
1162   if (x87_check_exceptions(cpustate))
1163      x87_write_stack(cpustate, 0, result, TRUE);
1164
1165   CYCLES(cpustate, 19);
1166}
1167
1168void x87_fisubr_m16int(i386_state *cpustate, UINT8 modrm)
1169{
1170   floatx80 result;
1171
1172   if (X87_IS_ST_EMPTY(0))
1173   {
1174      x87_set_stack_underflow(cpustate);
1175      result = fx80_inan;
1176   }
8121177   else
8131178   {
814      switch(modrm & 0x3f)
1179      UINT32 ea = GetEA(cpustate, modrm);
1180      INT16 m16int = READ16(cpustate, ea);
1181
1182      floatx80 a = int32_to_floatx80(m16int);
1183      floatx80 b = ST(0);
1184
1185      if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1186      || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000)))
8151187      {
816         case 0x29: // FUCOMPP
817            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
818            if(ST(0).f == ST(1).f)
819               cpustate->fpu_status_word |= FPU_C3;
820            if(ST(0).f < ST(1).f)
821               cpustate->fpu_status_word |= FPU_C0;
1188         cpustate->x87_sw |= X87_SW_IE;
1189         result = fx80_inan;
1190      }
1191      else
1192      {
1193         result = x87_sub(cpustate, a, b);
1194      }
1195   }
8221196
823            FPU_POP(cpustate);
824            FPU_POP(cpustate);
825            CYCLES(cpustate,5);
826            break;
827         default:
828            fatalerror("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
1197   if (x87_check_exceptions(cpustate))
1198      x87_write_stack(cpustate, 0, result, TRUE);
1199
1200   CYCLES(cpustate, 20);
1201}
1202
1203
1204/*************************************
1205 *
1206 * Divide
1207 *
1208 *************************************/
1209
1210void x87_fdiv_m32real(i386_state *cpustate, UINT8 modrm)
1211{
1212   floatx80 result;
1213
1214   if (X87_IS_ST_EMPTY(0))
1215   {
1216      x87_set_stack_underflow(cpustate);
1217      result = fx80_inan;
1218   }
1219   else
1220   {
1221      UINT32 ea = GetEA(cpustate, modrm);
1222      UINT32 m32real = READ32(cpustate, ea);
1223
1224      floatx80 a = ST(0);
1225      floatx80 b = float32_to_floatx80(m32real);
1226
1227      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1228      {
1229         cpustate->x87_sw |= X87_SW_IE;
1230         result = fx80_inan;
8291231      }
1232      else
1233      {
1234         result = x87_div(cpustate, a, b);
1235      }
8301236   }
1237
1238   if (x87_check_exceptions(cpustate))
1239      x87_write_stack(cpustate, 0, result, TRUE);
1240
1241   // 73, 62, 35
1242   CYCLES(cpustate, 73);
8311243}
8321244
833static void I386OP(fpu_group_db)(i386_state *cpustate)      // Opcode 0xdb
1245void x87_fdiv_m64real(i386_state *cpustate, UINT8 modrm)
8341246{
835   UINT8 modrm = FETCH(cpustate);
1247   floatx80 result;
8361248
837   if (modrm < 0xc0)
1249   if (X87_IS_ST_EMPTY(0))
8381250   {
839      UINT32 ea = GetEA(cpustate,modrm);
1251      x87_set_stack_underflow(cpustate);
1252      result = fx80_inan;
1253   }
1254   else
1255   {
1256      UINT32 ea = GetEA(cpustate, modrm);
1257      UINT64 m64real = READ64(cpustate, ea);
8401258
841      switch ((modrm >> 3) & 0x7)
1259      floatx80 a = ST(0);
1260      floatx80 b = float64_to_floatx80(m64real);
1261
1262      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
8421263      {
843         case 0:      // FILD
844         {
845            X87_REG t;
1264         cpustate->x87_sw |= X87_SW_IE;
1265         result = fx80_inan;
1266      }
1267      else
1268      {
1269         result = x87_div(cpustate, a, b);
1270      }
1271   }
8461272
847            t.f=(double)READ32(cpustate,ea);
848            FPU_PUSH(cpustate,t);
849            CYCLES(cpustate,9);
850            break;
851         }
1273   if (x87_check_exceptions(cpustate))
1274      x87_write_stack(cpustate, 0, result, TRUE);
8521275
853         case 2:      // FIST
854         {
855            INT32 t;
1276   // 73, 62, 35
1277   CYCLES(cpustate, 73);
1278}
8561279
857            t = X87_FROUND(cpustate,ST(0));
858            WRITE32(cpustate,ea,t);
859            CYCLES(cpustate,28);
860            break;
861         }
1280void x87_fdiv_st_sti(i386_state *cpustate, UINT8 modrm)
1281{
1282   int i = modrm & 7;
1283   floatx80 result;
8621284
863         case 3:      // FISTP
864         {
865            INT32 t;
1285   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1286   {
1287      x87_set_stack_underflow(cpustate);
1288      result = fx80_inan;
1289   }
1290   else
1291   {
1292      floatx80 a = ST(0);
1293      floatx80 b = ST(i);
8661294
867            t = X87_FROUND(cpustate,ST(0));
868            WRITE32(cpustate,ea,t);
869            FPU_POP(cpustate);
870            CYCLES(cpustate,28);
871            break;
872         }
1295      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1296      {
1297         cpustate->x87_sw |= X87_SW_IE;
1298         result = fx80_inan;
1299      }
1300      else
1301      {
1302         result = x87_div(cpustate, a, b);
1303      }
1304   }
8731305
874         case 5:      // FLD extended
875         {
876            X87_REG t;
1306   if (x87_check_exceptions(cpustate))
1307   {
1308      x87_write_stack(cpustate, 0, result, TRUE);
1309   }
8771310
878            t = READ80(cpustate,ea);
879            FPU_PUSH(cpustate,t);
880            CYCLES(cpustate,6);
881            break;
882         }
1311   // 73, 62, 35
1312   CYCLES(cpustate, 73);
1313}
8831314
884         case 7:      // FSTP extended
885         {
886            WRITE80(cpustate,ea,ST(0));
887            FPU_POP(cpustate);
888            CYCLES(cpustate,6);
889            break;
890         }
1315void x87_fdiv_sti_st(i386_state *cpustate, UINT8 modrm)
1316{
1317   int i = modrm & 7;
1318   floatx80 result;
8911319
892         default:
893            fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
1320   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1321   {
1322      x87_set_stack_underflow(cpustate);
1323      result = fx80_inan;
1324   }
1325   else
1326   {
1327      floatx80 a = ST(i);
1328      floatx80 b = ST(0);
1329
1330      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1331      {
1332         cpustate->x87_sw |= X87_SW_IE;
1333         result = fx80_inan;
8941334      }
1335      else
1336      {
1337         result = x87_div(cpustate, a, b);
1338      }
8951339   }
1340
1341   if (x87_check_exceptions(cpustate))
1342   {
1343      x87_write_stack(cpustate, i, result, TRUE);
1344   }
1345
1346   // 73, 62, 35
1347   CYCLES(cpustate, 73);
1348}
1349
1350void x87_fdivp(i386_state *cpustate, UINT8 modrm)
1351{
1352   int i = modrm & 7;
1353   floatx80 result;
1354
1355   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1356   {
1357      x87_set_stack_underflow(cpustate);
1358      result = fx80_inan;
1359   }
8961360   else
8971361   {
898      switch (modrm & 0x3f)
1362      floatx80 a = ST(i);
1363      floatx80 b = ST(0);
1364
1365      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
8991366      {
900         case 0x21:      // ??? (Sim City 2k)
901         {
902            logerror("x87 opcode 0xdb 0xe1 called at %08x\n",cpustate->pc-2);
903            CYCLES(cpustate,1);      // TODO
904            break;
905         }
906         case 0x22:      // FCLEX
907         {
908            // clears exception flags and busy bit.
909            cpustate->fpu_status_word &= ~0x80ff;
1367         cpustate->x87_sw |= X87_SW_IE;
1368         result = fx80_inan;
1369      }
1370      else
1371      {
1372         result = x87_div(cpustate, a, b);
1373      }
1374   }
9101375
911            CYCLES(cpustate,1);      // TODO
912            break;
913         }
914         case 0x23:      // FINIT
915         {
916            cpustate->fpu_control_word = 0x37f;
917            cpustate->fpu_status_word = 0;
918            cpustate->fpu_tag_word = 0xffff;
919            cpustate->fpu_data_ptr = 0;
920            cpustate->fpu_inst_ptr = 0;
921            cpustate->fpu_opcode = 0;
1376   if (x87_check_exceptions(cpustate))
1377   {
1378      x87_write_stack(cpustate, i, result, TRUE);
1379      x87_inc_stack(cpustate);
1380   }
9221381
923            CYCLES(cpustate,17);
924            break;
925         }
1382   // 73, 62, 35
1383   CYCLES(cpustate, 73);
1384}
9261385
927         case 0x24:      // FSETPM (treated as nop on 387+)
928         {
929            CYCLES(cpustate,1);
930            break;
931         }
1386void x87_fidiv_m32int(i386_state *cpustate, UINT8 modrm)
1387{
1388   floatx80 result;
9321389
933         default:
934            fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
1390   if (X87_IS_ST_EMPTY(0))
1391   {
1392      x87_set_stack_underflow(cpustate);
1393      result = fx80_inan;
1394   }
1395   else
1396   {
1397      UINT32 ea = GetEA(cpustate, modrm);
1398      INT32 m32int = READ32(cpustate, ea);
1399
1400      floatx80 a = ST(0);
1401      floatx80 b = int32_to_floatx80(m32int);
1402
1403      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1404      {
1405         cpustate->x87_sw |= X87_SW_IE;
1406         result = fx80_inan;
9351407      }
1408      else
1409      {
1410         result = x87_div(cpustate, a, b);
1411      }
9361412   }
1413
1414   if (x87_check_exceptions(cpustate))
1415      x87_write_stack(cpustate, 0, result, TRUE);
1416
1417   // 73, 62, 35
1418   CYCLES(cpustate, 73);
9371419}
9381420
939static void I386OP(fpu_group_dc)(i386_state *cpustate)      // Opcode 0xdc
1421void x87_fidiv_m16int(i386_state *cpustate, UINT8 modrm)
9401422{
941   UINT8 modrm = FETCH(cpustate);
1423   floatx80 result;
9421424
943   if (modrm < 0xc0)
1425   if (X87_IS_ST_EMPTY(0))
9441426   {
945      UINT32 ea = GetEA(cpustate,modrm);
946      X87_REG t;
1427      x87_set_stack_underflow(cpustate);
1428      result = fx80_inan;
1429   }
1430   else
1431   {
1432      UINT32 ea = GetEA(cpustate, modrm);
1433      INT16 m16int = READ32(cpustate, ea);
9471434
948      t.i = READ64(cpustate,ea);
1435      floatx80 a = ST(0);
1436      floatx80 b = int32_to_floatx80(m16int);
9491437
950      switch ((modrm >> 3) & 0x7)
1438      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
9511439      {
952         case 0: /* FADD double */
953         {
954            ST(0).f += t.f;
955            CYCLES(cpustate,8);
956            break;
957         }
1440         cpustate->x87_sw |= X87_SW_IE;
1441         result = fx80_inan;
1442      }
1443      else
1444      {
1445         result = x87_div(cpustate, a, b);
1446      }
1447   }
9581448
959         case 1: /* FMUL double */
960         {
961            ST(0).f *= t.f;
962            CYCLES(cpustate,14);
963            break;
964         }
1449   if (x87_check_exceptions(cpustate))
1450      x87_write_stack(cpustate, 0, result, TRUE);
9651451
966         case 2: /* FCOM double */
967         {
968            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
969            if(ST(0).f == t.f)
970               cpustate->fpu_status_word |= FPU_C3;
971            if(ST(0).f < t.f)
972               cpustate->fpu_status_word |= FPU_C0;
1452   // 73, 62, 35
1453   CYCLES(cpustate, 73);
1454}
9731455
974            CYCLES(cpustate,4);
975            break;
976         }
9771456
978         case 3: /* FCOMP double */
979         {
980            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
981            if(ST(0).f == t.f)
982               cpustate->fpu_status_word |= FPU_C3;
983            if(ST(0).f < t.f)
984               cpustate->fpu_status_word |= FPU_C0;
1457/*************************************
1458 *
1459 * Reverse Divide
1460 *
1461 *************************************/
9851462
986            FPU_POP(cpustate);
987            CYCLES(cpustate,4);
988            break;
989         }
1463void x87_fdivr_m32real(i386_state *cpustate, UINT8 modrm)
1464{
1465   floatx80 result;
9901466
991         case 4: /* FSUB double */
992         {
993            ST(0).f -= t.f;
994            CYCLES(cpustate,8);
995            break;
996         }
1467   if (X87_IS_ST_EMPTY(0))
1468   {
1469      x87_set_stack_underflow(cpustate);
1470      result = fx80_inan;
1471   }
1472   else
1473   {
1474      UINT32 ea = GetEA(cpustate, modrm);
1475      UINT32 m32real = READ32(cpustate, ea);
9971476
998         case 5: /* FSUBR double */
999         {
1000            ST(0).f = t.f - ST(0).f;
1001            CYCLES(cpustate,8);
1002            break;
1003         }
1477      floatx80 a = float32_to_floatx80(m32real);
1478      floatx80 b = ST(0);
10041479
1005         case 6: /* FDIV double */
1006         {
1007            if(t.f != 0.0)
1008               ST(0).f /= t.f;
1009            else
1010            {
1011               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1012                  ST(0).i |= FPU_INFINITY_DOUBLE;
1013               else
1014                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
1015            }
1480      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1481      {
1482         cpustate->x87_sw |= X87_SW_IE;
1483         result = fx80_inan;
1484      }
1485      else
1486      {
1487         result = x87_div(cpustate, a, b);
1488      }
1489   }
10161490
1017            CYCLES(cpustate,73);
1018            break;
1019         }
1491   if (x87_check_exceptions(cpustate))
1492      x87_write_stack(cpustate, 0, result, TRUE);
10201493
1021         case 7: /* FDIV double */
1022         {
1023            if(ST(0).f != 0.0)
1024               ST(0).f = t.f / ST(0).f;
1025            else
1026            {
1027               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1028                  ST(0).i |= FPU_INFINITY_DOUBLE;
1029               else
1030                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
1031            }
1032            CYCLES(cpustate,73);
1033            break;
1034         }
1494   // 73, 62, 35
1495   CYCLES(cpustate, 73);
1496}
10351497
1036         default:
1037            fatalerror("I386: FPU Op DC %02X at %08X", (modrm >> 3) & 0x7, cpustate->pc-2);
1498void x87_fdivr_m64real(i386_state *cpustate, UINT8 modrm)
1499{
1500   floatx80 result;
1501
1502   if (X87_IS_ST_EMPTY(0))
1503   {
1504      x87_set_stack_underflow(cpustate);
1505      result = fx80_inan;
1506   }
1507   else
1508   {
1509      UINT32 ea = GetEA(cpustate, modrm);
1510      UINT64 m64real = READ64(cpustate, ea);
1511
1512      floatx80 a = float64_to_floatx80(m64real);
1513      floatx80 b = ST(0);
1514
1515      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1516      {
1517         cpustate->x87_sw |= X87_SW_IE;
1518         result = fx80_inan;
10381519      }
1520      else
1521      {
1522         result = x87_div(cpustate, a, b);
1523      }
10391524   }
1525
1526   if (x87_check_exceptions(cpustate))
1527      x87_write_stack(cpustate, 0, result, TRUE);
1528
1529   // 73, 62, 35
1530   CYCLES(cpustate, 73);
1531}
1532
1533void x87_fdivr_st_sti(i386_state *cpustate, UINT8 modrm)
1534{
1535   int i = modrm & 7;
1536   floatx80 result;
1537
1538   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1539   {
1540      x87_set_stack_underflow(cpustate);
1541      result = fx80_inan;
1542   }
10401543   else
10411544   {
1042      switch (modrm & 0x3f)
1545      floatx80 a = ST(i);
1546      floatx80 b = ST(0);
1547
1548      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
10431549      {
1044         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // FADD
1045         {
1046            ST(modrm & 7).f += ST(0).f;
1047            CYCLES(cpustate,8);
1048            break;
1049         }
1550         cpustate->x87_sw |= X87_SW_IE;
1551         result = fx80_inan;
1552      }
1553      else
1554      {
1555         result = x87_div(cpustate, a, b);
1556      }
1557   }
10501558
1051         case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // FMUL
1052         {
1053            ST(modrm & 7).f *= ST(0).f;
1054            CYCLES(cpustate,8);
1055            break;
1056         }
1559   if (x87_check_exceptions(cpustate))
1560   {
1561      x87_write_stack(cpustate, 0, result, TRUE);
1562   }
10571563
1058         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: // FSUBR
1059         {
1060            ST(modrm & 7).f = ST(0).f - ST(modrm & 7).f;
1061            CYCLES(cpustate,8);
1062            break;
1063         }
1564   // 73, 62, 35
1565   CYCLES(cpustate, 73);
1566}
10641567
1065         case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // FSUB
1066         {
1067            ST(modrm & 7).f -= ST(0).f;
1068            CYCLES(cpustate,8);
1069            break;
1070         }
1568void x87_fdivr_sti_st(i386_state *cpustate, UINT8 modrm)
1569{
1570   int i = modrm & 7;
1571   floatx80 result;
10711572
1072         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // FSUBR
1073         {
1074            ST(modrm & 7).f = ST(0).f - ST(modrm & 7).f;
1075            CYCLES(cpustate,8);
1076            break;
1077         }
1573   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1574   {
1575      x87_set_stack_underflow(cpustate);
1576      result = fx80_inan;
1577   }
1578   else
1579   {
1580      floatx80 a = ST(0);
1581      floatx80 b = ST(i);
10781582
1079         case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // FSUB
1080         {
1081            ST(modrm & 7).f -= ST(0).f;
1082            CYCLES(cpustate,8);
1083            break;
1084         }
1583      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1584      {
1585         cpustate->x87_sw |= X87_SW_IE;
1586         result = fx80_inan;
1587      }
1588      else
1589      {
1590         result = x87_div(cpustate, a, b);
1591      }
1592   }
10851593
1086         // FDIVR
1087         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
1088         {
1089            if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0)
1090            {
1091               // set result as infinity if zero divide is masked
1092               if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1093               {
1094                  ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
1095               }
1096            }
1097            else
1098            {
1099               ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
1100            }
1101            CYCLES(cpustate,73);
1102            break;
1103         }
1594   if (x87_check_exceptions(cpustate))
1595   {
1596      x87_write_stack(cpustate, i, result, TRUE);
1597   }
11041598
1105          // FDIV
1106         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
1107         {
1108            if ((ST(0).i & U64(0x7fffffffffffffff)) == 0)
1109            {
1110               // set result as infinity if zero divide is masked
1111               if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1112               {
1113                  ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
1114               }
1115            }
1116            else
1117            {
1118               ST(modrm & 7).f /= ST(0).f;
1119            }
1120            CYCLES(cpustate,73);
1121            break;
1122         }
1599   // 73, 62, 35
1600   CYCLES(cpustate, 73);
1601}
11231602
1124         default:
1125            fatalerror("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
1603void x87_fdivrp(i386_state *cpustate, UINT8 modrm)
1604{
1605   int i = modrm & 7;
1606   floatx80 result;
1607
1608   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1609   {
1610      x87_set_stack_underflow(cpustate);
1611      result = fx80_inan;
1612   }
1613   else
1614   {
1615      floatx80 a = ST(0);
1616      floatx80 b = ST(i);
1617
1618      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1619      {
1620         cpustate->x87_sw |= X87_SW_IE;
1621         result = fx80_inan;
11261622      }
1623      else
1624      {
1625         result = x87_div(cpustate, a, b);
1626      }
11271627   }
1628
1629   if (x87_check_exceptions(cpustate))
1630   {
1631      x87_write_stack(cpustate, i, result, TRUE);
1632      x87_inc_stack(cpustate);
1633   }
1634
1635   // 73, 62, 35
1636   CYCLES(cpustate, 73);
11281637}
11291638
1130static void I386OP(fpu_group_dd)(i386_state *cpustate)      // Opcode 0xdd
1639
1640void x87_fidivr_m32int(i386_state *cpustate, UINT8 modrm)
11311641{
1132   UINT8 modrm = FETCH(cpustate);
1642   floatx80 result;
11331643
1134   if (modrm < 0xc0)
1644   if (X87_IS_ST_EMPTY(0))
11351645   {
1136      UINT32 ea = GetEA(cpustate,modrm);
1646      x87_set_stack_underflow(cpustate);
1647      result = fx80_inan;
1648   }
1649   else
1650   {
1651      UINT32 ea = GetEA(cpustate, modrm);
1652      INT32 m32int = READ32(cpustate, ea);
11371653
1138      switch ((modrm >> 3) & 0x7)
1654      floatx80 a = int32_to_floatx80(m32int);
1655      floatx80 b = ST(0);
1656
1657      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
11391658      {
1140         case 0: // FLD
1141         {
1142            X87_REG t;
1143            t.i = READ64(cpustate,ea);
1144            FPU_PUSH(cpustate,t);
1145            CYCLES(cpustate,3);
1146            break;
1147         }
1659         cpustate->x87_sw |= X87_SW_IE;
1660         result = fx80_inan;
1661      }
1662      else
1663      {
1664         result = x87_div(cpustate, a, b);
1665      }
1666   }
11481667
1149         case 2: // FST
1150         {
1151            X87_REG t;
1152            t.f = ST(0).f;
1153            WRITE64(cpustate,ea, t.i);
1154            //FPU_POP(cpustate);
1155            CYCLES(cpustate,8);
1156            break;
1157         }
1668   if (x87_check_exceptions(cpustate))
1669      x87_write_stack(cpustate, 0, result, TRUE);
11581670
1671   // 73, 62, 35
1672   CYCLES(cpustate, 73);
1673}
11591674
1160         case 3: // FSTP
1161         {
1162            X87_REG t;
1163            t.f = ST(0).f;
1164            WRITE64(cpustate,ea, t.i);
1165            FPU_POP(cpustate);
1166            CYCLES(cpustate,8);
1167            break;
1168         }
1675void x87_fidivr_m16int(i386_state *cpustate, UINT8 modrm)
1676{
1677   floatx80 result;
11691678
1170         case 4:   // FRSTOR
1171         {
1172            int i;
1173            if( cpustate->operand_size )  // 32-bit real/protected mode
1174            {
1175               cpustate->fpu_control_word = READ16(cpustate,ea);
1176               cpustate->fpu_status_word = READ16(cpustate,ea+4);
1177               cpustate->fpu_tag_word = READ16(cpustate,ea+8);
1178               ea+=28;
1179            }
1180            else // 16-bit real/protected mode
1181            {
1182               cpustate->fpu_control_word = READ16(cpustate,ea);
1183               cpustate->fpu_status_word = READ16(cpustate,ea+2);
1184               cpustate->fpu_tag_word = READ16(cpustate,ea+4);
1185               ea+=14;
1186            }
1679   if (X87_IS_ST_EMPTY(0))
1680   {
1681      x87_set_stack_underflow(cpustate);
1682      result = fx80_inan;
1683   }
1684   else
1685   {
1686      UINT32 ea = GetEA(cpustate, modrm);
1687      INT16 m16int = READ32(cpustate, ea);
11871688
1188            cpustate->fpu_top = (cpustate->fpu_status_word>>11) & 7;
1689      floatx80 a = int32_to_floatx80(m16int);
1690      floatx80 b = ST(0);
11891691
1190            for(i=0;i<8;i++)
1191               ST(i) = READ80(cpustate,ea+i*10);
1692      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1693      {
1694         cpustate->x87_sw |= X87_SW_IE;
1695         result = fx80_inan;
1696      }
1697      else
1698      {
1699         result = x87_div(cpustate, a, b);
1700      }
1701   }
11921702
1193            CYCLES(cpustate,(cpustate->cr[0] & 1) ? 34 : 44);
1194            break;
1195         }
1703   if (x87_check_exceptions(cpustate))
1704      x87_write_stack(cpustate, 0, result, TRUE);
11961705
1197         case 6: // FSAVE
1198         {
1199            int i;
1200            logerror("x87 FSAVE triggered with mode = %d %02x %02x\n",(cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1,cpustate->cr[0],cpustate->operand_size);
1201            switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
1202            {
1203               case 0:   // 16-bit real mode
1204                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
1205                  WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
1206                  WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
1207                  WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
1208                  //WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1209                  WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
1210                  //WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1211                  ea+=14;
1212                  break;
1213               case 1: // 16-bit protected mode
1214                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
1215                  WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
1216                  WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
1217                  WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
1218                  WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1219                  WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
1220                  WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1221                  ea+=14;
1222                  break;
1223               case 2: // 32-bit real mode
1224                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
1225                  WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
1226                  WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
1227                  WRITE16(cpustate,ea+12, cpustate->fpu_inst_ptr & 0xffff);
1228                  //WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1229                  WRITE16(cpustate,ea+20, cpustate->fpu_data_ptr & 0xffff);
1230                  //WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
1231                  WRITE32(cpustate,ea+24, (cpustate->fpu_data_ptr>>16)<<12);
1232                  ea+=28;
1233                  break;
1234               case 3: // 32-bit protected mode
1235                  WRITE16(cpustate,ea, cpustate->fpu_control_word);
1236                  WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
1237                  WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
1238                  WRITE32(cpustate,ea+12, cpustate->fpu_inst_ptr);
1239                  WRITE32(cpustate,ea+16, cpustate->fpu_opcode);
1240                  WRITE32(cpustate,ea+20, cpustate->fpu_data_ptr);
1241                  WRITE32(cpustate,ea+24, cpustate->fpu_inst_ptr);
1242                  ea+=28;
1243                  break;
1244            }
1706   // 73, 62, 35
1707   CYCLES(cpustate, 73);
1708}
12451709
1246            for(i=0;i<8;i++)
1247               ST(i) = READ80(cpustate,ea+i*10);
12481710
1249            CYCLES(cpustate,(cpustate->cr[0] & 1) ? 56 : 67);
1250            break;
1251         }
1711/*************************************
1712 *
1713 * Multiply
1714 *
1715 *************************************/
12521716
1253         case 7:         // FSTSW
1254         {
1255            WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 11));
1256            CYCLES(cpustate,1);      // TODO
1257            break;
1258         }
1717void x87_fmul_m32real(i386_state *cpustate, UINT8 modrm)
1718{
1719   floatx80 result;
12591720
1260         default:
1261            fatalerror("I386: FPU Op DD %02X (%02X) at %08X", modrm, (modrm >> 3) & 7, cpustate->pc-2);
1721   if (X87_IS_ST_EMPTY(0))
1722   {
1723      x87_set_stack_underflow(cpustate);
1724      result = fx80_inan;
1725   }
1726   else
1727   {
1728      UINT32 ea = GetEA(cpustate, modrm);
1729      UINT32 m32real = READ32(cpustate, ea);
1730
1731      floatx80 a = ST(0);
1732      floatx80 b = float32_to_floatx80(m32real);
1733
1734      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1735      {
1736         cpustate->x87_sw |= X87_SW_IE;
1737         result = fx80_inan;
12621738      }
1739      else
1740      {
1741         result = x87_mul(cpustate, a, b);
1742      }
12631743   }
1744
1745   if (x87_check_exceptions(cpustate))
1746      x87_write_stack(cpustate, 0, result, TRUE);
1747
1748   CYCLES(cpustate, 11);
1749}
1750
1751void x87_fmul_m64real(i386_state *cpustate, UINT8 modrm)
1752{
1753   floatx80 result;
1754
1755   if (X87_IS_ST_EMPTY(0))
1756   {
1757      x87_set_stack_underflow(cpustate);
1758      result = fx80_inan;
1759   }
12641760   else
12651761   {
1266      switch (modrm & 0x3f)
1762      UINT32 ea = GetEA(cpustate, modrm);
1763      UINT64 m64real = READ64(cpustate, ea);
1764
1765      floatx80 a = ST(0);
1766      floatx80 b = float64_to_floatx80(m64real);
1767
1768      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
12671769      {
1268         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // FFREE
1269         {
1270            cpustate->fpu_tag_word |= (3<<((modrm & 7)<< 1));
1271            CYCLES(cpustate,3);
1272            break;
1273         }
1770         cpustate->x87_sw |= X87_SW_IE;
1771         result = fx80_inan;
1772      }
1773      else
1774      {
1775         result = x87_mul(cpustate, a, b);
1776      }
1777   }
12741778
1275         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: // FST
1276         {
1277            UINT16 tmp;
1278            ST(modrm & 7) = ST(0);
1279            tmp = (cpustate->fpu_tag_word>>((cpustate->fpu_top&7)<<1))&3;
1280            cpustate->fpu_tag_word &= ~(3<<((modrm & 7)<< 1));
1281            cpustate->fpu_tag_word |= (tmp<<((modrm & 7)<< 1));
1282            CYCLES(cpustate,3);
1283            break;
1284         }
1779   if (x87_check_exceptions(cpustate))
1780      x87_write_stack(cpustate, 0, result, TRUE);
12851781
1286         case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // FSTP
1287         {
1288            UINT16 tmp;
1289            ST(modrm & 7) = ST(0);
1290            tmp = (cpustate->fpu_tag_word>>((cpustate->fpu_top&7)<<1))&3;
1291            cpustate->fpu_tag_word &= ~(3<<((modrm & 7)<< 1));
1292            cpustate->fpu_tag_word |= (tmp<<((modrm & 7)<< 1));
1293            FPU_POP(cpustate);
1294            CYCLES(cpustate,3);
1295            break;
1296         }
1782   CYCLES(cpustate, 14);
1783}
12971784
1298         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // FUCOM
1299         {
1300            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
1301            if (ST(0).f > ST(modrm & 7).f)
1302            {
1303               // C3 = 0, C2 = 0, C0 = 0
1304            }
1305            else if (ST(0).f < ST(modrm & 7).f)
1306            {
1307               cpustate->fpu_status_word |= FPU_C0;
1308            }
1309            else if (ST(0).f == ST(modrm & 7).f)
1310            {
1311               cpustate->fpu_status_word |= FPU_C3;
1312            }
1313            else
1314            {
1315               // unordered
1316               cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
1317            }
1785void x87_fmul_st_sti(i386_state *cpustate, UINT8 modrm)
1786{
1787   floatx80 result;
1788   int i = modrm & 7;
13181789
1319            //FPU_POP(cpustate);
1320            CYCLES(cpustate,4);
1321            break;
1322         }
1790   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1791   {
1792      x87_set_stack_underflow(cpustate);
1793      result = fx80_inan;
1794   }
1795   else
1796   {
1797      floatx80 a = ST(0);
1798      floatx80 b = ST(i);
13231799
1324         case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // FUCOMP
1325         {
1326            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
1327            if (ST(0).f > ST(modrm & 7).f)
1328            {
1329               // C3 = 0, C2 = 0, C0 = 0
1330            }
1331            else if (ST(0).f < ST(modrm & 7).f)
1332            {
1333               cpustate->fpu_status_word |= FPU_C0;
1334            }
1335            else if (ST(0).f == ST(modrm & 7).f)
1336            {
1337               cpustate->fpu_status_word |= FPU_C3;
1338            }
1339            else
1340            {
1341               // unordered
1342               cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
1343            }
1800      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1801      {
1802         cpustate->x87_sw |= X87_SW_IE;
1803         result = fx80_inan;
1804      }
1805      else
1806      {
1807         result = x87_mul(cpustate, a, b);
1808      }
1809   }
13441810
1345            FPU_POP(cpustate);
1346            CYCLES(cpustate,4);
1347            break;
1348         }
1811   if (x87_check_exceptions(cpustate))
1812      x87_write_stack(cpustate, 0, result, TRUE);
13491813
1350         default:
1351            fatalerror("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
1814   CYCLES(cpustate, 16);
1815}
1816
1817void x87_fmul_sti_st(i386_state *cpustate, UINT8 modrm)
1818{
1819   floatx80 result;
1820   int i = modrm & 7;
1821
1822   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
1823   {
1824      x87_set_stack_underflow(cpustate);
1825      result = fx80_inan;
1826   }
1827   else
1828   {
1829      floatx80 a = ST(0);
1830      floatx80 b = ST(i);
1831
1832      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1833      {
1834         cpustate->x87_sw |= X87_SW_IE;
1835         result = fx80_inan;
13521836      }
1837      else
1838      {
1839         result = x87_mul(cpustate, a, b);
1840      }
13531841   }
1842
1843   if (x87_check_exceptions(cpustate))
1844      x87_write_stack(cpustate, i, result, TRUE);
1845
1846   CYCLES(cpustate, 16);
13541847}
13551848
1356static void I386OP(fpu_group_de)(i386_state *cpustate)      // Opcode 0xde
1849void x87_fmulp(i386_state *cpustate, UINT8 modrm)
13571850{
1358   UINT8 modrm = FETCH(cpustate);
1851   floatx80 result;
1852   int i = modrm & 7;
13591853
1360   if (modrm < 0xc0)
1854   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
13611855   {
1362      UINT32 ea = GetEA(cpustate,modrm);
1363      INT32 t;
1856      x87_set_stack_underflow(cpustate);
1857      result = fx80_inan;
1858   }
1859   else
1860   {
1861      floatx80 a = ST(0);
1862      floatx80 b = ST(i);
13641863
1365      t = (INT32)READ16(cpustate,ea);
1864      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1865      {
1866         cpustate->x87_sw |= X87_SW_IE;
1867         result = fx80_inan;
1868      }
1869      else
1870      {
1871         result = x87_mul(cpustate, a, b);
1872      }
1873   }
13661874
1367      switch ((modrm >> 3) & 0x7)
1875   if (x87_check_exceptions(cpustate))
1876   {
1877      x87_write_stack(cpustate, i, result, TRUE);
1878      x87_inc_stack(cpustate);
1879   }
1880
1881   CYCLES(cpustate, 16);
1882}
1883
1884void x87_fimul_m32int(i386_state *cpustate, UINT8 modrm)
1885{
1886   floatx80 result;
1887
1888   if (X87_IS_ST_EMPTY(0))
1889   {
1890      x87_set_stack_underflow(cpustate);
1891      result = fx80_inan;
1892   }
1893   else
1894   {
1895      UINT32 ea = GetEA(cpustate, modrm);
1896      INT32 m32int = READ32(cpustate, ea);
1897
1898      floatx80 a = ST(0);
1899      floatx80 b = int32_to_floatx80(m32int);
1900
1901      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
13681902      {
1369         case 0:   // FIADD single precision
1370         {
1371            ST(0).f+=(double)t;
1372            CYCLES(cpustate,20);
1373            break;
1374         }
1903         cpustate->x87_sw |= X87_SW_IE;
1904         result = fx80_inan;
1905      }
1906      else
1907      {
1908         result = x87_mul(cpustate, a, b);
1909      }
1910   }
13751911
1376         case 1:   // FIMUL single precision
1377         {
1378            ST(0).f*=(double)t;
1379            CYCLES(cpustate,22);
1380            break;
1381         }
1912   if (x87_check_exceptions(cpustate))
1913      x87_write_stack(cpustate, 0, result, TRUE);
13821914
1383         case 2: // FICOM
1384         {
1385            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
1386            if (ST(0).f > (double)t)
1387            {
1388               // C3 = 0, C2 = 0, C0 = 0
1389            }
1390            else if (ST(0).f < (double)t)
1391            {
1392               cpustate->fpu_status_word |= FPU_C0;
1393            }
1394            else if (ST(0).f == (double)t)
1395            {
1396               cpustate->fpu_status_word |= FPU_C3;
1397            }
1398            else
1399            {
1400               // unordered
1401               cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
1402            }
1403            CYCLES(cpustate,15);
1404            break;
1405         }
1915   CYCLES(cpustate, 22);
1916}
14061917
1407         case 3: // FICOMP
1408         {
1409            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
1410            if (ST(0).f > (double)t)
1411            {
1412               // C3 = 0, C2 = 0, C0 = 0
1413            }
1414            else if (ST(0).f < (double)t)
1415            {
1416               cpustate->fpu_status_word |= FPU_C0;
1417            }
1418            else if (ST(0).f == (double)t)
1419            {
1420               cpustate->fpu_status_word |= FPU_C3;
1421            }
1422            else
1423            {
1424               // unordered
1425               cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
1426            }
1427            FPU_POP(cpustate);
1428            CYCLES(cpustate,15);
1429            break;
1430         }
1918void x87_fimul_m16int(i386_state *cpustate, UINT8 modrm)
1919{
1920   floatx80 result;
14311921
1432         case 4:   // FISUB single precision
1433         {
1434            ST(0).f-=(double)t;
1435            CYCLES(cpustate,20);
1436            break;
1437         }
1922   if (X87_IS_ST_EMPTY(0))
1923   {
1924      x87_set_stack_underflow(cpustate);
1925      result = fx80_inan;
1926   }
1927   else
1928   {
1929      UINT32 ea = GetEA(cpustate, modrm);
1930      INT16 m16int = READ16(cpustate, ea);
14381931
1439         case 5:   // FISUBR single precision
1440         {
1441            ST(0).f = (double)t - ST(0).f;
1442            CYCLES(cpustate,20);
1443            break;
1444         }
1932      floatx80 a = ST(0);
1933      floatx80 b = int32_to_floatx80(m16int);
14451934
1446         case 6:   // FIDIV single precision
1447         {
1448            if((double)t == 0)
1449            {
1450               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1451                  ST(0).i = FPU_INFINITY_DOUBLE;
1452               else
1453                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
1454            }
1455            else
1456               ST(0).f/=(double)t;
1457            CYCLES(cpustate,84);
1458            break;
1459         }
1935      if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
1936      {
1937         cpustate->x87_sw |= X87_SW_IE;
1938         result = fx80_inan;
1939      }
1940      else
1941      {
1942         result = x87_mul(cpustate, a, b);
1943      }
1944   }
14601945
1461         case 7:   // FIDIVR single precision
1462         {
1463            if(ST(0).f == 0)
1464            {
1465               if(cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1466                  ST(0).i = FPU_INFINITY_DOUBLE;
1467               else
1468                  cpustate->fpu_status_word |= FPU_EXCEPTION_ZERO_DIVIDE;
1469            }
1470            else
1471               ST(0).f = (double)t / ST(0).f;
1472            CYCLES(cpustate,84);
1473            break;
1474         }
1946   if (x87_check_exceptions(cpustate))
1947      x87_write_stack(cpustate, 0, result, TRUE);
14751948
1949   CYCLES(cpustate, 22);
1950}
14761951
1477         default:
1478            fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
1952
1953/*************************************
1954 *
1955 * Miscellaneous arithmetic
1956 *
1957 *************************************/
1958
1959void x87_fprem(i386_state *cpustate, UINT8 modrm)
1960{
1961   floatx80 result;
1962
1963   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
1964   {
1965      x87_set_stack_underflow(cpustate);
1966      result = fx80_inan;
1967   }
1968   else
1969   {
1970      floatx80 a = ST(0);
1971      floatx80 b = ST(1);
1972
1973      cpustate->x87_sw &= ~X87_SW_C0;
1974
1975      // TODO: Implement Cx bits
1976      result = floatx80_rem(a, b);
1977   }
1978
1979   if (x87_check_exceptions(cpustate))
1980      x87_write_stack(cpustate, 0, result, TRUE);
1981
1982   CYCLES(cpustate, 84);
1983}
1984
1985void x87_fprem1(i386_state *cpustate, UINT8 modrm)
1986{
1987   floatx80 result;
1988
1989   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
1990   {
1991      x87_set_stack_underflow(cpustate);
1992      result = fx80_inan;
1993   }
1994   else
1995   {
1996      floatx80 a = ST(0);
1997      floatx80 b = ST(1);
1998
1999      cpustate->x87_sw &= ~X87_SW_C0;
2000
2001      // TODO: Implement Cx bits
2002      result = floatx80_rem(a, b);
2003   }
2004
2005   if (x87_check_exceptions(cpustate))
2006      x87_write_stack(cpustate, 0, result, TRUE);
2007
2008   CYCLES(cpustate, 94);
2009}
2010
2011void x87_fsqrt(i386_state *cpustate, UINT8 modrm)
2012{
2013   floatx80 result;
2014
2015   if (X87_IS_ST_EMPTY(0))
2016   {
2017      x87_set_stack_underflow(cpustate);
2018      result = fx80_inan;
2019   }
2020   else
2021   {
2022      floatx80 value = ST(0);
2023
2024      if ((!floatx80_is_zero(value) && (value.high & 0x8000)) ||
2025          floatx80_is_denormal(value))
2026      {
2027         cpustate->x87_sw |= X87_SW_IE;
2028         result = fx80_inan;
14792029      }
2030      else
2031      {
2032         result = floatx80_sqrt(value);
2033      }
14802034   }
2035
2036   if (x87_check_exceptions(cpustate))
2037      x87_write_stack(cpustate, 0, result, TRUE);
2038
2039   CYCLES(cpustate, 8);
2040}
2041
2042/*************************************
2043 *
2044 * Trigonometric
2045 *
2046 *************************************/
2047
2048void x87_f2xm1(i386_state *cpustate, UINT8 modrm)
2049{
2050   floatx80 result;
2051
2052   if (X87_IS_ST_EMPTY(0))
2053   {
2054      x87_set_stack_underflow(cpustate);
2055      result = fx80_inan;
2056   }
14812057   else
14822058   {
1483      switch (modrm & 0x3f)
2059      // TODO: Inaccurate
2060      double x = fx80_to_double(ST(0));
2061      double res = pow(2.0, x) - 1;
2062      result = double_to_fx80(res);
2063   }
2064
2065   if (x87_check_exceptions(cpustate))
2066   {
2067      x87_write_stack(cpustate, 0, result, TRUE);
2068   }
2069
2070   CYCLES(cpustate, 242);
2071}
2072
2073void x87_fyl2x(i386_state *cpustate, UINT8 modrm)
2074{
2075   floatx80 result;
2076
2077   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
2078   {
2079      x87_set_stack_underflow(cpustate);
2080      result = fx80_inan;
2081   }
2082   else
2083   {
2084      floatx80 x = ST(0);
2085      floatx80 y = ST(1);
2086
2087      if (x.high & 0x8000)
14842088      {
1485         case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // FADDP
2089         cpustate->x87_sw |= X87_SW_IE;
2090         result = fx80_inan;
2091      }
2092      else
2093      {
2094         // TODO: Inaccurate
2095         double d64 = fx80_to_double(x);
2096         double l2x = log(d64)/log(2.0);
2097         result = floatx80_mul(double_to_fx80(l2x), y);
2098      }
2099   }
2100
2101   if (x87_check_exceptions(cpustate))
2102   {
2103      x87_write_stack(cpustate, 1, result, TRUE);
2104      x87_inc_stack(cpustate);
2105   }
2106
2107   CYCLES(cpustate, 250);
2108}
2109
2110void x87_fyl2xp1(i386_state *cpustate, UINT8 modrm)
2111{
2112   floatx80 result;
2113
2114   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
2115   {
2116      x87_set_stack_underflow(cpustate);
2117      result = fx80_inan;
2118   }
2119   else
2120   {
2121      floatx80 x = ST(0);
2122      floatx80 y = ST(1);
2123
2124      // TODO: Inaccurate
2125      double d64 = fx80_to_double(x);
2126      double l2x1 = log(d64 + 1.0)/log(2.0);
2127      result = floatx80_mul(double_to_fx80(l2x1), y);
2128   }
2129
2130   if (x87_check_exceptions(cpustate))
2131   {
2132      x87_write_stack(cpustate, 1, result, TRUE);
2133      x87_inc_stack(cpustate);
2134   }
2135
2136   CYCLES(cpustate, 313);
2137}
2138
2139void x87_fptan(i386_state *cpustate, UINT8 modrm)
2140{
2141   floatx80 result1, result2;
2142
2143   if (X87_IS_ST_EMPTY(0))
2144   {
2145      x87_set_stack_underflow(cpustate);
2146      result1 = fx80_inan;
2147      result2 = fx80_inan;
2148   }
2149   else if (!X87_IS_ST_EMPTY(7))
2150   {
2151      x87_set_stack_overflow(cpustate);
2152      result1 = fx80_inan;
2153      result2 = fx80_inan;
2154   }
2155   else
2156   {
2157      result1 = ST(0);
2158      result2 = fx80_one;
2159
2160      if (floatx80_ftan(result1) != -1)
2161         cpustate->x87_sw &= ~X87_SW_C2;
2162      else
2163         cpustate->x87_sw |= X87_SW_C2;
2164   }
2165
2166   if (x87_check_exceptions(cpustate))
2167   {
2168      x87_write_stack(cpustate, 0, result1, TRUE);
2169      x87_dec_stack(cpustate);
2170      x87_write_stack(cpustate, 0, result2, TRUE);
2171   }
2172
2173   CYCLES(cpustate, 244);
2174}
2175
2176void x87_fpatan(i386_state *cpustate, UINT8 modrm)
2177{
2178   floatx80 result;
2179
2180   if (X87_IS_ST_EMPTY(0))
2181   {
2182      x87_set_stack_underflow(cpustate);
2183      result = fx80_inan;
2184   }
2185   else
2186   {
2187      // TODO: Inaccurate
2188      double val = atan(fx80_to_double(ST(1)) / fx80_to_double(ST(0)));
2189      result = double_to_fx80(val);
2190   }
2191
2192   if (x87_check_exceptions(cpustate))
2193   {
2194      x87_write_stack(cpustate, 1, result, TRUE);
2195      x87_inc_stack(cpustate);
2196   }
2197
2198   CYCLES(cpustate, 289);
2199}
2200
2201void x87_fsin(i386_state *cpustate, UINT8 modrm)
2202{
2203   floatx80 result;
2204
2205   if (X87_IS_ST_EMPTY(0))
2206   {
2207      x87_set_stack_underflow(cpustate);
2208      result = fx80_inan;
2209   }
2210   else
2211   {
2212      result = ST(0);
2213
2214      if (floatx80_fsin(result) != -1)
2215         cpustate->x87_sw &= ~X87_SW_C2;
2216      else
2217         cpustate->x87_sw |= X87_SW_C2;
2218   }
2219
2220   if (x87_check_exceptions(cpustate))
2221      x87_write_stack(cpustate, 0, result, TRUE);
2222
2223   CYCLES(cpustate, 241);
2224}
2225
2226void x87_fcos(i386_state *cpustate, UINT8 modrm)
2227{
2228   floatx80 result;
2229
2230   if (X87_IS_ST_EMPTY(0))
2231   {
2232      x87_set_stack_underflow(cpustate);
2233      result = fx80_inan;
2234   }
2235   else
2236   {
2237      result = ST(0);
2238
2239      if (floatx80_fcos(result) != -1)
2240         cpustate->x87_sw &= ~X87_SW_C2;
2241      else
2242         cpustate->x87_sw |= X87_SW_C2;
2243   }
2244
2245   if (x87_check_exceptions(cpustate))
2246      x87_write_stack(cpustate, 0, result, TRUE);
2247
2248   CYCLES(cpustate, 241);
2249}
2250
2251void x87_fsincos(i386_state *cpustate, UINT8 modrm)
2252{
2253   floatx80 s_result, c_result;
2254
2255   if (X87_IS_ST_EMPTY(0))
2256   {
2257      x87_set_stack_underflow(cpustate);
2258      s_result = c_result = fx80_inan;
2259   }
2260   else if (!X87_IS_ST_EMPTY(7))
2261   {
2262      x87_set_stack_overflow(cpustate);
2263      s_result = c_result = fx80_inan;
2264   }
2265   else
2266   {
2267      extern int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a);
2268
2269      s_result = c_result = ST(0);
2270
2271      if (sf_fsincos(s_result, &s_result, &c_result) != -1)
2272         cpustate->x87_sw &= ~X87_SW_C2;
2273      else
2274         cpustate->x87_sw |= X87_SW_C2;
2275   }
2276
2277   if (x87_check_exceptions(cpustate))
2278   {
2279      x87_write_stack(cpustate, 0, s_result, TRUE);
2280      x87_dec_stack(cpustate);
2281      x87_write_stack(cpustate, 0, c_result, TRUE);
2282   }
2283
2284   CYCLES(cpustate, 291);
2285}
2286
2287
2288/*************************************
2289 *
2290 * Load data
2291 *
2292 *************************************/
2293
2294void x87_fld_m32real(i386_state *cpustate, UINT8 modrm)
2295{
2296   floatx80 value;
2297
2298   if (x87_dec_stack(cpustate))
2299   {
2300      UINT32 ea = GetEA(cpustate, modrm);
2301      UINT32 m32real = READ32(cpustate, ea);
2302
2303      value = float32_to_floatx80(m32real);
2304
2305      cpustate->x87_sw &= ~X87_SW_C1;
2306
2307      if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value))
2308      {
2309         cpustate->x87_sw |= X87_SW_IE;
2310         value = fx80_inan;
2311      }
2312   }
2313   else
2314   {
2315      value = fx80_inan;
2316   }
2317
2318   if (x87_check_exceptions(cpustate))
2319      x87_write_stack(cpustate, 0, value, TRUE);
2320
2321   CYCLES(cpustate, 3);
2322}
2323
2324void x87_fld_m64real(i386_state *cpustate, UINT8 modrm)
2325{
2326   floatx80 value;
2327
2328   if (x87_dec_stack(cpustate))
2329   {
2330      UINT32 ea = GetEA(cpustate, modrm);
2331      UINT64 m64real = READ64(cpustate, ea);
2332
2333      value = float64_to_floatx80(m64real);
2334
2335      cpustate->x87_sw &= ~X87_SW_C1;
2336
2337      if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value))
2338      {
2339         cpustate->x87_sw |= X87_SW_IE;
2340         value = fx80_inan;
2341      }
2342   }
2343   else
2344   {
2345      value = fx80_inan;
2346   }
2347
2348   if (x87_check_exceptions(cpustate))
2349      x87_write_stack(cpustate, 0, value, TRUE);
2350
2351   CYCLES(cpustate, 3);
2352}
2353
2354void x87_fld_m80real(i386_state *cpustate, UINT8 modrm)
2355{
2356   floatx80 value;
2357
2358   if (x87_dec_stack(cpustate))
2359   {
2360      cpustate->x87_sw &= ~X87_SW_C1;
2361      UINT32 ea = GetEA(cpustate, modrm);
2362      value = READ80(cpustate, ea);
2363   }
2364   else
2365   {
2366      value = fx80_inan;
2367   }
2368
2369   if (x87_check_exceptions(cpustate))
2370      x87_write_stack(cpustate, 0, value, TRUE);
2371
2372   CYCLES(cpustate, 6);
2373}
2374
2375void x87_fld_sti(i386_state *cpustate, UINT8 modrm)
2376{
2377   floatx80 value;
2378
2379   if (x87_dec_stack(cpustate))
2380   {
2381      cpustate->x87_sw &= ~X87_SW_C1;
2382      value = ST((modrm + 1) & 7);
2383   }
2384   else
2385   {
2386      value = fx80_inan;
2387   }
2388
2389   if (x87_check_exceptions(cpustate))
2390      x87_write_stack(cpustate, 0, value, TRUE);
2391
2392   CYCLES(cpustate, 4);
2393}
2394
2395void x87_fild_m16int(i386_state *cpustate, UINT8 modrm)
2396{
2397   floatx80 value;
2398
2399   if (!x87_dec_stack(cpustate))
2400   {
2401      value = fx80_inan;
2402   }
2403   else
2404   {
2405      cpustate->x87_sw &= ~X87_SW_C1;
2406
2407      UINT32 ea = GetEA(cpustate, modrm);
2408      INT16 m16int = READ16(cpustate, ea);
2409      value = int32_to_floatx80(m16int);
2410   }
2411
2412   if (x87_check_exceptions(cpustate))
2413      x87_write_stack(cpustate, 0, value, TRUE);
2414
2415   CYCLES(cpustate, 13);
2416}
2417
2418void x87_fild_m32int(i386_state *cpustate, UINT8 modrm)
2419{
2420   floatx80 value;
2421
2422   if (!x87_dec_stack(cpustate))
2423   {
2424      value = fx80_inan;
2425   }
2426   else
2427   {
2428      cpustate->x87_sw &= ~X87_SW_C1;
2429
2430      UINT32 ea = GetEA(cpustate, modrm);
2431      INT32 m32int = READ32(cpustate, ea);
2432      value = int32_to_floatx80(m32int);
2433   }
2434
2435   if (x87_check_exceptions(cpustate))
2436      x87_write_stack(cpustate, 0, value, TRUE);
2437
2438   CYCLES(cpustate, 9);
2439}
2440
2441void x87_fild_m64int(i386_state *cpustate, UINT8 modrm)
2442{
2443   floatx80 value;
2444
2445   if (!x87_dec_stack(cpustate))
2446   {
2447      value = fx80_inan;
2448   }
2449   else
2450   {
2451      cpustate->x87_sw &= ~X87_SW_C1;
2452
2453      UINT32 ea = GetEA(cpustate, modrm);
2454      INT64 m64int = READ64(cpustate, ea);
2455      value = int64_to_floatx80(m64int);
2456   }
2457
2458   if (x87_check_exceptions(cpustate))
2459      x87_write_stack(cpustate, 0, value, TRUE);
2460
2461   CYCLES(cpustate, 10);
2462}
2463
2464void x87_fbld(i386_state *cpustate, UINT8 modrm)
2465{
2466   floatx80 value;
2467
2468   if (!x87_dec_stack(cpustate))
2469   {
2470      value = fx80_inan;
2471   }
2472   else
2473   {
2474      cpustate->x87_sw &= ~X87_SW_C1;
2475
2476      UINT32 ea = GetEA(cpustate, modrm);
2477      UINT64 m64val = 0;
2478      UINT16 sign;
2479
2480      value = READ80(cpustate, ea);
2481
2482      sign = value.high & 0x8000;
2483      m64val += ((value.high >> 4) & 0xf) * 10;
2484      m64val += ((value.high >> 0) & 0xf);
2485
2486      for (int i = 60; i >= 0; i -= 4)
2487      {
2488         m64val *= 10;
2489         m64val += (value.low >> i) & 0xf;
2490      }
2491
2492      value = int64_to_floatx80(m64val);
2493      value.high |= sign;
2494   }
2495
2496   if (x87_check_exceptions(cpustate))
2497      x87_write_stack(cpustate, 0, value, TRUE);
2498
2499   CYCLES(cpustate, 75);
2500}
2501
2502
2503/*************************************
2504 *
2505 * Store data
2506 *
2507 *************************************/
2508
2509void x87_fst_m32real(i386_state *cpustate, UINT8 modrm)
2510{
2511   floatx80 value;
2512
2513   if (X87_IS_ST_EMPTY(0))
2514   {
2515      x87_set_stack_underflow(cpustate);
2516      value = fx80_inan;
2517   }
2518   else
2519   {
2520      cpustate->x87_sw &= ~X87_SW_C1;
2521      value = ST(0);
2522   }
2523
2524   if (x87_check_exceptions(cpustate))
2525   {
2526      UINT32 m32real = floatx80_to_float32(value);
2527      UINT32 ea = GetEA(cpustate, modrm);
2528      WRITE32(cpustate, ea, m32real);
2529   }
2530
2531   CYCLES(cpustate, 7);
2532}
2533
2534void x87_fst_m64real(i386_state *cpustate, UINT8 modrm)
2535{
2536   floatx80 value;
2537
2538   if (X87_IS_ST_EMPTY(0))
2539   {
2540      x87_set_stack_underflow(cpustate);
2541      value = fx80_inan;
2542   }
2543   else
2544   {
2545      cpustate->x87_sw &= ~X87_SW_C1;
2546      value = ST(0);
2547   }
2548
2549   if (x87_check_exceptions(cpustate))
2550   {
2551      UINT64 m64real = floatx80_to_float64(value);
2552      UINT32 ea = GetEA(cpustate, modrm);
2553      WRITE64(cpustate, ea, m64real);
2554   }
2555
2556   CYCLES(cpustate, 8);
2557}
2558
2559void x87_fst_sti(i386_state *cpustate, UINT8 modrm)
2560{
2561   int i = modrm & 7;
2562   floatx80 value;
2563
2564   if (X87_IS_ST_EMPTY(0))
2565   {
2566      x87_set_stack_underflow(cpustate);
2567      value = fx80_inan;
2568   }
2569   else
2570   {
2571      cpustate->x87_sw &= ~X87_SW_C1;
2572      value = ST(0);
2573   }
2574
2575   if (x87_check_exceptions(cpustate))
2576      x87_write_stack(cpustate, i, value, TRUE);
2577
2578   CYCLES(cpustate, 3);
2579}
2580
2581void x87_fstp_m32real(i386_state *cpustate, UINT8 modrm)
2582{
2583   floatx80 value;
2584
2585   if (X87_IS_ST_EMPTY(0))
2586   {
2587      x87_set_stack_underflow(cpustate);
2588      value = fx80_inan;
2589   }
2590   else
2591   {
2592      cpustate->x87_sw &= ~X87_SW_C1;
2593      value = ST(0);
2594   }
2595
2596   if (x87_check_exceptions(cpustate))
2597   {
2598      UINT32 m32real = floatx80_to_float32(value);
2599      UINT32 ea = GetEA(cpustate, modrm);
2600      WRITE32(cpustate, ea, m32real);
2601      x87_inc_stack(cpustate);
2602   }
2603
2604   CYCLES(cpustate, 7);
2605}
2606
2607void x87_fstp_m64real(i386_state *cpustate, UINT8 modrm)
2608{
2609   floatx80 value;
2610
2611   if (X87_IS_ST_EMPTY(0))
2612   {
2613      x87_set_stack_underflow(cpustate);
2614      value = fx80_inan;
2615   }
2616   else
2617   {
2618      cpustate->x87_sw &= ~X87_SW_C1;
2619      value = ST(0);
2620   }
2621
2622
2623   if (x87_check_exceptions(cpustate))
2624   {
2625      UINT64 m64real = floatx80_to_float64(value);
2626      UINT32 ea = GetEA(cpustate, modrm);
2627      WRITE64(cpustate, ea, m64real);
2628      x87_inc_stack(cpustate);
2629   }
2630
2631   CYCLES(cpustate, 8);
2632}
2633
2634void x87_fstp_m80real(i386_state *cpustate, UINT8 modrm)
2635{
2636   floatx80 value;
2637
2638   if (X87_IS_ST_EMPTY(0))
2639   {
2640      x87_set_stack_underflow(cpustate);
2641      value = fx80_inan;
2642   }
2643   else
2644   {
2645      cpustate->x87_sw &= ~X87_SW_C1;
2646      value = ST(0);
2647   }
2648
2649   if (x87_check_exceptions(cpustate))
2650   {
2651      UINT32 ea = GetEA(cpustate, modrm);
2652      WRITE80(cpustate, ea, value);
2653      x87_inc_stack(cpustate);
2654   }
2655
2656   CYCLES(cpustate, 6);
2657}
2658
2659void x87_fstp_sti(i386_state *cpustate, UINT8 modrm)
2660{
2661   int i = modrm & 7;
2662   floatx80 value;
2663
2664   if (X87_IS_ST_EMPTY(0))
2665   {
2666      x87_set_stack_underflow(cpustate);
2667      value = fx80_inan;
2668   }
2669   else
2670   {
2671      cpustate->x87_sw &= ~X87_SW_C1;
2672      value = ST(0);
2673   }
2674
2675   if (x87_check_exceptions(cpustate))
2676   {
2677      x87_write_stack(cpustate, i, value, TRUE);
2678      x87_inc_stack(cpustate);
2679   }
2680
2681   CYCLES(cpustate, 3);
2682}
2683
2684void x87_fist_m16int(i386_state *cpustate, UINT8 modrm)
2685{
2686   INT16 m16int;
2687
2688   if (X87_IS_ST_EMPTY(0))
2689   {
2690      x87_set_stack_underflow(cpustate);
2691      m16int = -32768;
2692   }
2693   else
2694   {
2695      floatx80 fx80 = floatx80_round_to_int(ST(0));
2696
2697      floatx80 lowerLim = int32_to_floatx80(-32768);
2698      floatx80 upperLim = int32_to_floatx80(32767);
2699
2700      cpustate->x87_sw &= ~X87_SW_C1;
2701
2702      if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim))
2703         m16int = floatx80_to_int32(fx80);
2704      else
2705         m16int = -32768;
2706   }
2707
2708   if (x87_check_exceptions(cpustate))
2709   {
2710      UINT32 ea = GetEA(cpustate, modrm);
2711      WRITE16(cpustate, ea, m16int);
2712   }
2713
2714   CYCLES(cpustate, 29);
2715}
2716
2717void x87_fist_m32int(i386_state *cpustate, UINT8 modrm)
2718{
2719   INT32 m32int;
2720
2721   if (X87_IS_ST_EMPTY(0))
2722   {
2723      x87_set_stack_underflow(cpustate);
2724      m32int = 0x80000000;
2725   }
2726   else
2727   {
2728      floatx80 fx80 = floatx80_round_to_int(ST(0));
2729
2730      floatx80 lowerLim = int32_to_floatx80(0x80000000);
2731      floatx80 upperLim = int32_to_floatx80(0x7fffffff);
2732
2733      cpustate->x87_sw &= ~X87_SW_C1;
2734
2735      if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim))
2736         m32int = floatx80_to_int32(fx80);
2737      else
2738         m32int = 0x80000000;
2739   }
2740
2741   if (x87_check_exceptions(cpustate))
2742   {
2743      UINT32 ea = GetEA(cpustate, modrm);
2744      WRITE32(cpustate, ea, m32int);
2745   }
2746
2747   CYCLES(cpustate, 28);
2748}
2749
2750void x87_fistp_m16int(i386_state *cpustate, UINT8 modrm)
2751{
2752   INT16 m16int;
2753
2754   if (X87_IS_ST_EMPTY(0))
2755   {
2756      x87_set_stack_underflow(cpustate);
2757      m16int = (UINT16)0x8000;
2758   }
2759   else
2760   {
2761      floatx80 fx80 = floatx80_round_to_int(ST(0));
2762
2763      floatx80 lowerLim = int32_to_floatx80(-32768);
2764      floatx80 upperLim = int32_to_floatx80(32767);
2765
2766      cpustate->x87_sw &= ~X87_SW_C1;
2767
2768      if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim))
2769         m16int = floatx80_to_int32(fx80);
2770      else
2771         m16int = (UINT16)0x8000;
2772   }
2773
2774   if (x87_check_exceptions(cpustate))
2775   {
2776      UINT32 ea = GetEA(cpustate, modrm);
2777      WRITE16(cpustate, ea, m16int);
2778      x87_inc_stack(cpustate);
2779   }
2780
2781   CYCLES(cpustate, 29);
2782}
2783
2784void x87_fistp_m32int(i386_state *cpustate, UINT8 modrm)
2785{
2786   INT32 m32int;
2787
2788   if (X87_IS_ST_EMPTY(0))
2789   {
2790      x87_set_stack_underflow(cpustate);
2791      m32int = 0x80000000;
2792   }
2793   else
2794   {
2795      floatx80 fx80 = floatx80_round_to_int(ST(0));
2796
2797      floatx80 lowerLim = int32_to_floatx80(0x80000000);
2798      floatx80 upperLim = int32_to_floatx80(0x7fffffff);
2799
2800      cpustate->x87_sw &= ~X87_SW_C1;
2801
2802      if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim))
2803         m32int = floatx80_to_int32(fx80);
2804      else
2805         m32int = 0x80000000;
2806   }
2807
2808   if (x87_check_exceptions(cpustate))
2809   {
2810      UINT32 ea = GetEA(cpustate, modrm);
2811      WRITE32(cpustate, ea, m32int);
2812      x87_inc_stack(cpustate);
2813   }
2814
2815   CYCLES(cpustate, 29);
2816}
2817
2818void x87_fistp_m64int(i386_state *cpustate, UINT8 modrm)
2819{
2820   INT64 m64int;
2821
2822   if (X87_IS_ST_EMPTY(0))
2823   {
2824      x87_set_stack_underflow(cpustate);
2825      m64int = U64(0x8000000000000000);
2826   }
2827   else
2828   {
2829      floatx80 fx80 = floatx80_round_to_int(ST(0));
2830
2831      floatx80 lowerLim = int64_to_floatx80(U64(0x8000000000000000));
2832      floatx80 upperLim = int64_to_floatx80(U64(0x7fffffffffffffff));
2833
2834      cpustate->x87_sw &= ~X87_SW_C1;
2835
2836      if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim))
2837         m64int = floatx80_to_int64(fx80);
2838      else
2839         m64int = U64(0x8000000000000000);
2840   }
2841
2842   if (x87_check_exceptions(cpustate))
2843   {
2844      UINT32 ea = GetEA(cpustate, modrm);
2845      WRITE64(cpustate, ea, m64int);
2846      x87_inc_stack(cpustate);
2847   }
2848
2849   CYCLES(cpustate, 29);
2850}
2851
2852void x87_fbstp(i386_state *cpustate, UINT8 modrm)
2853{
2854   floatx80 result;
2855
2856   if (X87_IS_ST_EMPTY(0))
2857   {
2858      x87_set_stack_underflow(cpustate);
2859      result = fx80_inan;
2860   }
2861   else
2862   {
2863      UINT64 u64 = floatx80_to_int64(floatx80_abs(ST(0)));
2864      result.low = 0;
2865
2866      for (int i = 0; i < 64; i += 4)
2867      {
2868         result.low += (u64 % 10) << i;
2869         u64 /= 10;
2870      }
2871
2872      result.high = (u64 % 10);
2873      result.high += ((u64 / 10) % 10) << 4;
2874      result.high |= ST(0).high & 0x8000;
2875   }
2876
2877   if (x87_check_exceptions(cpustate))
2878   {
2879      UINT32 ea = GetEA(cpustate, modrm);
2880      WRITE80(cpustate, ea, result);
2881      x87_inc_stack(cpustate);
2882   }
2883
2884   CYCLES(cpustate, 175);
2885}
2886
2887
2888/*************************************
2889 *
2890 * Constant load
2891 *
2892 *************************************/
2893
2894void x87_fld1(i386_state *cpustate, UINT8 modrm)
2895{
2896   floatx80 value;
2897   int tag;
2898
2899   if (x87_dec_stack(cpustate))
2900   {
2901      cpustate->x87_sw &= ~X87_SW_C1;
2902      value = fx80_one;
2903      tag = X87_TW_VALID;
2904   }
2905   else
2906   {
2907      value = fx80_inan;
2908      tag = X87_TW_SPECIAL;
2909   }
2910
2911   if (x87_check_exceptions(cpustate))
2912   {
2913      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
2914      x87_write_stack(cpustate, 0, value, FALSE);
2915   }
2916
2917   CYCLES(cpustate, 4);
2918}
2919
2920void x87_fldl2t(i386_state *cpustate, UINT8 modrm)
2921{
2922   floatx80 value;
2923   int tag;
2924
2925   if (x87_dec_stack(cpustate))
2926   {
2927      tag = X87_TW_VALID;
2928      value.high = 0x4000;
2929
2930      if (X87_RC == X87_CW_RC_UP)
2931         value.low =  U64(0xd49a784bcd1b8aff);
2932      else
2933         value.low = U64(0xd49a784bcd1b8afe);
2934
2935      cpustate->x87_sw &= ~X87_SW_C1;
2936   }
2937   else
2938   {
2939      value = fx80_inan;
2940      tag = X87_TW_SPECIAL;
2941   }
2942
2943   if (x87_check_exceptions(cpustate))
2944   {
2945      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
2946      x87_write_stack(cpustate, 0, value, FALSE);
2947   }
2948
2949   CYCLES(cpustate, 8);
2950}
2951
2952void x87_fldl2e(i386_state *cpustate, UINT8 modrm)
2953{
2954   floatx80 value;
2955   int tag;
2956
2957   if (x87_dec_stack(cpustate))
2958   {
2959      int rc = X87_RC;
2960      tag = X87_TW_VALID;
2961      value.high = 0x3fff;
2962
2963      if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST)
2964         value.low = U64(0xb8aa3b295c17f0bc);
2965      else
2966         value.low = U64(0xb8aa3b295c17f0bb);
2967
2968      cpustate->x87_sw &= ~X87_SW_C1;
2969   }
2970   else
2971   {
2972      value = fx80_inan;
2973      tag = X87_TW_SPECIAL;
2974   }
2975
2976   if (x87_check_exceptions(cpustate))
2977   {
2978      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
2979      x87_write_stack(cpustate, 0, value, FALSE);
2980   }
2981
2982   CYCLES(cpustate, 8);
2983}
2984
2985void x87_fldpi(i386_state *cpustate, UINT8 modrm)
2986{
2987   floatx80 value;
2988   int tag;
2989
2990   if (x87_dec_stack(cpustate))
2991   {
2992      int rc = X87_RC;
2993      tag = X87_TW_VALID;
2994      value.high = 0x4000;
2995
2996      if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST)
2997         value.low = U64(0xc90fdaa22168c235);
2998      else
2999         value.low = U64(0xc90fdaa22168c234);
3000
3001      cpustate->x87_sw &= ~X87_SW_C1;
3002   }
3003   else
3004   {
3005      value = fx80_inan;
3006      tag = X87_TW_SPECIAL;
3007   }
3008
3009   if (x87_check_exceptions(cpustate))
3010   {
3011      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
3012      x87_write_stack(cpustate, 0, value, FALSE);
3013   }
3014
3015   CYCLES(cpustate, 8);
3016}
3017
3018void x87_fldlg2(i386_state *cpustate, UINT8 modrm)
3019{
3020   floatx80 value;
3021   int tag;
3022
3023   if (x87_dec_stack(cpustate))
3024   {
3025      int rc = X87_RC;
3026      tag = X87_TW_VALID;
3027      value.high = 0x3ffd;
3028
3029      if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST)
3030         value.low = U64(0x9a209a84fbcff799);
3031      else
3032         value.low = U64(0x9a209a84fbcff798);
3033
3034      cpustate->x87_sw &= ~X87_SW_C1;
3035   }
3036   else
3037   {
3038      value = fx80_inan;
3039      tag = X87_TW_SPECIAL;
3040   }
3041
3042   if (x87_check_exceptions(cpustate))
3043   {
3044      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
3045      x87_write_stack(cpustate, 0, value, FALSE);
3046   }
3047
3048   CYCLES(cpustate, 8);
3049}
3050
3051void x87_fldln2(i386_state *cpustate, UINT8 modrm)
3052{
3053   floatx80 value;
3054   int tag;
3055
3056   if (x87_dec_stack(cpustate))
3057   {
3058      int rc = X87_RC;
3059      tag = X87_TW_VALID;
3060      value.high = 0x3ffe;
3061
3062      if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST)
3063         value.low = U64(0xb17217f7d1cf79ac);
3064      else
3065         value.low = U64(0xb17217f7d1cf79ab);
3066
3067      cpustate->x87_sw &= ~X87_SW_C1;
3068   }
3069   else
3070   {
3071      value = fx80_inan;
3072      tag = X87_TW_SPECIAL;
3073   }
3074
3075   if (x87_check_exceptions(cpustate))
3076   {
3077      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
3078      x87_write_stack(cpustate, 0, value, FALSE);
3079   }
3080
3081   CYCLES(cpustate, 8);
3082}
3083
3084void x87_fldz(i386_state *cpustate, UINT8 modrm)
3085{
3086   floatx80 value;
3087   int tag;
3088
3089   if (x87_dec_stack(cpustate))
3090   {
3091      value = fx80_zero;
3092      tag = X87_TW_ZERO;
3093      cpustate->x87_sw &= ~X87_SW_C1;
3094   }
3095   else
3096   {
3097      value = fx80_inan;
3098      tag = X87_TW_SPECIAL;
3099   }
3100
3101   if (x87_check_exceptions(cpustate))
3102   {
3103      x87_set_tag(cpustate, ST_TO_PHYS(0), tag);
3104      x87_write_stack(cpustate, 0, value, FALSE);
3105   }
3106
3107   CYCLES(cpustate, 4);
3108}
3109
3110
3111/*************************************
3112 *
3113 * Miscellaneous
3114 *
3115 *************************************/
3116
3117void x87_fnop(i386_state *cpustate, UINT8 modrm)
3118{
3119   CYCLES(cpustate, 3);
3120}
3121
3122void x87_fchs(i386_state *cpustate, UINT8 modrm)
3123{
3124   floatx80 value;
3125
3126   if (X87_IS_ST_EMPTY(0))
3127   {
3128      x87_set_stack_underflow(cpustate);
3129      value = fx80_inan;
3130   }
3131   else
3132   {
3133      cpustate->x87_sw &= ~X87_SW_C1;
3134
3135      value = ST(0);
3136      value.high ^= 0x8000;
3137   }
3138
3139   if (x87_check_exceptions(cpustate))
3140      x87_write_stack(cpustate, 0, value, FALSE);
3141
3142   CYCLES(cpustate, 6);
3143}
3144
3145void x87_fabs(i386_state *cpustate, UINT8 modrm)
3146{
3147   floatx80 value;
3148
3149   if (X87_IS_ST_EMPTY(0))
3150   {
3151      x87_set_stack_underflow(cpustate);
3152      value = fx80_inan;
3153   }
3154   else
3155   {
3156      cpustate->x87_sw &= ~X87_SW_C1;
3157
3158      value = ST(0);
3159      value.high &= 0x7fff;
3160   }
3161
3162   if (x87_check_exceptions(cpustate))
3163      x87_write_stack(cpustate, 0, value, FALSE);
3164
3165   CYCLES(cpustate, 6);
3166}
3167
3168void x87_fscale(i386_state *cpustate, UINT8 modrm)
3169{
3170   floatx80 value;
3171
3172   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
3173   {
3174      x87_set_stack_underflow(cpustate);
3175      value = fx80_inan;
3176   }
3177   else
3178   {
3179      cpustate->x87_sw &= ~X87_SW_C1;
3180      value = ST(0);
3181
3182      // Set the rounding mode to truncate
3183      UINT16 old_cw = cpustate->x87_cw;
3184      UINT16 new_cw = (old_cw & ~(X87_CW_RC_MASK << X87_CW_RC_SHIFT)) | (X87_CW_RC_ZERO << X87_CW_RC_SHIFT);
3185      x87_write_cw(cpustate, new_cw);
3186
3187      // Interpret ST(1) as an integer
3188      UINT32 st1 = floatx80_to_int32(floatx80_round_to_int(ST(1)));
3189
3190      // Restore the rounding mode
3191      x87_write_cw(cpustate, old_cw);
3192
3193      // Get the unbiased exponent of ST(0)
3194      INT16 exp = (ST(0).high & 0x7fff) - 0x3fff;
3195
3196      // Calculate the new exponent
3197      exp = (exp + st1 + 0x3fff) & 0x7fff;
3198
3199      // Write it back
3200      value.high = (value.high & ~0x7fff) + exp;
3201   }
3202
3203   if (x87_check_exceptions(cpustate))
3204      x87_write_stack(cpustate, 0, value, FALSE);
3205
3206   CYCLES(cpustate, 31);
3207}
3208
3209void x87_frndint(i386_state *cpustate, UINT8 modrm)
3210{
3211   floatx80 value;
3212
3213   if (X87_IS_ST_EMPTY(0))
3214   {
3215      x87_set_stack_underflow(cpustate);
3216      value = fx80_inan;
3217   }
3218   else
3219   {
3220      cpustate->x87_sw &= ~X87_SW_C1;
3221
3222      value = floatx80_round_to_int(ST(0));
3223   }
3224
3225   if (x87_check_exceptions(cpustate))
3226      x87_write_stack(cpustate, 0, value, TRUE);
3227
3228   CYCLES(cpustate, 21);
3229}
3230
3231void x87_fxtract(i386_state *cpustate, UINT8 modrm)
3232{
3233   floatx80 sig80, exp80;
3234
3235   if (X87_IS_ST_EMPTY(0))
3236   {
3237      x87_set_stack_underflow(cpustate);
3238      sig80 = exp80 = fx80_inan;
3239   }
3240   else if (!X87_IS_ST_EMPTY(7))
3241   {
3242      x87_set_stack_overflow(cpustate);
3243      sig80 = exp80 = fx80_inan;
3244   }
3245   else
3246   {
3247      floatx80 value = ST(0);
3248
3249      if (floatx80_eq(value, fx80_zero))
3250      {
3251         cpustate->x87_sw |= X87_SW_ZE;
3252
3253         exp80 = fx80_ninf;
3254         sig80 = fx80_zero;
3255      }
3256      else
3257      {
3258         // Extract the unbiased exponent
3259         exp80 = int32_to_floatx80((value.high & 0x7fff) - 0x3fff);
3260
3261         // For the significand, replicate the original value and set its true exponent to 0.
3262         sig80 = value;
3263         sig80.high &= ~0x7fff;
3264         sig80.high |=  0x3fff;
3265      }
3266   }
3267
3268   if (x87_check_exceptions(cpustate))
3269   {
3270      x87_write_stack(cpustate, 0, exp80, TRUE);
3271      x87_dec_stack(cpustate);
3272      x87_write_stack(cpustate, 0, sig80, TRUE);
3273   }
3274
3275   CYCLES(cpustate, 21);
3276}
3277
3278/*************************************
3279 *
3280 * Comparison
3281 *
3282 *************************************/
3283
3284void x87_ftst(i386_state *cpustate, UINT8 modrm)
3285{
3286   if (X87_IS_ST_EMPTY(0))
3287   {
3288      x87_set_stack_underflow(cpustate);
3289      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3290   }
3291   else
3292   {
3293      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3294
3295      if (floatx80_is_nan(ST(0)))
3296      {
3297         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3298         cpustate->x87_sw |= X87_SW_IE;
3299      }
3300      else
3301      {
3302         if (floatx80_eq(ST(0), fx80_zero))
3303            cpustate->x87_sw |= X87_SW_C3;
3304
3305         if (floatx80_lt(ST(0), fx80_zero))
3306            cpustate->x87_sw |= X87_SW_C0;
3307      }
3308   }
3309
3310   x87_check_exceptions(cpustate);
3311
3312   CYCLES(cpustate, 4);
3313}
3314
3315void x87_fxam(i386_state *cpustate, UINT8 modrm)
3316{
3317   floatx80 value = ST(0);
3318
3319   cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3320
3321   // TODO: Unsupported and denormal values
3322   if (X87_IS_ST_EMPTY(0))
3323   {
3324      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C0;
3325   }
3326   else if (floatx80_is_zero(value))
3327   {
3328      cpustate->x87_sw |= X87_SW_C3;
3329   }
3330   if (floatx80_is_nan(value))
3331   {
3332      cpustate->x87_sw |= X87_SW_C0;
3333   }
3334   else if (floatx80_is_inf(value))
3335   {
3336      cpustate->x87_sw |= X87_SW_C2 | X87_SW_C0;
3337   }
3338   else
3339   {
3340      cpustate->x87_sw |= X87_SW_C2;
3341   }
3342
3343   if (value.high & 0x8000)
3344      cpustate->x87_sw |= X87_SW_C1;
3345
3346   CYCLES(cpustate, 8);
3347}
3348
3349void x87_ficom_m16int(i386_state *cpustate, UINT8 modrm)
3350{
3351   if (X87_IS_ST_EMPTY(0))
3352   {
3353      x87_set_stack_underflow(cpustate);
3354      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3355   }
3356   else
3357   {
3358      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3359
3360      UINT32 ea = GetEA(cpustate, modrm);
3361      INT16 m16int = READ16(cpustate, ea);
3362
3363      floatx80 a = ST(0);
3364      floatx80 b = int32_to_floatx80(m16int);
3365
3366      if (floatx80_is_nan(a))
3367      {
3368         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3369         cpustate->x87_sw |= X87_SW_IE;
3370      }
3371      else
3372      {
3373         if (floatx80_eq(a, b))
3374            cpustate->x87_sw |= X87_SW_C3;
3375
3376         if (floatx80_lt(a, b))
3377            cpustate->x87_sw |= X87_SW_C0;
3378      }
3379   }
3380
3381   x87_check_exceptions(cpustate);
3382
3383   CYCLES(cpustate, 16);
3384}
3385
3386void x87_ficom_m32int(i386_state *cpustate, UINT8 modrm)
3387{
3388   if (X87_IS_ST_EMPTY(0))
3389   {
3390      x87_set_stack_underflow(cpustate);
3391      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3392   }
3393   else
3394   {
3395      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3396
3397      UINT32 ea = GetEA(cpustate, modrm);
3398      INT32 m32int = READ32(cpustate, ea);
3399
3400      floatx80 a = ST(0);
3401      floatx80 b = int32_to_floatx80(m32int);
3402
3403      if (floatx80_is_nan(a))
3404      {
3405         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3406         cpustate->x87_sw |= X87_SW_IE;
3407      }
3408      else
3409      {
3410         if (floatx80_eq(a, b))
3411            cpustate->x87_sw |= X87_SW_C3;
3412
3413         if (floatx80_lt(a, b))
3414            cpustate->x87_sw |= X87_SW_C0;
3415      }
3416   }
3417
3418   x87_check_exceptions(cpustate);
3419
3420   CYCLES(cpustate, 15);
3421}
3422
3423void x87_ficomp_m16int(i386_state *cpustate, UINT8 modrm)
3424{
3425   if (X87_IS_ST_EMPTY(0))
3426   {
3427      x87_set_stack_underflow(cpustate);
3428      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3429   }
3430   else
3431   {
3432      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3433
3434      UINT32 ea = GetEA(cpustate, modrm);
3435      INT16 m16int = READ16(cpustate, ea);
3436
3437      floatx80 a = ST(0);
3438      floatx80 b = int32_to_floatx80(m16int);
3439
3440      if (floatx80_is_nan(a))
3441      {
3442         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3443         cpustate->x87_sw |= X87_SW_IE;
3444      }
3445      else
3446      {
3447         if (floatx80_eq(a, b))
3448            cpustate->x87_sw |= X87_SW_C3;
3449
3450         if (floatx80_lt(a, b))
3451            cpustate->x87_sw |= X87_SW_C0;
3452      }
3453   }
3454
3455   if (x87_check_exceptions(cpustate))
3456      x87_inc_stack(cpustate);
3457
3458   CYCLES(cpustate, 16);
3459}
3460
3461void x87_ficomp_m32int(i386_state *cpustate, UINT8 modrm)
3462{
3463   if (X87_IS_ST_EMPTY(0))
3464   {
3465      x87_set_stack_underflow(cpustate);
3466      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3467   }
3468   else
3469   {
3470      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3471
3472      UINT32 ea = GetEA(cpustate, modrm);
3473      INT32 m32int = READ32(cpustate, ea);
3474
3475      floatx80 a = ST(0);
3476      floatx80 b = int32_to_floatx80(m32int);
3477
3478      if (floatx80_is_nan(a))
3479      {
3480         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3481         cpustate->x87_sw |= X87_SW_IE;
3482      }
3483      else
3484      {
3485         if (floatx80_eq(a, b))
3486            cpustate->x87_sw |= X87_SW_C3;
3487
3488         if (floatx80_lt(a, b))
3489            cpustate->x87_sw |= X87_SW_C0;
3490      }
3491   }
3492
3493   if (x87_check_exceptions(cpustate))
3494      x87_inc_stack(cpustate);
3495
3496   CYCLES(cpustate, 15);
3497}
3498
3499
3500void x87_fcom_m32real(i386_state *cpustate, UINT8 modrm)
3501{
3502   if (X87_IS_ST_EMPTY(0))
3503   {
3504      x87_set_stack_underflow(cpustate);
3505      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3506   }
3507   else
3508   {
3509      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3510
3511      UINT32 ea = GetEA(cpustate, modrm);
3512      UINT32 m32real = READ32(cpustate, ea);
3513
3514      floatx80 a = ST(0);
3515      floatx80 b = float32_to_floatx80(m32real);
3516
3517      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3518      {
3519         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3520         cpustate->x87_sw |= X87_SW_IE;
3521      }
3522      else
3523      {
3524         if (floatx80_eq(a, b))
3525            cpustate->x87_sw |= X87_SW_C3;
3526
3527         if (floatx80_lt(a, b))
3528            cpustate->x87_sw |= X87_SW_C0;
3529      }
3530   }
3531
3532   x87_check_exceptions(cpustate);
3533
3534   CYCLES(cpustate, 4);
3535}
3536
3537void x87_fcom_m64real(i386_state *cpustate, UINT8 modrm)
3538{
3539   if (X87_IS_ST_EMPTY(0))
3540   {
3541      x87_set_stack_underflow(cpustate);
3542      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3543   }
3544   else
3545   {
3546      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3547
3548      UINT32 ea = GetEA(cpustate, modrm);
3549      UINT64 m64real = READ64(cpustate, ea);
3550
3551      floatx80 a = ST(0);
3552      floatx80 b = float64_to_floatx80(m64real);
3553
3554      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3555      {
3556         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3557         cpustate->x87_sw |= X87_SW_IE;
3558      }
3559      else
3560      {
3561         if (floatx80_eq(a, b))
3562            cpustate->x87_sw |= X87_SW_C3;
3563
3564         if (floatx80_lt(a, b))
3565            cpustate->x87_sw |= X87_SW_C0;
3566      }
3567   }
3568
3569   x87_check_exceptions(cpustate);
3570
3571   CYCLES(cpustate, 4);
3572}
3573
3574void x87_fcom_sti(i386_state *cpustate, UINT8 modrm)
3575{
3576   int i = modrm & 7;
3577
3578   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
3579   {
3580      x87_set_stack_underflow(cpustate);
3581      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3582   }
3583   else
3584   {
3585      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3586
3587      floatx80 a = ST(0);
3588      floatx80 b = ST(i);
3589
3590      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3591      {
3592         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3593         cpustate->x87_sw |= X87_SW_IE;
3594      }
3595      else
3596      {
3597         if (floatx80_eq(a, b))
3598            cpustate->x87_sw |= X87_SW_C3;
3599
3600         if (floatx80_lt(a, b))
3601            cpustate->x87_sw |= X87_SW_C0;
3602      }
3603   }
3604
3605   x87_check_exceptions(cpustate);
3606
3607   CYCLES(cpustate, 4);
3608}
3609
3610void x87_fcomp_m32real(i386_state *cpustate, UINT8 modrm)
3611{
3612   if (X87_IS_ST_EMPTY(0))
3613   {
3614      x87_set_stack_underflow(cpustate);
3615      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3616   }
3617   else
3618   {
3619      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3620
3621      UINT32 ea = GetEA(cpustate, modrm);
3622      UINT32 m32real = READ32(cpustate, ea);
3623
3624      floatx80 a = ST(0);
3625      floatx80 b = float32_to_floatx80(m32real);
3626
3627      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3628      {
3629         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3630         cpustate->x87_sw |= X87_SW_IE;
3631      }
3632      else
3633      {
3634         if (floatx80_eq(a, b))
3635            cpustate->x87_sw |= X87_SW_C3;
3636
3637         if (floatx80_lt(a, b))
3638            cpustate->x87_sw |= X87_SW_C0;
3639      }
3640   }
3641
3642   if (x87_check_exceptions(cpustate))
3643      x87_inc_stack(cpustate);
3644
3645   CYCLES(cpustate, 4);
3646}
3647
3648void x87_fcomp_m64real(i386_state *cpustate, UINT8 modrm)
3649{
3650   if (X87_IS_ST_EMPTY(0))
3651   {
3652      x87_set_stack_underflow(cpustate);
3653      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3654   }
3655   else
3656   {
3657      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3658
3659      UINT32 ea = GetEA(cpustate, modrm);
3660      UINT64 m64real = READ64(cpustate, ea);
3661
3662      floatx80 a = ST(0);
3663      floatx80 b = float64_to_floatx80(m64real);
3664
3665      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3666      {
3667         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3668         cpustate->x87_sw |= X87_SW_IE;
3669      }
3670      else
3671      {
3672         if (floatx80_eq(a, b))
3673            cpustate->x87_sw |= X87_SW_C3;
3674
3675         if (floatx80_lt(a, b))
3676            cpustate->x87_sw |= X87_SW_C0;
3677      }
3678   }
3679
3680   if (x87_check_exceptions(cpustate))
3681      x87_inc_stack(cpustate);
3682
3683   CYCLES(cpustate, 4);
3684}
3685
3686void x87_fcomp_sti(i386_state *cpustate, UINT8 modrm)
3687{
3688   int i = modrm & 7;
3689
3690   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
3691   {
3692      x87_set_stack_underflow(cpustate);
3693      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3694   }
3695   else
3696   {
3697      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3698
3699      floatx80 a = ST(0);
3700      floatx80 b = ST(i);
3701
3702      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3703      {
3704         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3705         cpustate->x87_sw |= X87_SW_IE;
3706      }
3707      else
3708      {
3709         if (floatx80_eq(a, b))
3710            cpustate->x87_sw |= X87_SW_C3;
3711
3712         if (floatx80_lt(a, b))
3713            cpustate->x87_sw |= X87_SW_C0;
3714      }
3715   }
3716
3717   if (x87_check_exceptions(cpustate))
3718      x87_inc_stack(cpustate);
3719
3720   CYCLES(cpustate, 4);
3721}
3722
3723void x87_fcompp(i386_state *cpustate, UINT8 modrm)
3724{
3725   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
3726   {
3727      x87_set_stack_underflow(cpustate);
3728      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3729   }
3730   else
3731   {
3732      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3733
3734      floatx80 a = ST(0);
3735      floatx80 b = ST(1);
3736
3737      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3738      {
3739         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3740         cpustate->x87_sw |= X87_SW_IE;
3741      }
3742      else
3743      {
3744         if (floatx80_eq(a, b))
3745            cpustate->x87_sw |= X87_SW_C3;
3746
3747         if (floatx80_lt(a, b))
3748            cpustate->x87_sw |= X87_SW_C0;
3749      }
3750   }
3751
3752   if (x87_check_exceptions(cpustate))
3753   {
3754      x87_inc_stack(cpustate);
3755      x87_inc_stack(cpustate);
3756   }
3757
3758   CYCLES(cpustate, 5);
3759}
3760
3761
3762/*************************************
3763 *
3764 * Unordererd comparison
3765 *
3766 *************************************/
3767
3768void x87_fucom_sti(i386_state *cpustate, UINT8 modrm)
3769{
3770   int i = modrm & 7;
3771
3772   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
3773   {
3774      x87_set_stack_underflow(cpustate);
3775      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3776   }
3777   else
3778   {
3779      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3780
3781      floatx80 a = ST(0);
3782      floatx80 b = ST(i);
3783
3784      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3785      {
3786         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3787
3788         if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
3789            cpustate->x87_sw |= X87_SW_IE;
3790      }
3791      else
3792      {
3793         if (floatx80_eq(a, b))
3794            cpustate->x87_sw |= X87_SW_C3;
3795
3796         if (floatx80_lt(a, b))
3797            cpustate->x87_sw |= X87_SW_C0;
3798      }
3799   }
3800
3801   x87_check_exceptions(cpustate);
3802
3803   CYCLES(cpustate, 4);
3804}
3805
3806void x87_fucomp_sti(i386_state *cpustate, UINT8 modrm)
3807{
3808   int i = modrm & 7;
3809
3810   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i))
3811   {
3812      x87_set_stack_underflow(cpustate);
3813      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3814   }
3815   else
3816   {
3817      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3818
3819      floatx80 a = ST(0);
3820      floatx80 b = ST(i);
3821
3822      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3823      {
3824         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3825
3826         if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
3827            cpustate->x87_sw |= X87_SW_IE;
3828      }
3829      else
3830      {
3831         if (floatx80_eq(a, b))
3832            cpustate->x87_sw |= X87_SW_C3;
3833
3834         if (floatx80_lt(a, b))
3835            cpustate->x87_sw |= X87_SW_C0;
3836      }
3837   }
3838
3839   if (x87_check_exceptions(cpustate))
3840      x87_inc_stack(cpustate);
3841
3842   CYCLES(cpustate, 4);
3843}
3844
3845void x87_fucompp(i386_state *cpustate, UINT8 modrm)
3846{
3847   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
3848   {
3849      x87_set_stack_underflow(cpustate);
3850      cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0;
3851   }
3852   else
3853   {
3854      cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0);
3855
3856      floatx80 a = ST(0);
3857      floatx80 b = ST(1);
3858
3859      if (floatx80_is_nan(a) || floatx80_is_nan(b))
3860      {
3861         cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3;
3862
3863         if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
3864            cpustate->x87_sw |= X87_SW_IE;
3865      }
3866      else
3867      {
3868         if (floatx80_eq(a, b))
3869            cpustate->x87_sw |= X87_SW_C3;
3870
3871         if (floatx80_lt(a, b))
3872            cpustate->x87_sw |= X87_SW_C0;
3873      }
3874   }
3875
3876   if (x87_check_exceptions(cpustate))
3877   {
3878      x87_inc_stack(cpustate);
3879      x87_inc_stack(cpustate);
3880   }
3881
3882   CYCLES(cpustate, 4);
3883}
3884
3885
3886/*************************************
3887 *
3888 * Control
3889 *
3890 *************************************/
3891
3892void x87_fdecstp(i386_state *cpustate, UINT8 modrm)
3893{
3894   cpustate->x87_sw &= ~X87_SW_C1;
3895
3896   x87_dec_stack(cpustate);
3897   x87_check_exceptions(cpustate);
3898
3899   CYCLES(cpustate, 3);
3900}
3901
3902void x87_fincstp(i386_state *cpustate, UINT8 modrm)
3903{
3904   cpustate->x87_sw &= ~X87_SW_C1;
3905
3906   x87_inc_stack(cpustate);
3907   x87_check_exceptions(cpustate);
3908
3909   CYCLES(cpustate, 3);
3910}
3911
3912void x87_fclex(i386_state *cpustate, UINT8 modrm)
3913{
3914   cpustate->x87_sw &= ~0x80ff;
3915
3916   CYCLES(cpustate, 7);
3917}
3918
3919void x87_ffree(i386_state *cpustate, UINT8 modrm)
3920{
3921   x87_set_tag(cpustate, ST_TO_PHYS(modrm & 7), X87_TW_EMPTY);
3922
3923   CYCLES(cpustate, 3);
3924}
3925
3926void x87_finit(i386_state *cpustate, UINT8 modrm)
3927{
3928   x87_reset(cpustate);
3929
3930   CYCLES(cpustate, 17);
3931}
3932
3933void x87_fldcw(i386_state *cpustate, UINT8 modrm)
3934{
3935   UINT32 ea = GetEA(cpustate, modrm);
3936   UINT16 cw = READ16(cpustate, ea);
3937
3938   x87_write_cw(cpustate, cw);
3939
3940   x87_check_exceptions(cpustate);
3941
3942   CYCLES(cpustate, 4);
3943}
3944
3945void x87_fstcw(i386_state *cpustate, UINT8 modrm)
3946{
3947   UINT32 ea = GetEA(cpustate, modrm);
3948   WRITE16(cpustate, ea, cpustate->x87_cw);
3949
3950   CYCLES(cpustate, 3);
3951}
3952
3953void x87_fldenv(i386_state *cpustate, UINT8 modrm)
3954{
3955   // TODO: Pointers and selectors
3956   UINT32 ea = GetEA(cpustate, modrm);
3957
3958   if (cpustate->operand_size)
3959   {
3960      // 32-bit real/protected mode
3961      x87_write_cw(cpustate, READ16(cpustate, ea));
3962      cpustate->x87_sw = READ16(cpustate, ea + 4);
3963      cpustate->x87_tw = READ16(cpustate, ea + 8);
3964   }
3965   else
3966   {
3967      // 16-bit real/protected mode
3968      x87_write_cw(cpustate, READ16(cpustate, ea));
3969      cpustate->x87_sw = READ16(cpustate, ea + 2);
3970      cpustate->x87_tw = READ16(cpustate, ea + 4);
3971   }
3972
3973   x87_check_exceptions(cpustate);
3974
3975   CYCLES(cpustate,(cpustate->cr[0] & 1) ? 34 : 44);
3976}
3977
3978void x87_fstenv(i386_state *cpustate, UINT8 modrm)
3979{
3980   UINT32 ea = GetEA(cpustate, modrm);
3981
3982   // TODO: Pointers and selectors
3983   switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
3984   {
3985      case 0: // 16-bit real mode
3986         WRITE16(cpustate, ea + 0, cpustate->x87_cw);
3987         WRITE16(cpustate, ea + 2, cpustate->x87_sw);
3988         WRITE16(cpustate, ea + 4, cpustate->x87_tw);
3989//         WRITE16(cpustate, ea + 6, cpustate->fpu_inst_ptr & 0xffff);
3990//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
3991//         WRITE16(cpustate, ea + 10, cpustate->fpu_data_ptr & 0xffff);
3992//         WRITE16(cpustate, ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
3993         break;
3994      case 1: // 16-bit protected mode
3995         WRITE16(cpustate,ea + 0, cpustate->x87_cw);
3996         WRITE16(cpustate,ea + 2, cpustate->x87_sw);
3997         WRITE16(cpustate,ea + 4, cpustate->x87_tw);
3998//         WRITE16(cpustate,ea + 6, cpustate->fpu_inst_ptr & 0xffff);
3999//         WRITE16(cpustate,ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4000//         WRITE16(cpustate,ea + 10, cpustate->fpu_data_ptr & 0xffff);
4001//         WRITE16(cpustate,ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
4002         break;
4003      case 2: // 32-bit real mode
4004         WRITE16(cpustate, ea + 0, cpustate->x87_cw);
4005         WRITE16(cpustate, ea + 4, cpustate->x87_sw);
4006         WRITE16(cpustate, ea + 8, cpustate->x87_tw);
4007//         WRITE16(cpustate, ea + 12, cpustate->fpu_inst_ptr & 0xffff);
4008//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4009//         WRITE16(cpustate, ea + 20, cpustate->fpu_data_ptr & 0xffff);
4010//         WRITE16(cpustate, ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4011//         WRITE32(cpustate, ea + 24, (cpustate->fpu_data_ptr >> 16) << 12);
4012         break;
4013      case 3: // 32-bit protected mode
4014         WRITE16(cpustate, ea + 0,  cpustate->x87_cw);
4015         WRITE16(cpustate, ea + 4,  cpustate->x87_sw);
4016         WRITE16(cpustate, ea + 8,  cpustate->x87_tw);
4017//         WRITE32(cpustate, ea + 12, cpustate->fpu_inst_ptr);
4018//         WRITE32(cpustate, ea + 16, cpustate->fpu_opcode);
4019//         WRITE32(cpustate, ea + 20, cpustate->fpu_data_ptr);
4020//         WRITE32(cpustate, ea + 24, cpustate->fpu_inst_ptr);
4021         break;
4022   }
4023
4024   CYCLES(cpustate,(cpustate->cr[0] & 1) ? 56 : 67);
4025}
4026
4027void x87_fsave(i386_state *cpustate, UINT8 modrm)
4028{
4029   UINT32 ea = GetEA(cpustate, modrm);
4030
4031   // TODO: Pointers and selectors
4032   switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
4033   {
4034      case 0: // 16-bit real mode
4035         WRITE16(cpustate, ea + 0, cpustate->x87_cw);
4036         WRITE16(cpustate, ea + 2, cpustate->x87_sw);
4037         WRITE16(cpustate, ea + 4, cpustate->x87_tw);
4038//         WRITE16(cpustate, ea + 6, cpustate->fpu_inst_ptr & 0xffff);
4039//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4040//         WRITE16(cpustate, ea + 10, cpustate->fpu_data_ptr & 0xffff);
4041//         WRITE16(cpustate, ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
4042         ea += 14;
4043         break;
4044      case 1: // 16-bit protected mode
4045         WRITE16(cpustate,ea + 0, cpustate->x87_cw);
4046         WRITE16(cpustate,ea + 2, cpustate->x87_sw);
4047         WRITE16(cpustate,ea + 4, cpustate->x87_tw);
4048//         WRITE16(cpustate,ea + 6, cpustate->fpu_inst_ptr & 0xffff);
4049//         WRITE16(cpustate,ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4050//         WRITE16(cpustate,ea + 10, cpustate->fpu_data_ptr & 0xffff);
4051//         WRITE16(cpustate,ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
4052         ea += 14;
4053         break;
4054      case 2: // 32-bit real mode
4055         WRITE16(cpustate, ea + 0, cpustate->x87_cw);
4056         WRITE16(cpustate, ea + 4, cpustate->x87_sw);
4057         WRITE16(cpustate, ea + 8, cpustate->x87_tw);
4058//         WRITE16(cpustate, ea + 12, cpustate->fpu_inst_ptr & 0xffff);
4059//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4060//         WRITE16(cpustate, ea + 20, cpustate->fpu_data_ptr & 0xffff);
4061//         WRITE16(cpustate, ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4062//         WRITE32(cpustate, ea + 24, (cpustate->fpu_data_ptr >> 16) << 12);
4063         ea += 28;
4064         break;
4065      case 3: // 32-bit protected mode
4066         WRITE16(cpustate, ea + 0,  cpustate->x87_cw);
4067         WRITE16(cpustate, ea + 4,  cpustate->x87_sw);
4068         WRITE16(cpustate, ea + 8,  cpustate->x87_tw);
4069//         WRITE32(cpustate, ea + 12, cpustate->fpu_inst_ptr);
4070//         WRITE32(cpustate, ea + 16, cpustate->fpu_opcode);
4071//         WRITE32(cpustate, ea + 20, cpustate->fpu_data_ptr);
4072//         WRITE32(cpustate, ea + 24, cpustate->fpu_inst_ptr);
4073         ea += 28;
4074         break;
4075   }
4076
4077   for (int i = 0; i < 8; ++i)
4078      x87_write_stack(cpustate, i, READ80(cpustate, ea + i*10), FALSE);
4079
4080   CYCLES(cpustate,(cpustate->cr[0] & 1) ? 56 : 67);
4081}
4082
4083void x87_frstor(i386_state *cpustate, UINT8 modrm)
4084{
4085   UINT32 ea = GetEA(cpustate, modrm);
4086
4087   // TODO: Pointers and selectors
4088   switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
4089   {
4090      case 0: // 16-bit real mode
4091         x87_write_cw(cpustate, READ16(cpustate, ea));
4092         cpustate->x87_sw = READ16(cpustate, ea + 2);
4093         cpustate->x87_tw = READ16(cpustate, ea + 4);
4094//         WRITE16(cpustate, ea + 6, cpustate->fpu_inst_ptr & 0xffff);
4095//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4096//         WRITE16(cpustate, ea + 10, cpustate->fpu_data_ptr & 0xffff);
4097//         WRITE16(cpustate, ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
4098         ea += 14;
4099         break;
4100      case 1: // 16-bit protected mode
4101         x87_write_cw(cpustate, READ16(cpustate, ea));
4102         cpustate->x87_sw = READ16(cpustate, ea + 2);
4103         cpustate->x87_tw = READ16(cpustate, ea + 4);
4104//         WRITE16(cpustate,ea + 6, cpustate->fpu_inst_ptr & 0xffff);
4105//         WRITE16(cpustate,ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4106//         WRITE16(cpustate,ea + 10, cpustate->fpu_data_ptr & 0xffff);
4107//         WRITE16(cpustate,ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4);
4108         ea += 14;
4109         break;
4110      case 2: // 32-bit real mode
4111         x87_write_cw(cpustate, READ16(cpustate, ea));
4112         cpustate->x87_sw = READ16(cpustate, ea + 4);
4113         cpustate->x87_tw = READ16(cpustate, ea + 8);
4114//         WRITE16(cpustate, ea + 12, cpustate->fpu_inst_ptr & 0xffff);
4115//         WRITE16(cpustate, ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4116//         WRITE16(cpustate, ea + 20, cpustate->fpu_data_ptr & 0xffff);
4117//         WRITE16(cpustate, ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
4118//         WRITE32(cpustate, ea + 24, (cpustate->fpu_data_ptr >> 16) << 12);
4119         ea += 28;
4120         break;
4121      case 3: // 32-bit protected mode
4122         x87_write_cw(cpustate, READ16(cpustate, ea));
4123         cpustate->x87_sw = READ16(cpustate, ea + 4);
4124         cpustate->x87_tw = READ16(cpustate, ea + 8);
4125//         WRITE32(cpustate, ea + 12, cpustate->fpu_inst_ptr);
4126//         WRITE32(cpustate, ea + 16, cpustate->fpu_opcode);
4127//         WRITE32(cpustate, ea + 20, cpustate->fpu_data_ptr);
4128//         WRITE32(cpustate, ea + 24, cpustate->fpu_inst_ptr);
4129         ea += 28;
4130         break;
4131   }
4132
4133   for (int i = 0; i < 8; ++i)
4134      WRITE80(cpustate, ea + i*10, ST(i));
4135
4136   CYCLES(cpustate,(cpustate->cr[0] & 1) ? 34 : 44);
4137}
4138
4139void x87_fxch(i386_state *cpustate, UINT8 modrm)
4140{
4141   if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1))
4142      x87_set_stack_underflow(cpustate);
4143
4144   if (x87_check_exceptions(cpustate))
4145   {
4146      floatx80 tmp = ST(0);
4147      ST(0) = ST(1);
4148      ST(1) = tmp;
4149
4150      // Swap the tags
4151      int tag0 = X87_TAG(ST_TO_PHYS(0));
4152      x87_set_tag(cpustate, ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(1)));
4153      x87_set_tag(cpustate, ST_TO_PHYS(1), tag0);
4154   }
4155
4156   CYCLES(cpustate, 4);
4157}
4158
4159void x87_fxch_sti(i386_state *cpustate, UINT8 modrm)
4160{
4161   int i = modrm & 7;
4162
4163   if (X87_IS_ST_EMPTY(0))
4164   {
4165      ST(0) = fx80_inan;
4166      x87_set_tag(cpustate, ST_TO_PHYS(0), X87_TW_SPECIAL);
4167      x87_set_stack_underflow(cpustate);
4168   }
4169   if (X87_IS_ST_EMPTY(i))
4170   {
4171      ST(i) = fx80_inan;
4172      x87_set_tag(cpustate, ST_TO_PHYS(i), X87_TW_SPECIAL);
4173      x87_set_stack_underflow(cpustate);
4174   }
4175
4176   if (x87_check_exceptions(cpustate))
4177   {
4178      floatx80 tmp = ST(0);
4179      ST(0) = ST(i);
4180      ST(i) = tmp;
4181
4182      // Swap the tags
4183      int tag0 = X87_TAG(ST_TO_PHYS(0));
4184      x87_set_tag(cpustate, ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(i)));
4185      x87_set_tag(cpustate, ST_TO_PHYS(i), tag0);
4186   }
4187
4188   CYCLES(cpustate, 4);
4189}
4190
4191void x87_fstsw_ax(i386_state *cpustate, UINT8 modrm)
4192{
4193   REG16(AX) = cpustate->x87_sw;
4194
4195   CYCLES(cpustate, 3);
4196}
4197
4198void x87_fstsw_m2byte(i386_state *cpustate, UINT8 modrm)
4199{
4200   UINT32 ea = GetEA(cpustate, modrm);
4201
4202   WRITE16(cpustate, ea, cpustate->x87_sw);
4203
4204   CYCLES(cpustate, 3);
4205}
4206
4207void x87_invalid(i386_state *cpustate, UINT8 modrm)
4208{
4209   // TODO
4210   fatalerror("x87 invalid instruction (PC:%.4x)", cpustate->pc);
4211}
4212
4213
4214
4215/*************************************
4216 *
4217 * Instruction dispatch
4218 *
4219 *************************************/
4220
4221static void I386OP(x87_group_d8)(i386_state *cpustate)
4222{
4223   UINT8 modrm = FETCH(cpustate);
4224   cpustate->opcode_table_x87_d8[modrm](cpustate, modrm);
4225}
4226
4227static void I386OP(x87_group_d9)(i386_state *cpustate)
4228{
4229   UINT8 modrm = FETCH(cpustate);
4230   cpustate->opcode_table_x87_d9[modrm](cpustate, modrm);
4231}
4232
4233static void I386OP(x87_group_da)(i386_state *cpustate)
4234{
4235   UINT8 modrm = FETCH(cpustate);
4236   cpustate->opcode_table_x87_da[modrm](cpustate, modrm);
4237}
4238
4239static void I386OP(x87_group_db)(i386_state *cpustate)
4240{
4241   UINT8 modrm = FETCH(cpustate);
4242   cpustate->opcode_table_x87_db[modrm](cpustate, modrm);
4243}
4244
4245static void I386OP(x87_group_dc)(i386_state *cpustate)
4246{
4247   UINT8 modrm = FETCH(cpustate);
4248   cpustate->opcode_table_x87_dc[modrm](cpustate, modrm);
4249}
4250
4251static void I386OP(x87_group_dd)(i386_state *cpustate)
4252{
4253   UINT8 modrm = FETCH(cpustate);
4254   cpustate->opcode_table_x87_dd[modrm](cpustate, modrm);
4255}
4256
4257static void I386OP(x87_group_de)(i386_state *cpustate)
4258{
4259   UINT8 modrm = FETCH(cpustate);
4260   cpustate->opcode_table_x87_de[modrm](cpustate, modrm);
4261}
4262
4263static void I386OP(x87_group_df)(i386_state *cpustate)
4264{
4265   UINT8 modrm = FETCH(cpustate);
4266   cpustate->opcode_table_x87_df[modrm](cpustate, modrm);
4267}
4268
4269
4270/*************************************
4271 *
4272 * Opcode table building
4273 *
4274 *************************************/
4275
4276void build_x87_opcode_table_d8(i386_state *cpustate)
4277{
4278   int modrm = 0;
4279
4280   for (modrm = 0; modrm < 0xff; ++modrm)
4281   {
4282      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4283
4284      if (modrm < 0xc0)
4285      {
4286         switch ((modrm >> 3) & 0x7)
14864287         {
1487            ST(modrm & 7).f += ST(0).f;
1488            FPU_POP(cpustate);
1489            CYCLES(cpustate,8);
1490            break;
4288            case 0x00: ptr = x87_fadd_m32real;   break;
4289            case 0x01: ptr = x87_fmul_m32real;   break;
4290            case 0x02: ptr = x87_fcom_m32real;   break;
4291            case 0x03: ptr = x87_fcomp_m32real;   break;
4292            case 0x04: ptr = x87_fsub_m32real;   break;
4293            case 0x05: ptr = x87_fsubr_m32real;   break;
4294            case 0x06: ptr = x87_fdiv_m32real;   break;
4295            case 0x07: ptr = x87_fdivr_m32real;   break;
14914296         }
1492
1493         case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // FMULP
4297      }
4298      else
4299      {
4300         switch (modrm)
14944301         {
1495            ST(modrm & 7).f *= ST(0).f;
1496            FPU_POP(cpustate);
1497            CYCLES(cpustate,16);
1498            break;
4302            case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = x87_fadd_st_sti;   break;
4303            case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = x87_fmul_st_sti;   break;
4304            case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = x87_fcom_sti;      break;
4305            case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = x87_fcomp_sti;   break;
4306            case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = x87_fsub_st_sti;   break;
4307            case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = x87_fsubr_st_sti;   break;
4308            case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = x87_fdiv_st_sti;   break;
4309            case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = x87_fdivr_st_sti;   break;
14994310         }
4311      }
15004312
1501         case 0x19:         // FCOMPP
4313      cpustate->opcode_table_x87_d8[modrm] = ptr;
4314   }
4315}
4316
4317
4318void build_x87_opcode_table_d9(i386_state *cpustate)
4319{
4320   int modrm = 0;
4321
4322   for (modrm = 0; modrm < 0xff; ++modrm)
4323   {
4324      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4325
4326      if (modrm < 0xc0)
4327      {
4328         switch ((modrm >> 3) & 0x7)
15024329         {
1503            cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
1504            if (ST(0).f > ST(1).f)
1505            {
1506               // C3 = 0, C2 = 0, C0 = 0
1507            }
1508            else if (ST(0).f < ST(1).f)
1509            {
1510               cpustate->fpu_status_word |= FPU_C0;
1511            }
1512            else if (ST(0).f == ST(1).f)
1513            {
1514               cpustate->fpu_status_word |= FPU_C3;
1515            }
1516            else
1517            {
1518               // unordered
1519               cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
1520            }
1521            FPU_POP(cpustate);
1522            FPU_POP(cpustate);
1523            CYCLES(cpustate,5);
1524            break;
4330            case 0x00: ptr = x87_fld_m32real;   break;
4331            case 0x02: ptr = x87_fst_m32real;   break;
4332            case 0x03: ptr = x87_fstp_m32real;   break;
4333            case 0x04: ptr = x87_fldenv;      break;
4334            case 0x05: ptr = x87_fldcw;         break;
4335            case 0x06: ptr = x87_fstenv;      break;
4336            case 0x07: ptr = x87_fstcw;         break;
15254337         }
1526
1527         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: // FSUBRP
4338      }
4339      else
4340      {
4341         switch (modrm)
15284342         {
1529            ST(modrm & 7).f = ST(0).f - ST(modrm & 7).f;
1530            FPU_POP(cpustate);
1531            CYCLES(cpustate,8);
1532            break;
1533         }
4343            case 0xc0:
4344            case 0xc1:
4345            case 0xc2:
4346            case 0xc3:
4347            case 0xc4:
4348            case 0xc5:
4349            case 0xc6:
4350            case 0xc7: ptr = x87_fld_sti;   break;
15344351
1535         case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // FSUBP
1536         {
1537            ST(modrm & 7).f -= ST(0).f;
1538            FPU_POP(cpustate);
1539            CYCLES(cpustate,8);
1540            break;
4352            case 0xc8:
4353            case 0xc9:
4354            case 0xca:
4355            case 0xcb:
4356            case 0xcc:
4357            case 0xcd:
4358            case 0xce:
4359            case 0xcf: ptr = x87_fxch_sti;   break;
4360
4361            case 0xd0: ptr = x87_fnop;      break;
4362            case 0xe0: ptr = x87_fchs;      break;
4363            case 0xe1: ptr = x87_fabs;      break;
4364            case 0xe4: ptr = x87_ftst;      break;
4365            case 0xe5: ptr = x87_fxam;      break;
4366            case 0xe8: ptr = x87_fld1;      break;
4367            case 0xe9: ptr = x87_fldl2t;   break;
4368            case 0xea: ptr = x87_fldl2e;   break;
4369            case 0xeb: ptr = x87_fldpi;      break;
4370            case 0xec: ptr = x87_fldlg2;   break;
4371            case 0xed: ptr = x87_fldln2;   break;
4372            case 0xee: ptr = x87_fldz;      break;
4373            case 0xf0: ptr = x87_f2xm1;      break;
4374            case 0xf1: ptr = x87_fyl2x;      break;
4375            case 0xf2: ptr = x87_fptan;      break;
4376            case 0xf3: ptr = x87_fpatan;   break;
4377            case 0xf4: ptr = x87_fxtract;   break;
4378            case 0xf5: ptr = x87_fprem1;   break;
4379            case 0xf6: ptr = x87_fdecstp;   break;
4380            case 0xf7: ptr = x87_fincstp;   break;
4381            case 0xf8: ptr = x87_fprem;      break;
4382            case 0xf9: ptr = x87_fyl2xp1;   break;
4383            case 0xfa: ptr = x87_fsqrt;      break;
4384            case 0xfb: ptr = x87_fsincos;   break;
4385            case 0xfc: ptr = x87_frndint;   break;
4386            case 0xfd: ptr = x87_fscale;   break;
4387            case 0xfe: ptr = x87_fsin;      break;
4388            case 0xff: ptr = x87_fcos;      break;
15414389         }
4390      }
15424391
1543         // FDIVRP
1544         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
4392      cpustate->opcode_table_x87_d9[modrm] = ptr;
4393   }
4394}
4395
4396void build_x87_opcode_table_da(i386_state *cpustate)
4397{
4398   int modrm = 0;
4399
4400   for (modrm = 0; modrm < 0xff; ++modrm)
4401   {
4402      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4403
4404      if (modrm < 0xc0)
4405      {
4406         switch ((modrm >> 3) & 0x7)
15454407         {
1546            if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0)
1547            {
1548               // set result as infinity if zero divide is masked
1549               if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1550               {
1551                  ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
1552               }
1553            }
1554            else
1555            {
1556               ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
1557            }
1558            FPU_POP(cpustate);
1559            CYCLES(cpustate,73);
1560            break;
4408            case 0x00: ptr = x87_fiadd_m32int;   break;
4409            case 0x01: ptr = x87_fimul_m32int;   break;
4410            case 0x02: ptr = x87_ficom_m32int;   break;
4411            case 0x03: ptr = x87_ficomp_m32int;   break;
4412            case 0x04: ptr = x87_fisub_m32int;   break;
4413            case 0x05: ptr = x87_fisubr_m32int;   break;
4414            case 0x06: ptr = x87_fidiv_m32int;   break;
4415            case 0x07: ptr = x87_fidivr_m32int;   break;
15614416         }
1562
1563         // FDIVP
1564         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
4417      }
4418      else
4419      {
4420         switch (modrm)
15654421         {
1566            if ((ST(0).i & U64(0x7fffffffffffffff)) == 0)
1567            {
1568               // set result as infinity if zero divide is masked
1569               if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
1570               {
1571                  ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
1572               }
1573            }
1574            else
1575            {
1576               ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
1577            }
1578            FPU_POP(cpustate);
1579            CYCLES(cpustate,73);
1580            break;
4422            case 0xe9: ptr = x87_fucompp;      break;
15814423         }
4424      }
15824425
1583         default:
1584            fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
1585      }
4426      cpustate->opcode_table_x87_da[modrm] = ptr;
15864427   }
15874428}
15884429
1589static void I386OP(fpu_group_df)(i386_state *cpustate)      // Opcode 0xdf
4430
4431void build_x87_opcode_table_db(i386_state *cpustate)
15904432{
1591   UINT8 modrm = FETCH(cpustate);
4433   int modrm = 0;
15924434
1593   if (modrm < 0xc0)
4435   for (modrm = 0; modrm < 0xff; ++modrm)
15944436   {
1595      UINT32 ea = GetEA(cpustate,modrm);
4437      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
15964438
1597      switch ((modrm >> 3) & 0x7)
4439      if (modrm < 0xc0)
15984440      {
1599         case 0:      // FILD short
4441         switch ((modrm >> 3) & 0x7)
16004442         {
1601            X87_REG t;
1602
1603            t.f=(INT16)READ16(cpustate,ea);
1604            FPU_PUSH(cpustate,t);
1605            CYCLES(cpustate,13);
1606            break;
4443            case 0x00: ptr = x87_fild_m32int;   break;
4444            case 0x02: ptr = x87_fist_m32int;   break;
4445            case 0x03: ptr = x87_fistp_m32int;   break;
4446            case 0x05: ptr = x87_fld_m80real;   break;
4447            case 0x07: ptr = x87_fstp_m80real;   break;
16074448         }
1608
1609         case 2:      // FIST
4449      }
4450      else
4451      {
4452         switch (modrm)
16104453         {
1611            INT16 t;
4454            case 0xe0: ptr = x87_fnop;         break; /* FENI */
4455            case 0xe1: ptr = x87_fnop;         break; /* FDISI */
4456            case 0xe2: ptr = x87_fclex;         break;
4457            case 0xe3: ptr = x87_finit;         break;
4458            case 0xe4: ptr = x87_fnop;         break; /* FSETPM */
4459         }
4460      }
16124461
1613            t = X87_FROUND(cpustate,ST(0));
1614            WRITE16(cpustate,ea,t);
1615            CYCLES(cpustate,1); // TODO
1616            break;
4462      cpustate->opcode_table_x87_db[modrm] = ptr;
4463   }
4464}
16174465
4466
4467void build_x87_opcode_table_dc(i386_state *cpustate)
4468{
4469   int modrm = 0;
4470
4471   for (modrm = 0; modrm < 0xff; ++modrm)
4472   {
4473      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4474
4475      if (modrm < 0xc0)
4476      {
4477         switch ((modrm >> 3) & 0x7)
4478         {
4479            case 0x00: ptr = x87_fadd_m64real;   break;
4480            case 0x01: ptr = x87_fmul_m64real;   break;
4481            case 0x02: ptr = x87_fcom_m64real;   break;
4482            case 0x03: ptr = x87_fcomp_m64real;   break;
4483            case 0x04: ptr = x87_fsub_m64real;   break;
4484            case 0x05: ptr = x87_fsubr_m64real;   break;
4485            case 0x06: ptr = x87_fdiv_m64real;   break;
4486            case 0x07: ptr = x87_fdivr_m64real;   break;
16184487         }
1619         case 3:      // FISTP short
4488      }
4489      else
4490      {
4491         switch (modrm)
16204492         {
1621            INT16 t;
1622
1623            t = X87_FROUND(cpustate,ST(0));
1624            WRITE16(cpustate,ea,t);
1625            FPU_POP(cpustate);
1626            CYCLES(cpustate,29);
1627            break;
4493            case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = x87_fadd_sti_st;   break;
4494            case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = x87_fmul_sti_st;   break;
4495            case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = x87_fsubr_sti_st;   break;
4496            case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = x87_fsub_sti_st;   break;
4497            case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = x87_fdivr_sti_st;   break;
4498            case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = x87_fdiv_sti_st;   break;
16284499         }
1629         case 4:      // FBLD
1630         {
1631            int i;
1632            double bcd_data = 0.0;
1633            UINT8 byte;
1634            X87_REG t;
4500      }
16354501
1636            for(i=0;i<9;i++)
1637            {
1638               byte = READ8(cpustate,ea+i);
1639               bcd_data += floor(fmod((byte & 0x0f),10.0));
1640               bcd_data *= 10.0;
1641               byte >>= 4;
1642               bcd_data += floor(fmod((byte & 0x0f),10.0));
1643               bcd_data *= 10.0;
1644            }
1645            byte = READ8(cpustate,ea+9);
1646            if(byte & 0x80)
1647               bcd_data -= bcd_data;
4502      cpustate->opcode_table_x87_dc[modrm] = ptr;
4503   }
4504}
16484505
1649            t.f = bcd_data;
1650            FPU_PUSH(cpustate,t);
1651            CYCLES(cpustate,1); // TODO
4506
4507void build_x87_opcode_table_dd(i386_state *cpustate)
4508{
4509   int modrm = 0;
4510
4511   for (modrm = 0; modrm < 0xff; ++modrm)
4512   {
4513      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4514
4515      if (modrm < 0xc0)
4516      {
4517         switch ((modrm >> 3) & 0x7)
4518         {
4519            case 0x00: ptr = x87_fld_m64real;   break;
4520            case 0x02: ptr = x87_fst_m64real;   break;
4521            case 0x03: ptr = x87_fstp_m64real;   break;
4522            case 0x04: ptr = x87_frstor;      break;
4523            case 0x06: ptr = x87_fsave;         break;
4524            case 0x07: ptr = x87_fstsw_m2byte;   break;
16524525         }
1653         case 5:      // FILD long
4526      }
4527      else
4528      {
4529         switch (modrm)
16544530         {
1655            X87_REG t;
1656
1657            t.f=(INT64)READ64(cpustate,ea);
1658            FPU_PUSH(cpustate,t);
1659            CYCLES(cpustate,10);
1660            break;
4531            case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = x87_ffree;      break;
4532            case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = x87_fst_sti;      break;
4533            case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = x87_fstp_sti;      break;
4534            case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = x87_fucom_sti;   break;
4535            case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = x87_fucomp_sti;   break;
16614536         }
4537      }
16624538
1663         case 6:      // FBSTP
1664         {
1665            UINT8 res;
1666            double bcd_data;
1667            int i;
4539      cpustate->opcode_table_x87_dd[modrm] = ptr;
4540   }
4541}
16684542
1669            bcd_data = ST(0).f;
16704543
1671            for(i=0;i<9;i++)
1672            {
1673               res = (UINT8)floor(fmod(bcd_data,10.0));
1674               bcd_data -= floor(fmod(bcd_data,10.0));
1675               bcd_data /= 10.0;
1676               res |= (UINT8)floor(fmod(bcd_data,10.0))<<4;
1677               bcd_data -= floor(fmod(bcd_data,10.0));
1678               bcd_data /= 10.0;
1679               WRITE8(cpustate,ea+i,res);
1680            }
1681            res = (UINT8)floor(fmod(bcd_data,10.0));
1682            if(bcd_data < 0)
1683               res |= 0x80;
1684            WRITE8(cpustate,ea+9,res);
1685            FPU_POP(cpustate);
1686            CYCLES(cpustate,1); // TODO
1687            break;
1688         }
4544void build_x87_opcode_table_de(i386_state *cpustate)
4545{
4546   int modrm = 0;
16894547
1690         case 7:      // FISTP long
4548   for (modrm = 0; modrm < 0xff; ++modrm)
4549   {
4550      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4551
4552      if (modrm < 0xc0)
4553      {
4554         switch ((modrm >> 3) & 0x7)
16914555         {
1692            INT64 t;
1693
1694            t = X87_FROUND(cpustate,ST(0));
1695            WRITE64(cpustate,ea,t);
1696            FPU_POP(cpustate);
1697            CYCLES(cpustate,29);
1698            break;
4556            case 0x00: ptr = x87_fiadd_m16int;   break;
4557            case 0x01: ptr = x87_fimul_m16int;   break;
4558            case 0x02: ptr = x87_ficom_m16int;   break;
4559            case 0x03: ptr = x87_ficomp_m16int;   break;
4560            case 0x04: ptr = x87_fisub_m16int;   break;
4561            case 0x05: ptr = x87_fisubr_m16int;   break;
4562            case 0x06: ptr = x87_fidiv_m16int;   break;
4563            case 0x07: ptr = x87_fidivr_m16int;   break;
16994564         }
4565      }
4566      else
4567      {
4568         switch (modrm)
4569         {
4570            case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = x87_faddp;   break;
4571            case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = x87_fmulp;   break;
4572            case 0xd9: ptr = x87_fcompp; break;
4573            case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = x87_fsubrp;   break;
4574            case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = x87_fsubp;   break;
4575            case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = x87_fdivrp;   break;
4576            case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = x87_fdivp;   break;
4577         }
4578      }
17004579
1701         default:
1702            fatalerror("I386: FPU Op DF %02X at %08X", (modrm >> 3) & 7, cpustate->pc-2);
1703      }
4580      cpustate->opcode_table_x87_de[modrm] = ptr;
17044581   }
1705   else
4582}
4583
4584
4585void build_x87_opcode_table_df(i386_state *cpustate)
4586{
4587   int modrm = 0;
4588
4589   for (modrm = 0; modrm < 0xff; ++modrm)
17064590   {
1707      switch (modrm & 0x3f)
4591      void (*ptr)(i386_state *cpustate, UINT8 modrm) = x87_invalid;
4592
4593      if (modrm < 0xc0)
17084594      {
1709         case 0x20:         // FSTSW AX
4595         switch ((modrm >> 3) & 0x7)
17104596         {
1711            REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 11);
1712            CYCLES(cpustate,1);      // TODO
1713            break;
4597            case 0x00: ptr = x87_fild_m16int;   break;
4598            case 0x02: ptr = x87_fist_m16int;   break;
4599            case 0x03: ptr = x87_fistp_m16int;   break;
4600            case 0x04: ptr = x87_fbld;         break;
4601            case 0x05: ptr = x87_fild_m64int;   break;
4602            case 0x06: ptr = x87_fbstp;         break;
4603            case 0x07: ptr = x87_fistp_m64int;   break;
17144604         }
4605      }
4606      else
4607      {
4608         switch (modrm)
4609         {
4610            case 0xe0: ptr = x87_fstsw_ax;      break;
4611         }
4612      }
17154613
1716         default:
1717            fatalerror("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
1718      }
4614      cpustate->opcode_table_x87_df[modrm] = ptr;
17194615   }
17204616}
4617
4618void build_x87_opcode_table(i386_state *cpustate)
4619{
4620   build_x87_opcode_table_d8(cpustate);
4621   build_x87_opcode_table_d9(cpustate);
4622   build_x87_opcode_table_da(cpustate);
4623   build_x87_opcode_table_db(cpustate);
4624   build_x87_opcode_table_dc(cpustate);
4625   build_x87_opcode_table_dd(cpustate);
4626   build_x87_opcode_table_de(cpustate);
4627   build_x87_opcode_table_df(cpustate);
4628}
4629
src/emu/cpu/i386/i386.c
r14218r14219
35013501   cpustate->eflags_mask = 0x00077fd7;
35023502   cpustate->eip = 0xfff0;
35033503
3504   x87_reset(cpustate);
3505
35043506   // [11:8] Family
35053507   // [ 7:4] Model
35063508   // [ 3:0] Stepping ID
r14218r14219
35093511   REG32(EDX) = (4 << 8) | (0 << 4) | (3);
35103512
35113513   build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486);
3514   build_x87_opcode_table(get_safe_token(device));
35123515   cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I486];
35133516   cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I486];
35143517
r14218r14219
35243527   i386_state *cpustate = get_safe_token(device);
35253528   switch (state)
35263529   {
3527      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->fpu_control_word = info->i;         break;
3528      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->fpu_status_word = info->i;         break;
3529      case CPUINFO_INT_REGISTER + X87_ST0:         ST(0).f = info->i;                  break;
3530      case CPUINFO_INT_REGISTER + X87_ST1:         ST(1).f = info->i;                  break;
3531      case CPUINFO_INT_REGISTER + X87_ST2:         ST(2).f = info->i;                  break;
3532      case CPUINFO_INT_REGISTER + X87_ST3:         ST(3).f = info->i;                  break;
3533      case CPUINFO_INT_REGISTER + X87_ST4:         ST(4).f = info->i;                  break;
3534      case CPUINFO_INT_REGISTER + X87_ST5:         ST(5).f = info->i;                  break;
3535      case CPUINFO_INT_REGISTER + X87_ST6:         ST(6).f = info->i;                  break;
3536      case CPUINFO_INT_REGISTER + X87_ST7:         ST(7).f = info->i;                  break;
3530      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->x87_cw = info->i;      break;
3531      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->x87_sw = info->i;      break;
3532      case CPUINFO_INT_REGISTER + X87_TAG:         cpustate->x87_tw = info->i;      break;
35373533
3538      default:                              CPU_SET_INFO_CALL(i386);            break;
3534      default:                              CPU_SET_INFO_CALL(i386);      break;
35393535   }
35403536}
35413537
r14218r14219
35493545      case CPUINFO_FCT_RESET:                      info->reset = CPU_RESET_NAME(i486);      break;
35503546      case CPUINFO_FCT_EXIT:                      info->exit = CPU_EXIT_NAME(i486);      break;
35513547
3552      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->fpu_control_word;         break;
3553      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->fpu_status_word;         break;
3554      case CPUINFO_INT_REGISTER + X87_ST0:         info->i = ST(0).f;                  break;
3555      case CPUINFO_INT_REGISTER + X87_ST1:         info->i = ST(1).f;                  break;
3556      case CPUINFO_INT_REGISTER + X87_ST2:         info->i = ST(2).f;                  break;
3557      case CPUINFO_INT_REGISTER + X87_ST3:         info->i = ST(3).f;                  break;
3558      case CPUINFO_INT_REGISTER + X87_ST4:         info->i = ST(4).f;                  break;
3559      case CPUINFO_INT_REGISTER + X87_ST5:         info->i = ST(5).f;                  break;
3560      case CPUINFO_INT_REGISTER + X87_ST6:         info->i = ST(6).f;                  break;
3561      case CPUINFO_INT_REGISTER + X87_ST7:         info->i = ST(7).f;                  break;
3548      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->x87_cw;            break;
3549      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->x87_sw;            break;
3550      case CPUINFO_INT_REGISTER + X87_TAG:         info->i = cpustate->x87_tw;            break;
35623551
35633552      case DEVINFO_STR_NAME:                     strcpy(info->s, "I486");            break;
3564      case DEVINFO_STR_FAMILY:               strcpy(info->s, "Intel 486");         break;
3565      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
3566      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
3567      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", ST(0).f);   break;
3568      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", ST(1).f);   break;
3569      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", ST(2).f);   break;
3570      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", ST(3).f);   break;
3571      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", ST(4).f);   break;
3572      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", ST(5).f);   break;
3573      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", ST(6).f);   break;
3574      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", ST(7).f);   break;
3553      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Intel 486");         break;
3554      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "x87_CW: %04X", cpustate->x87_cw); break;
3555      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "x87_SW: %04X", cpustate->x87_sw); break;
3556      case CPUINFO_STR_REGISTER + X87_TAG:         sprintf(info->s, "x87_TAG:%04X", cpustate->x87_tw); break;
3557      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", fx80_to_double(ST(0)));   break;
3558      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", fx80_to_double(ST(1)));   break;
3559      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", fx80_to_double(ST(2)));   break;
3560      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", fx80_to_double(ST(3)));   break;
3561      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", fx80_to_double(ST(4)));   break;
3562      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", fx80_to_double(ST(5)));   break;
3563      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", fx80_to_double(ST(6)));   break;
3564      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", fx80_to_double(ST(7)));   break;
35753565
35763566      default:                              CPU_GET_INFO_CALL(i386);            break;
35773567   }
r14218r14219
36183608   cpustate->eflags_mask = 0x003f7fd7;
36193609   cpustate->eip = 0xfff0;
36203610
3611   x87_reset(cpustate);
3612
36213613   // [11:8] Family
36223614   // [ 7:4] Model
36233615   // [ 3:0] Stepping ID
r14218r14219
36263618   REG32(EDX) = (5 << 8) | (2 << 4) | (5);
36273619
36283620   build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM);
3621   build_x87_opcode_table(get_safe_token(device));
36293622   cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];
36303623   cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];
36313624
r14218r14219
36563649   i386_state *cpustate = get_safe_token(device);
36573650   switch (state)
36583651   {
3659      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->fpu_control_word = info->i;         break;
3660      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->fpu_status_word = info->i;         break;
3661      case CPUINFO_INT_REGISTER + X87_ST0:         ST(0).f = info->i;                  break;
3662      case CPUINFO_INT_REGISTER + X87_ST1:         ST(1).f = info->i;                  break;
3663      case CPUINFO_INT_REGISTER + X87_ST2:         ST(2).f = info->i;                  break;
3664      case CPUINFO_INT_REGISTER + X87_ST3:         ST(3).f = info->i;                  break;
3665      case CPUINFO_INT_REGISTER + X87_ST4:         ST(4).f = info->i;                  break;
3666      case CPUINFO_INT_REGISTER + X87_ST5:         ST(5).f = info->i;                  break;
3667      case CPUINFO_INT_REGISTER + X87_ST6:         ST(6).f = info->i;                  break;
3668      case CPUINFO_INT_REGISTER + X87_ST7:         ST(7).f = info->i;                  break;
3652      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->x87_cw = info->i;      break;
3653      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->x87_sw = info->i;      break;
3654      case CPUINFO_INT_REGISTER + X87_TAG:         cpustate->x87_tw = info->i;      break;
36693655
3670      default:                              CPU_SET_INFO_CALL(i386);            break;
3656      default:                              CPU_SET_INFO_CALL(i386);      break;
36713657   }
36723658}
36733659
r14218r14219
36813667      case CPUINFO_FCT_RESET:                      info->reset = CPU_RESET_NAME(pentium);   break;
36823668      case CPUINFO_FCT_EXIT:                      info->exit = CPU_EXIT_NAME(pentium);   break;
36833669
3684      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->fpu_control_word;         break;
3685      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->fpu_status_word;         break;
3686      case CPUINFO_INT_REGISTER + X87_ST0:         info->i = ST(0).f;                  break;
3687      case CPUINFO_INT_REGISTER + X87_ST1:         info->i = ST(1).f;                  break;
3688      case CPUINFO_INT_REGISTER + X87_ST2:         info->i = ST(2).f;                  break;
3689      case CPUINFO_INT_REGISTER + X87_ST3:         info->i = ST(3).f;                  break;
3690      case CPUINFO_INT_REGISTER + X87_ST4:         info->i = ST(4).f;                  break;
3691      case CPUINFO_INT_REGISTER + X87_ST5:         info->i = ST(5).f;                  break;
3692      case CPUINFO_INT_REGISTER + X87_ST6:         info->i = ST(6).f;                  break;
3693      case CPUINFO_INT_REGISTER + X87_ST7:         info->i = ST(7).f;                  break;
3670      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->x87_cw;            break;
3671      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->x87_sw;            break;
3672      case CPUINFO_INT_REGISTER + X87_TAG:         info->i = cpustate->x87_tw;            break;
36943673
36953674      case DEVINFO_STR_NAME:                     strcpy(info->s, "PENTIUM");            break;
36963675      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Intel Pentium");      break;
3697      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
3698      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
3699      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", ST(0).f);   break;
3700      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", ST(1).f);   break;
3701      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", ST(2).f);   break;
3702      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", ST(3).f);   break;
3703      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", ST(4).f);   break;
3704      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", ST(5).f);   break;
3705      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", ST(6).f);   break;
3706      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", ST(7).f);   break;
3676      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "x87_CW: %04X", cpustate->x87_cw); break;
3677      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "x87_SW: %04X", cpustate->x87_sw); break;
3678      case CPUINFO_STR_REGISTER + X87_TAG:         sprintf(info->s, "x87_TAG:%04X", cpustate->x87_tw); break;
3679      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", fx80_to_double(ST(0)));   break;
3680      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", fx80_to_double(ST(1)));   break;
3681      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", fx80_to_double(ST(2)));   break;
3682      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", fx80_to_double(ST(3)));   break;
3683      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", fx80_to_double(ST(4)));   break;
3684      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", fx80_to_double(ST(5)));   break;
3685      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", fx80_to_double(ST(6)));   break;
3686      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", fx80_to_double(ST(7)));   break;
37073687
37083688      default:                              CPU_GET_INFO_CALL(i386);            break;
37093689   }
r14218r14219
37503730   cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
37513731   cpustate->eip = 0xfff0;
37523732
3733   x87_reset(cpustate);
3734
37533735   // [11:8] Family
37543736   // [ 7:4] Model
37553737   // [ 3:0] Stepping ID
r14218r14219
37573739   REG32(EAX) = 0;
37583740   REG32(EDX) = (4 << 8) | (4 << 4) | (1);   /* TODO: is this correct? */
37593741
3742   build_x87_opcode_table(get_safe_token(device));
37603743   build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_CYRIX);
37613744   cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_MEDIAGX];
37623745   cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_MEDIAGX];
r14218r14219
37833766   i386_state *cpustate = get_safe_token(device);
37843767   switch (state)
37853768   {
3786      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->fpu_control_word = info->i;         break;
3787      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->fpu_status_word = info->i;         break;
3788      case CPUINFO_INT_REGISTER + X87_ST0:         ST(0).f = info->i;                  break;
3789      case CPUINFO_INT_REGISTER + X87_ST1:         ST(1).f = info->i;                  break;
3790      case CPUINFO_INT_REGISTER + X87_ST2:         ST(2).f = info->i;                  break;
3791      case CPUINFO_INT_REGISTER + X87_ST3:         ST(3).f = info->i;                  break;
3792      case CPUINFO_INT_REGISTER + X87_ST4:         ST(4).f = info->i;                  break;
3793      case CPUINFO_INT_REGISTER + X87_ST5:         ST(5).f = info->i;                  break;
3794      case CPUINFO_INT_REGISTER + X87_ST6:         ST(6).f = info->i;                  break;
3795      case CPUINFO_INT_REGISTER + X87_ST7:         ST(7).f = info->i;                  break;
3769      case CPUINFO_INT_REGISTER + X87_CTRL:         cpustate->x87_cw = info->i;         break;
3770      case CPUINFO_INT_REGISTER + X87_STATUS:         cpustate->x87_sw = info->i;         break;
37963771
3797      default:                              CPU_SET_INFO_CALL(i386);            break;
3772      default:                              CPU_SET_INFO_CALL(i386);         break;
37983773   }
37993774}
38003775
r14218r14219
38083783      case CPUINFO_FCT_RESET:                      info->reset = CPU_RESET_NAME(mediagx);   break;
38093784      case CPUINFO_FCT_EXIT:                      info->exit = CPU_EXIT_NAME(mediagx);   break;
38103785
3811      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->fpu_control_word;         break;
3812      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->fpu_status_word;         break;
3813      case CPUINFO_INT_REGISTER + X87_ST0:         info->i = ST(0).f;                  break;
3814      case CPUINFO_INT_REGISTER + X87_ST1:         info->i = ST(1).f;                  break;
3815      case CPUINFO_INT_REGISTER + X87_ST2:         info->i = ST(2).f;                  break;
3816      case CPUINFO_INT_REGISTER + X87_ST3:         info->i = ST(3).f;                  break;
3817      case CPUINFO_INT_REGISTER + X87_ST4:         info->i = ST(4).f;                  break;
3818      case CPUINFO_INT_REGISTER + X87_ST5:         info->i = ST(5).f;                  break;
3819      case CPUINFO_INT_REGISTER + X87_ST6:         info->i = ST(6).f;                  break;
3820      case CPUINFO_INT_REGISTER + X87_ST7:         info->i = ST(7).f;                  break;
3786      case CPUINFO_INT_REGISTER + X87_CTRL:         info->i = cpustate->x87_cw;            break;
3787      case CPUINFO_INT_REGISTER + X87_STATUS:         info->i = cpustate->x87_sw;            break;
3788      case CPUINFO_INT_REGISTER + X87_TAG:         info->i = cpustate->x87_tw;            break;
38213789
38223790      case DEVINFO_STR_NAME:                     strcpy(info->s, "MEDIAGX");            break;
3823      case DEVINFO_STR_FAMILY:               strcpy(info->s, "Cyrix MediaGX");      break;
3824      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
3825      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
3826      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", ST(0).f);   break;
3827      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", ST(1).f);   break;
3828      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", ST(2).f);   break;
3829      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", ST(3).f);   break;
3830      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", ST(4).f);   break;
3831      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", ST(5).f);   break;
3832      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", ST(6).f);   break;
3833      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", ST(7).f);   break;
3791      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "Cyrix MediaGX");      break;
3792      case CPUINFO_STR_REGISTER + X87_CTRL:         sprintf(info->s, "x87_CW: %04X", cpustate->x87_cw); break;
3793      case CPUINFO_STR_REGISTER + X87_STATUS:         sprintf(info->s, "x87_SW: %04X", cpustate->x87_sw); break;
3794      case CPUINFO_STR_REGISTER + X87_TAG:         sprintf(info->s, "x87_TAG: %04X", cpustate->x87_tw); break;
3795      case CPUINFO_STR_REGISTER + X87_ST0:         sprintf(info->s, "ST0: %f", fx80_to_double(ST(0)));   break;
3796      case CPUINFO_STR_REGISTER + X87_ST1:         sprintf(info->s, "ST1: %f", fx80_to_double(ST(1)));   break;
3797      case CPUINFO_STR_REGISTER + X87_ST2:         sprintf(info->s, "ST2: %f", fx80_to_double(ST(2)));   break;
3798      case CPUINFO_STR_REGISTER + X87_ST3:         sprintf(info->s, "ST3: %f", fx80_to_double(ST(3)));   break;
3799      case CPUINFO_STR_REGISTER + X87_ST4:         sprintf(info->s, "ST4: %f", fx80_to_double(ST(4)));   break;
3800      case CPUINFO_STR_REGISTER + X87_ST5:         sprintf(info->s, "ST5: %f", fx80_to_double(ST(5)));   break;
3801      case CPUINFO_STR_REGISTER + X87_ST6:         sprintf(info->s, "ST6: %f", fx80_to_double(ST(6)));   break;
3802      case CPUINFO_STR_REGISTER + X87_ST7:         sprintf(info->s, "ST7: %f", fx80_to_double(ST(7)));   break;
38343803
38353804      default:                              CPU_GET_INFO_CALL(i386);            break;
38363805   }
r14218r14219
38393808DEFINE_LEGACY_CPU_DEVICE(I386, i386);
38403809DEFINE_LEGACY_CPU_DEVICE(I486, i486);
38413810DEFINE_LEGACY_CPU_DEVICE(PENTIUM, pentium);
3842DEFINE_LEGACY_CPU_DEVICE(MEDIAGX, mediagx);
3811DEFINE_LEGACY_CPU_DEVICE(MEDIAGX, mediagx);
No newline at end of file

Previous 15994 Revisions Next


© 1998-2018 The MESS Team