1 /////////////////////////////////////////////////////////////////////////
2 // $Id: fpu_arith.cc 13466 2018-02-16 07:57:32Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2003-2018 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu/cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
28 
29 #if BX_SUPPORT_FPU
30 
i387cw_to_softfloat_status_word(Bit16u control_word)31 float_status_t i387cw_to_softfloat_status_word(Bit16u control_word)
32 {
33   float_status_t status;
34 
35   int precision = control_word & FPU_CW_PC;
36 
37   switch(precision)
38   {
39      case FPU_PR_32_BITS:
40        status.float_rounding_precision = 32;
41        break;
42      case FPU_PR_64_BITS:
43        status.float_rounding_precision = 64;
44        break;
45      case FPU_PR_80_BITS:
46        status.float_rounding_precision = 80;
47        break;
48      default:
49     /* With the precision control bits set to 01 "(reserved)", a
50        real CPU behaves as if the precision control bits were
51        set to 11 "80 bits" */
52        status.float_rounding_precision = 80;
53   }
54 
55   status.float_exception_flags = 0; // clear exceptions before execution
56   status.float_nan_handling_mode = float_first_operand_nan;
57   status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10;
58   status.flush_underflow_to_zero = 0;
59   status.float_suppress_exception = 0;
60   status.float_exception_masks = control_word & FPU_CW_Exceptions_Mask;
61   status.denormals_are_zeros = 0;
62 
63   return status;
64 }
65 
66 #include "softfloatx80.h"
67 
FPU_handle_NaN(floatx80 a,int aIsNaN,float32 b32,int bIsNaN,float_status_t & status)68 floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, float_status_t &status)
69 {
70     int aIsSignalingNaN = floatx80_is_signaling_nan(a);
71     int bIsSignalingNaN = float32_is_signaling_nan(b32);
72 
73     if (aIsSignalingNaN | bIsSignalingNaN)
74         float_raise(status, float_flag_invalid);
75 
76     // propagate QNaN to SNaN
77     a = propagateFloatx80NaN(a, status);
78 
79     if (aIsNaN & !bIsNaN) return a;
80 
81     // float32 is NaN so conversion will propagate SNaN to QNaN and raise
82     // appropriate exception flags
83     floatx80 b = float32_to_floatx80(b32, status);
84 
85     if (aIsSignalingNaN) {
86         if (bIsSignalingNaN) goto returnLargerSignificand;
87         return bIsNaN ? b : a;
88     }
89     else if (aIsNaN) {
90         if (bIsSignalingNaN) return a;
91  returnLargerSignificand:
92         if (a.fraction < b.fraction) return b;
93         if (b.fraction < a.fraction) return a;
94         return (a.exp < b.exp) ? a : b;
95     }
96     else {
97         return b;
98     }
99 }
100 
FPU_handle_NaN(floatx80 a,float32 b,floatx80 & r,float_status_t & status)101 int FPU_handle_NaN(floatx80 a, float32 b, floatx80 &r, float_status_t &status)
102 {
103   if (floatx80_is_unsupported(a)) {
104      float_raise(status, float_flag_invalid);
105      r = floatx80_default_nan;
106      return 1;
107   }
108 
109   int aIsNaN = floatx80_is_nan(a), bIsNaN = float32_is_nan(b);
110   if (aIsNaN | bIsNaN) {
111      r = FPU_handle_NaN(a, aIsNaN, b, bIsNaN, status);
112      return 1;
113   }
114   return 0;
115 }
116 
FPU_handle_NaN(floatx80 a,int aIsNaN,float64 b64,int bIsNaN,float_status_t & status)117 floatx80 FPU_handle_NaN(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, float_status_t &status)
118 {
119     int aIsSignalingNaN = floatx80_is_signaling_nan(a);
120     int bIsSignalingNaN = float64_is_signaling_nan(b64);
121 
122     if (aIsSignalingNaN | bIsSignalingNaN)
123         float_raise(status, float_flag_invalid);
124 
125     // propagate QNaN to SNaN
126     a = propagateFloatx80NaN(a, status);
127 
128     if (aIsNaN & !bIsNaN) return a;
129 
130     // float64 is NaN so conversion will propagate SNaN to QNaN and raise
131     // appropriate exception flags
132     floatx80 b = float64_to_floatx80(b64, status);
133 
134     if (aIsSignalingNaN) {
135         if (bIsSignalingNaN) goto returnLargerSignificand;
136         return bIsNaN ? b : a;
137     }
138     else if (aIsNaN) {
139         if (bIsSignalingNaN) return a;
140  returnLargerSignificand:
141         if (a.fraction < b.fraction) return b;
142         if (b.fraction < a.fraction) return a;
143         return (a.exp < b.exp) ? a : b;
144     }
145     else {
146         return b;
147     }
148 }
149 
FPU_handle_NaN(floatx80 a,float64 b,floatx80 & r,float_status_t & status)150 int FPU_handle_NaN(floatx80 a, float64 b, floatx80 &r, float_status_t &status)
151 {
152   if (floatx80_is_unsupported(a)) {
153      float_raise(status, float_flag_invalid);
154      r = floatx80_default_nan;
155      return 1;
156   }
157 
158   int aIsNaN = floatx80_is_nan(a), bIsNaN = float64_is_nan(b);
159   if (aIsNaN | bIsNaN) {
160      r = FPU_handle_NaN(a, aIsNaN, b, bIsNaN, status);
161      return 1;
162   }
163   return 0;
164 }
165 
FADD_ST0_STj(bxInstruction_c * i)166 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_ST0_STj(bxInstruction_c *i)
167 {
168   BX_CPU_THIS_PTR prepareFPU(i);
169   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
170 
171   clear_C1();
172 
173   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
174   {
175      FPU_stack_underflow(i, 0);
176      BX_NEXT_INSTR(i);
177   }
178 
179   floatx80 a = BX_READ_FPU_REG(0);
180   floatx80 b = BX_READ_FPU_REG(i->src());
181 
182   float_status_t status =
183      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
184 
185   floatx80 result = floatx80_add(a, b, status);
186 
187   if (! FPU_exception(i, status.float_exception_flags))
188      BX_WRITE_FPU_REG(result, 0);
189 
190   BX_NEXT_INSTR(i);
191 }
192 
FADD_STi_ST0(bxInstruction_c * i)193 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_STi_ST0(bxInstruction_c *i)
194 {
195   BX_CPU_THIS_PTR prepareFPU(i);
196   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
197 
198   int pop_stack = i->b1() & 2;
199 
200   clear_C1();
201 
202   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
203   {
204      FPU_stack_underflow(i, i->dst(), pop_stack);
205      BX_NEXT_INSTR(i);
206   }
207 
208   floatx80 a = BX_READ_FPU_REG(i->dst());
209   floatx80 b = BX_READ_FPU_REG(0);
210 
211   float_status_t status =
212      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
213 
214   floatx80 result = floatx80_add(a, b, status);
215 
216   if (! FPU_exception(i, status.float_exception_flags)) {
217      BX_WRITE_FPU_REG(result, i->dst());
218      if (pop_stack)
219         BX_CPU_THIS_PTR the_i387.FPU_pop();
220   }
221 
222   BX_NEXT_INSTR(i);
223 }
224 
FADD_SINGLE_REAL(bxInstruction_c * i)225 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_SINGLE_REAL(bxInstruction_c *i)
226 {
227   BX_CPU_THIS_PTR prepareFPU(i);
228 
229   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
230   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
231 
232   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
233 
234   clear_C1();
235 
236   if (IS_TAG_EMPTY(0)) {
237      FPU_stack_underflow(i, 0);
238      BX_NEXT_INSTR(i);
239   }
240 
241   float_status_t status =
242      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
243 
244   floatx80 a = BX_READ_FPU_REG(0), result;
245   if (! FPU_handle_NaN(a, load_reg, result, status))
246      result = floatx80_add(a, float32_to_floatx80(load_reg, status), status);
247 
248   if (! FPU_exception(i, status.float_exception_flags))
249      BX_WRITE_FPU_REG(result, 0);
250 
251   BX_NEXT_INSTR(i);
252 }
253 
FADD_DOUBLE_REAL(bxInstruction_c * i)254 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FADD_DOUBLE_REAL(bxInstruction_c *i)
255 {
256   BX_CPU_THIS_PTR prepareFPU(i);
257 
258   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
259   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
260 
261   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
262 
263   clear_C1();
264 
265   if (IS_TAG_EMPTY(0)) {
266      FPU_stack_underflow(i, 0);
267      BX_NEXT_INSTR(i);
268   }
269 
270   float_status_t status =
271      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
272 
273   floatx80 a = BX_READ_FPU_REG(0), result;
274   if (! FPU_handle_NaN(a, load_reg, result, status))
275      result = floatx80_add(a, float64_to_floatx80(load_reg, status), status);
276 
277   if (! FPU_exception(i, status.float_exception_flags))
278      BX_WRITE_FPU_REG(result, 0);
279 
280   BX_NEXT_INSTR(i);
281 }
282 
FIADD_WORD_INTEGER(bxInstruction_c * i)283 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIADD_WORD_INTEGER(bxInstruction_c *i)
284 {
285   BX_CPU_THIS_PTR prepareFPU(i);
286 
287   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
288   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
289 
290   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
291 
292   clear_C1();
293 
294   if (IS_TAG_EMPTY(0)) {
295      FPU_stack_underflow(i, 0);
296      BX_NEXT_INSTR(i);
297   }
298 
299   floatx80 a = BX_READ_FPU_REG(0);
300   floatx80 b = int32_to_floatx80((Bit32s)(load_reg));
301 
302   float_status_t status =
303      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
304 
305   floatx80 result = floatx80_add(a, b, status);
306 
307   if (! FPU_exception(i, status.float_exception_flags))
308      BX_WRITE_FPU_REG(result, 0);
309 
310   BX_NEXT_INSTR(i);
311 }
312 
FIADD_DWORD_INTEGER(bxInstruction_c * i)313 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIADD_DWORD_INTEGER(bxInstruction_c *i)
314 {
315   BX_CPU_THIS_PTR prepareFPU(i);
316 
317   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
318   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
319 
320   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
321 
322   clear_C1();
323 
324   if (IS_TAG_EMPTY(0)) {
325      FPU_stack_underflow(i, 0);
326      BX_NEXT_INSTR(i);
327   }
328 
329   floatx80 a = BX_READ_FPU_REG(0);
330   floatx80 b = int32_to_floatx80(load_reg);
331 
332   float_status_t status =
333      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
334 
335   floatx80 result = floatx80_add(a, b, status);
336 
337   if (! FPU_exception(i, status.float_exception_flags))
338      BX_WRITE_FPU_REG(result, 0);
339 
340   BX_NEXT_INSTR(i);
341 }
342 
FMUL_ST0_STj(bxInstruction_c * i)343 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_ST0_STj(bxInstruction_c *i)
344 {
345   BX_CPU_THIS_PTR prepareFPU(i);
346   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
347 
348   clear_C1();
349 
350   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
351   {
352      FPU_stack_underflow(i, 0);
353      BX_NEXT_INSTR(i);
354   }
355 
356   floatx80 a = BX_READ_FPU_REG(0);
357   floatx80 b = BX_READ_FPU_REG(i->src());
358 
359   float_status_t status =
360      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
361 
362   floatx80 result = floatx80_mul(a, b, status);
363 
364   if (! FPU_exception(i, status.float_exception_flags))
365      BX_WRITE_FPU_REG(result, 0);
366 
367   BX_NEXT_INSTR(i);
368 }
369 
FMUL_STi_ST0(bxInstruction_c * i)370 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_STi_ST0(bxInstruction_c *i)
371 {
372   BX_CPU_THIS_PTR prepareFPU(i);
373   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
374 
375   int pop_stack = i->b1() & 2;
376 
377   clear_C1();
378 
379   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
380   {
381      FPU_stack_underflow(i, i->dst(), pop_stack);
382      BX_NEXT_INSTR(i);
383   }
384 
385   floatx80 a = BX_READ_FPU_REG(i->dst());
386   floatx80 b = BX_READ_FPU_REG(0);
387 
388   float_status_t status =
389      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
390 
391   floatx80 result = floatx80_mul(a, b, status);
392 
393   if (! FPU_exception(i, status.float_exception_flags)) {
394      BX_WRITE_FPU_REG(result, i->dst());
395      if (pop_stack)
396         BX_CPU_THIS_PTR the_i387.FPU_pop();
397   }
398 
399   BX_NEXT_INSTR(i);
400 }
401 
FMUL_SINGLE_REAL(bxInstruction_c * i)402 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_SINGLE_REAL(bxInstruction_c *i)
403 {
404   BX_CPU_THIS_PTR prepareFPU(i);
405 
406   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
407   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
408 
409   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
410 
411   clear_C1();
412 
413   if (IS_TAG_EMPTY(0)) {
414      FPU_stack_underflow(i, 0);
415      BX_NEXT_INSTR(i);
416   }
417 
418   float_status_t status =
419      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
420 
421   floatx80 a = BX_READ_FPU_REG(0), result;
422   if (! FPU_handle_NaN(a, load_reg, result, status))
423      result = floatx80_mul(a, float32_to_floatx80(load_reg, status), status);
424 
425   if (! FPU_exception(i, status.float_exception_flags))
426      BX_WRITE_FPU_REG(result, 0);
427 
428   BX_NEXT_INSTR(i);
429 }
430 
FMUL_DOUBLE_REAL(bxInstruction_c * i)431 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FMUL_DOUBLE_REAL(bxInstruction_c *i)
432 {
433   BX_CPU_THIS_PTR prepareFPU(i);
434 
435   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
436   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
437 
438   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
439 
440   clear_C1();
441 
442   if (IS_TAG_EMPTY(0)) {
443      FPU_stack_underflow(i, 0);
444      BX_NEXT_INSTR(i);
445   }
446 
447   float_status_t status =
448      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
449 
450   floatx80 a = BX_READ_FPU_REG(0), result;
451   if (! FPU_handle_NaN(a, load_reg, result, status))
452      result = floatx80_mul(a, float64_to_floatx80(load_reg, status), status);
453 
454   if (! FPU_exception(i, status.float_exception_flags))
455      BX_WRITE_FPU_REG(result, 0);
456 
457   BX_NEXT_INSTR(i);
458 }
459 
FIMUL_WORD_INTEGER(bxInstruction_c * i)460 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIMUL_WORD_INTEGER(bxInstruction_c *i)
461 {
462   BX_CPU_THIS_PTR prepareFPU(i);
463 
464   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
465   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
466 
467   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
468 
469   clear_C1();
470 
471   if (IS_TAG_EMPTY(0)) {
472      FPU_stack_underflow(i, 0);
473      BX_NEXT_INSTR(i);
474   }
475 
476   floatx80 a = BX_READ_FPU_REG(0);
477   floatx80 b = int32_to_floatx80((Bit32s)(load_reg));
478 
479   float_status_t status =
480      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
481 
482   floatx80 result = floatx80_mul(a, b, status);
483 
484   if (! FPU_exception(i, status.float_exception_flags))
485      BX_WRITE_FPU_REG(result, 0);
486 
487   BX_NEXT_INSTR(i);
488 }
489 
FIMUL_DWORD_INTEGER(bxInstruction_c * i)490 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIMUL_DWORD_INTEGER(bxInstruction_c *i)
491 {
492   BX_CPU_THIS_PTR prepareFPU(i);
493 
494   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
495   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
496 
497   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
498 
499   clear_C1();
500 
501   if (IS_TAG_EMPTY(0)) {
502      FPU_stack_underflow(i, 0);
503      BX_NEXT_INSTR(i);
504   }
505 
506   floatx80 a = BX_READ_FPU_REG(0);
507   floatx80 b = int32_to_floatx80(load_reg);
508 
509   float_status_t status =
510      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
511 
512   floatx80 result = floatx80_mul(a, b, status);
513 
514   if (! FPU_exception(i, status.float_exception_flags))
515      BX_WRITE_FPU_REG(result, 0);
516 
517   BX_NEXT_INSTR(i);
518 }
519 
FSUB_ST0_STj(bxInstruction_c * i)520 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_ST0_STj(bxInstruction_c *i)
521 {
522   BX_CPU_THIS_PTR prepareFPU(i);
523   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
524 
525   clear_C1();
526 
527   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
528   {
529      FPU_stack_underflow(i, 0);
530      BX_NEXT_INSTR(i);
531   }
532 
533   floatx80 a = BX_READ_FPU_REG(0);
534   floatx80 b = BX_READ_FPU_REG(i->src());
535 
536   float_status_t status =
537      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
538 
539   floatx80 result = floatx80_sub(a, b, status);
540 
541   if (! FPU_exception(i, status.float_exception_flags))
542      BX_WRITE_FPU_REG(result, 0);
543 
544   BX_NEXT_INSTR(i);
545 }
546 
FSUBR_ST0_STj(bxInstruction_c * i)547 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_ST0_STj(bxInstruction_c *i)
548 {
549   BX_CPU_THIS_PTR prepareFPU(i);
550   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
551 
552   clear_C1();
553 
554   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
555   {
556      FPU_stack_underflow(i, 0);
557      BX_NEXT_INSTR(i);
558   }
559 
560   floatx80 a = BX_READ_FPU_REG(i->src());
561   floatx80 b = BX_READ_FPU_REG(0);
562 
563   float_status_t status =
564      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
565 
566   floatx80 result = floatx80_sub(a, b, status);
567 
568   if (! FPU_exception(i, status.float_exception_flags))
569      BX_WRITE_FPU_REG(result, 0);
570 
571   BX_NEXT_INSTR(i);
572 }
573 
FSUB_STi_ST0(bxInstruction_c * i)574 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_STi_ST0(bxInstruction_c *i)
575 {
576   BX_CPU_THIS_PTR prepareFPU(i);
577   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
578 
579   int pop_stack = i->b1() & 2;
580 
581   clear_C1();
582 
583   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
584   {
585      FPU_stack_underflow(i, i->dst(), pop_stack);
586      BX_NEXT_INSTR(i);
587   }
588 
589   floatx80 a = BX_READ_FPU_REG(i->dst());
590   floatx80 b = BX_READ_FPU_REG(0);
591 
592   float_status_t status =
593      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
594 
595   floatx80 result = floatx80_sub(a, b, status);
596 
597   if (! FPU_exception(i, status.float_exception_flags)) {
598      BX_WRITE_FPU_REG(result, i->dst());
599      if (pop_stack)
600         BX_CPU_THIS_PTR the_i387.FPU_pop();
601   }
602 
603   BX_NEXT_INSTR(i);
604 }
605 
FSUBR_STi_ST0(bxInstruction_c * i)606 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_STi_ST0(bxInstruction_c *i)
607 {
608   BX_CPU_THIS_PTR prepareFPU(i);
609   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
610 
611   int pop_stack = i->b1() & 2;
612 
613   clear_C1();
614 
615   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
616   {
617      FPU_stack_underflow(i, i->dst(), pop_stack);
618      BX_NEXT_INSTR(i);
619   }
620 
621   floatx80 a = BX_READ_FPU_REG(0);
622   floatx80 b = BX_READ_FPU_REG(i->dst());
623 
624   float_status_t status =
625      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
626 
627   floatx80 result = floatx80_sub(a, b, status);
628 
629   if (! FPU_exception(i, status.float_exception_flags)) {
630      BX_WRITE_FPU_REG(result, i->dst());
631      if (pop_stack)
632         BX_CPU_THIS_PTR the_i387.FPU_pop();
633   }
634 
635   BX_NEXT_INSTR(i);
636 }
637 
FSUB_SINGLE_REAL(bxInstruction_c * i)638 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_SINGLE_REAL(bxInstruction_c *i)
639 {
640   BX_CPU_THIS_PTR prepareFPU(i);
641 
642   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
643   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
644 
645   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
646 
647   clear_C1();
648 
649   if (IS_TAG_EMPTY(0)) {
650      FPU_stack_underflow(i, 0);
651      BX_NEXT_INSTR(i);
652   }
653 
654   float_status_t status =
655      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
656 
657   floatx80 a = BX_READ_FPU_REG(0), result;
658   if (! FPU_handle_NaN(a, load_reg, result, status))
659      result = floatx80_sub(a, float32_to_floatx80(load_reg, status), status);
660 
661   if (! FPU_exception(i, status.float_exception_flags))
662      BX_WRITE_FPU_REG(result, 0);
663 
664   BX_NEXT_INSTR(i);
665 }
666 
FSUBR_SINGLE_REAL(bxInstruction_c * i)667 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_SINGLE_REAL(bxInstruction_c *i)
668 {
669   BX_CPU_THIS_PTR prepareFPU(i);
670 
671   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
672   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
673 
674   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
675 
676   clear_C1();
677 
678   if (IS_TAG_EMPTY(0)) {
679      FPU_stack_underflow(i, 0);
680      BX_NEXT_INSTR(i);
681   }
682 
683   float_status_t status =
684      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
685 
686   floatx80 b = BX_READ_FPU_REG(0), result;
687   if (! FPU_handle_NaN(b, load_reg, result, status))
688      result = floatx80_sub(float32_to_floatx80(load_reg, status), b, status);
689 
690   if (! FPU_exception(i, status.float_exception_flags))
691      BX_WRITE_FPU_REG(result, 0);
692 
693   BX_NEXT_INSTR(i);
694 }
695 
FSUB_DOUBLE_REAL(bxInstruction_c * i)696 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUB_DOUBLE_REAL(bxInstruction_c *i)
697 {
698   BX_CPU_THIS_PTR prepareFPU(i);
699 
700   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
701   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
702 
703   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
704 
705   clear_C1();
706 
707   if (IS_TAG_EMPTY(0)) {
708      FPU_stack_underflow(i, 0);
709      BX_NEXT_INSTR(i);
710   }
711 
712   float_status_t status =
713      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
714 
715   floatx80 a = BX_READ_FPU_REG(0), result;
716   if (! FPU_handle_NaN(a, load_reg, result, status))
717      result = floatx80_sub(a, float64_to_floatx80(load_reg, status), status);
718 
719   if (! FPU_exception(i, status.float_exception_flags))
720      BX_WRITE_FPU_REG(result, 0);
721 
722   BX_NEXT_INSTR(i);
723 }
724 
FSUBR_DOUBLE_REAL(bxInstruction_c * i)725 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSUBR_DOUBLE_REAL(bxInstruction_c *i)
726 {
727   BX_CPU_THIS_PTR prepareFPU(i);
728 
729   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
730   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
731 
732   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
733 
734   clear_C1();
735 
736   if (IS_TAG_EMPTY(0)) {
737      FPU_stack_underflow(i, 0);
738      BX_NEXT_INSTR(i);
739   }
740 
741   float_status_t status =
742      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
743 
744 
745   floatx80 b = BX_READ_FPU_REG(0), result;
746   if (! FPU_handle_NaN(b, load_reg, result, status))
747      result = floatx80_sub(float64_to_floatx80(load_reg, status), b, status);
748 
749   if (! FPU_exception(i, status.float_exception_flags))
750      BX_WRITE_FPU_REG(result, 0);
751 
752   BX_NEXT_INSTR(i);
753 }
754 
FISUB_WORD_INTEGER(bxInstruction_c * i)755 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUB_WORD_INTEGER(bxInstruction_c *i)
756 {
757   BX_CPU_THIS_PTR prepareFPU(i);
758 
759   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
760   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
761 
762   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
763 
764   clear_C1();
765 
766   if (IS_TAG_EMPTY(0)) {
767      FPU_stack_underflow(i, 0);
768      BX_NEXT_INSTR(i);
769   }
770 
771   floatx80 a = BX_READ_FPU_REG(0);
772   floatx80 b = int32_to_floatx80((Bit32s)(load_reg));
773 
774   float_status_t status =
775      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
776 
777   floatx80 result = floatx80_sub(a, b, status);
778 
779   if (! FPU_exception(i, status.float_exception_flags))
780      BX_WRITE_FPU_REG(result, 0);
781 
782   BX_NEXT_INSTR(i);
783 }
784 
FISUBR_WORD_INTEGER(bxInstruction_c * i)785 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUBR_WORD_INTEGER(bxInstruction_c *i)
786 {
787   BX_CPU_THIS_PTR prepareFPU(i);
788 
789   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
790   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
791 
792   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
793 
794   clear_C1();
795 
796   if (IS_TAG_EMPTY(0)) {
797      FPU_stack_underflow(i, 0);
798      BX_NEXT_INSTR(i);
799   }
800 
801   floatx80 a = int32_to_floatx80((Bit32s)(load_reg));
802   floatx80 b = BX_READ_FPU_REG(0);
803 
804   float_status_t status =
805      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
806 
807   floatx80 result = floatx80_sub(a, b, status);
808 
809   if (! FPU_exception(i, status.float_exception_flags))
810      BX_WRITE_FPU_REG(result, 0);
811 
812   BX_NEXT_INSTR(i);
813 }
814 
FISUB_DWORD_INTEGER(bxInstruction_c * i)815 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUB_DWORD_INTEGER(bxInstruction_c *i)
816 {
817   BX_CPU_THIS_PTR prepareFPU(i);
818 
819   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
820   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
821 
822   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
823 
824   clear_C1();
825 
826   if (IS_TAG_EMPTY(0)) {
827      FPU_stack_underflow(i, 0);
828      BX_NEXT_INSTR(i);
829   }
830 
831   float_status_t status =
832      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
833 
834   floatx80 result = floatx80_sub(BX_READ_FPU_REG(0), int32_to_floatx80(load_reg), status);
835 
836   if (! FPU_exception(i, status.float_exception_flags))
837      BX_WRITE_FPU_REG(result, 0);
838 
839   BX_NEXT_INSTR(i);
840 }
841 
FISUBR_DWORD_INTEGER(bxInstruction_c * i)842 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISUBR_DWORD_INTEGER(bxInstruction_c *i)
843 {
844   BX_CPU_THIS_PTR prepareFPU(i);
845 
846   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
847   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
848 
849   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
850 
851   clear_C1();
852 
853   if (IS_TAG_EMPTY(0)) {
854      FPU_stack_underflow(i, 0);
855      BX_NEXT_INSTR(i);
856   }
857 
858   floatx80 a = int32_to_floatx80(load_reg);
859   floatx80 b = BX_READ_FPU_REG(0);
860 
861   float_status_t status =
862      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
863 
864   floatx80 result = floatx80_sub(a, b, status);
865 
866   if (! FPU_exception(i, status.float_exception_flags))
867      BX_WRITE_FPU_REG(result, 0);
868 
869   BX_NEXT_INSTR(i);
870 }
871 
FDIV_ST0_STj(bxInstruction_c * i)872 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_ST0_STj(bxInstruction_c *i)
873 {
874   BX_CPU_THIS_PTR prepareFPU(i);
875   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
876 
877   clear_C1();
878 
879   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
880   {
881      FPU_stack_underflow(i, 0);
882      BX_NEXT_INSTR(i);
883   }
884 
885   floatx80 a = BX_READ_FPU_REG(0);
886   floatx80 b = BX_READ_FPU_REG(i->src());
887 
888   float_status_t status =
889      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
890 
891   floatx80 result = floatx80_div(a, b, status);
892 
893   if (! FPU_exception(i, status.float_exception_flags))
894      BX_WRITE_FPU_REG(result, 0);
895 
896   BX_NEXT_INSTR(i);
897 }
898 
FDIVR_ST0_STj(bxInstruction_c * i)899 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_ST0_STj(bxInstruction_c *i)
900 {
901   BX_CPU_THIS_PTR prepareFPU(i);
902   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
903 
904   clear_C1();
905 
906   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->src()))
907   {
908      FPU_stack_underflow(i, 0);
909      BX_NEXT_INSTR(i);
910   }
911 
912   floatx80 a = BX_READ_FPU_REG(i->src());
913   floatx80 b = BX_READ_FPU_REG(0);
914 
915   float_status_t status =
916      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
917 
918   floatx80 result = floatx80_div(a, b, status);
919 
920   if (! FPU_exception(i, status.float_exception_flags))
921      BX_WRITE_FPU_REG(result, 0);
922 
923   BX_NEXT_INSTR(i);
924 }
925 
FDIV_STi_ST0(bxInstruction_c * i)926 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_STi_ST0(bxInstruction_c *i)
927 {
928   BX_CPU_THIS_PTR prepareFPU(i);
929   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
930 
931   int pop_stack = i->b1() & 2;
932 
933   clear_C1();
934 
935   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
936   {
937      FPU_stack_underflow(i, i->dst(), pop_stack);
938      BX_NEXT_INSTR(i);
939   }
940 
941   floatx80 a = BX_READ_FPU_REG(i->dst());
942   floatx80 b = BX_READ_FPU_REG(0);
943 
944   float_status_t status =
945      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
946 
947   floatx80 result = floatx80_div(a, b, status);
948 
949   if (! FPU_exception(i, status.float_exception_flags)) {
950      BX_WRITE_FPU_REG(result, i->dst());
951      if (pop_stack)
952         BX_CPU_THIS_PTR the_i387.FPU_pop();
953   }
954 
955   BX_NEXT_INSTR(i);
956 }
957 
FDIVR_STi_ST0(bxInstruction_c * i)958 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_STi_ST0(bxInstruction_c *i)
959 {
960   BX_CPU_THIS_PTR prepareFPU(i);
961   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
962 
963   int pop_stack = i->b1() & 2;
964 
965   clear_C1();
966 
967   if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->dst()))
968   {
969      FPU_stack_underflow(i, i->dst(), pop_stack);
970      BX_NEXT_INSTR(i);
971   }
972 
973   floatx80 a = BX_READ_FPU_REG(0);
974   floatx80 b = BX_READ_FPU_REG(i->dst());
975 
976   float_status_t status =
977      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
978 
979   floatx80 result = floatx80_div(a, b, status);
980 
981   if (! FPU_exception(i, status.float_exception_flags)) {
982      BX_WRITE_FPU_REG(result, i->dst());
983      if (pop_stack)
984         BX_CPU_THIS_PTR the_i387.FPU_pop();
985   }
986 
987   BX_NEXT_INSTR(i);
988 }
989 
FDIV_SINGLE_REAL(bxInstruction_c * i)990 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_SINGLE_REAL(bxInstruction_c *i)
991 {
992   BX_CPU_THIS_PTR prepareFPU(i);
993 
994   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
995   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
996 
997   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
998 
999   clear_C1();
1000 
1001   if (IS_TAG_EMPTY(0)) {
1002      FPU_stack_underflow(i, 0);
1003      BX_NEXT_INSTR(i);
1004   }
1005 
1006   float_status_t status =
1007      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1008 
1009   floatx80 a = BX_READ_FPU_REG(0), result;
1010   if (! FPU_handle_NaN(a, load_reg, result, status))
1011      result = floatx80_div(a, float32_to_floatx80(load_reg, status), status);
1012 
1013   if (! FPU_exception(i, status.float_exception_flags))
1014      BX_WRITE_FPU_REG(result, 0);
1015 
1016   BX_NEXT_INSTR(i);
1017 }
1018 
FDIVR_SINGLE_REAL(bxInstruction_c * i)1019 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_SINGLE_REAL(bxInstruction_c *i)
1020 {
1021   BX_CPU_THIS_PTR prepareFPU(i);
1022 
1023   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1024   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
1025 
1026   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1027 
1028   clear_C1();
1029 
1030   if (IS_TAG_EMPTY(0)) {
1031      FPU_stack_underflow(i, 0);
1032      BX_NEXT_INSTR(i);
1033   }
1034 
1035   float_status_t status =
1036      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1037 
1038   floatx80 b = BX_READ_FPU_REG(0), result;
1039   if (! FPU_handle_NaN(b, load_reg, result, status))
1040      result = floatx80_div(float32_to_floatx80(load_reg, status), b, status);
1041 
1042   if (! FPU_exception(i, status.float_exception_flags))
1043      BX_WRITE_FPU_REG(result, 0);
1044 
1045   BX_NEXT_INSTR(i);
1046 }
1047 
FDIV_DOUBLE_REAL(bxInstruction_c * i)1048 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIV_DOUBLE_REAL(bxInstruction_c *i)
1049 {
1050   BX_CPU_THIS_PTR prepareFPU(i);
1051 
1052   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1053   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
1054 
1055   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1056 
1057   clear_C1();
1058 
1059   if (IS_TAG_EMPTY(0)) {
1060      FPU_stack_underflow(i, 0);
1061      BX_NEXT_INSTR(i);
1062   }
1063 
1064   float_status_t status =
1065      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1066 
1067   floatx80 a = BX_READ_FPU_REG(0), result;
1068   if (! FPU_handle_NaN(a, load_reg, result, status))
1069      result = floatx80_div(a, float64_to_floatx80(load_reg, status), status);
1070 
1071   if (! FPU_exception(i, status.float_exception_flags))
1072      BX_WRITE_FPU_REG(result, 0);
1073 
1074   BX_NEXT_INSTR(i);
1075 }
1076 
FDIVR_DOUBLE_REAL(bxInstruction_c * i)1077 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FDIVR_DOUBLE_REAL(bxInstruction_c *i)
1078 {
1079   BX_CPU_THIS_PTR prepareFPU(i);
1080 
1081   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1082   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
1083 
1084   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1085 
1086   clear_C1();
1087 
1088   if (IS_TAG_EMPTY(0)) {
1089      FPU_stack_underflow(i, 0);
1090      BX_NEXT_INSTR(i);
1091   }
1092 
1093   float_status_t status =
1094      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1095 
1096   floatx80 b = BX_READ_FPU_REG(0), result;
1097   if (! FPU_handle_NaN(b, load_reg, result, status))
1098      result = floatx80_div(float64_to_floatx80(load_reg, status), b, status);
1099 
1100   if (! FPU_exception(i, status.float_exception_flags))
1101      BX_WRITE_FPU_REG(result, 0);
1102 
1103   BX_NEXT_INSTR(i);
1104 }
1105 
FIDIV_WORD_INTEGER(bxInstruction_c * i)1106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIV_WORD_INTEGER(bxInstruction_c *i)
1107 {
1108   BX_CPU_THIS_PTR prepareFPU(i);
1109 
1110   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1111   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
1112 
1113   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1114 
1115   clear_C1();
1116 
1117   if (IS_TAG_EMPTY(0)) {
1118      FPU_stack_underflow(i, 0);
1119      BX_NEXT_INSTR(i);
1120   }
1121 
1122   floatx80 a = BX_READ_FPU_REG(0);
1123   floatx80 b = int32_to_floatx80((Bit32s)(load_reg));
1124 
1125   float_status_t status =
1126      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1127 
1128   floatx80 result = floatx80_div(a, b, status);
1129 
1130   if (! FPU_exception(i, status.float_exception_flags))
1131      BX_WRITE_FPU_REG(result, 0);
1132 
1133   BX_NEXT_INSTR(i);
1134 }
1135 
FIDIVR_WORD_INTEGER(bxInstruction_c * i)1136 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIVR_WORD_INTEGER(bxInstruction_c *i)
1137 {
1138   BX_CPU_THIS_PTR prepareFPU(i);
1139 
1140   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1141   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
1142 
1143   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1144 
1145   clear_C1();
1146 
1147   if (IS_TAG_EMPTY(0)) {
1148      FPU_stack_underflow(i, 0);
1149      BX_NEXT_INSTR(i);
1150   }
1151 
1152   floatx80 a = int32_to_floatx80((Bit32s)(load_reg));
1153   floatx80 b = BX_READ_FPU_REG(0);
1154 
1155   float_status_t status =
1156      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1157 
1158   floatx80 result = floatx80_div(a, b, status);
1159 
1160   if (! FPU_exception(i, status.float_exception_flags))
1161      BX_WRITE_FPU_REG(result, 0);
1162 
1163   BX_NEXT_INSTR(i);
1164 }
1165 
FIDIV_DWORD_INTEGER(bxInstruction_c * i)1166 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIV_DWORD_INTEGER(bxInstruction_c *i)
1167 {
1168   BX_CPU_THIS_PTR prepareFPU(i);
1169 
1170   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1171   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
1172 
1173   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1174 
1175   clear_C1();
1176 
1177   if (IS_TAG_EMPTY(0)) {
1178      FPU_stack_underflow(i, 0);
1179      BX_NEXT_INSTR(i);
1180   }
1181 
1182   floatx80 a = BX_READ_FPU_REG(0);
1183   floatx80 b = int32_to_floatx80(load_reg);
1184 
1185   float_status_t status =
1186      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1187 
1188   floatx80 result = floatx80_div(a, b, status);
1189 
1190   if (! FPU_exception(i, status.float_exception_flags))
1191      BX_WRITE_FPU_REG(result, 0);
1192 
1193   BX_NEXT_INSTR(i);
1194 }
1195 
FIDIVR_DWORD_INTEGER(bxInstruction_c * i)1196 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIDIVR_DWORD_INTEGER(bxInstruction_c *i)
1197 {
1198   BX_CPU_THIS_PTR prepareFPU(i);
1199 
1200   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
1201   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
1202 
1203   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1204 
1205   clear_C1();
1206 
1207   if (IS_TAG_EMPTY(0)) {
1208      FPU_stack_underflow(i, 0);
1209      BX_NEXT_INSTR(i);
1210   }
1211 
1212   floatx80 a = int32_to_floatx80(load_reg);
1213   floatx80 b = BX_READ_FPU_REG(0);
1214 
1215   float_status_t status =
1216      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1217 
1218   floatx80 result = floatx80_div(a, b, status);
1219 
1220   if (! FPU_exception(i, status.float_exception_flags))
1221      BX_WRITE_FPU_REG(result, 0);
1222 
1223   BX_NEXT_INSTR(i);
1224 }
1225 
FSQRT(bxInstruction_c * i)1226 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSQRT(bxInstruction_c *i)
1227 {
1228   BX_CPU_THIS_PTR prepareFPU(i);
1229   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1230 
1231   clear_C1();
1232 
1233   if (IS_TAG_EMPTY(0)) {
1234      FPU_stack_underflow(i, 0);
1235      BX_NEXT_INSTR(i);
1236   }
1237 
1238   float_status_t status =
1239      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1240 
1241   floatx80 result = floatx80_sqrt(BX_READ_FPU_REG(0), status);
1242 
1243   if (! FPU_exception(i, status.float_exception_flags))
1244      BX_WRITE_FPU_REG(result, 0);
1245 
1246   BX_NEXT_INSTR(i);
1247 }
1248 
1249 /* D9 FC */
FRNDINT(bxInstruction_c * i)1250 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FRNDINT(bxInstruction_c *i)
1251 {
1252   BX_CPU_THIS_PTR prepareFPU(i);
1253   BX_CPU_THIS_PTR FPU_update_last_instruction(i);
1254 
1255   clear_C1();
1256 
1257   if (IS_TAG_EMPTY(0)) {
1258      FPU_stack_underflow(i, 0);
1259      BX_NEXT_INSTR(i);
1260   }
1261 
1262   float_status_t status =
1263      i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
1264 
1265   floatx80 result = floatx80_round_to_int(BX_READ_FPU_REG(0), status);
1266 
1267   if (! FPU_exception(i, status.float_exception_flags))
1268      BX_WRITE_FPU_REG(result, 0);
1269 
1270   BX_NEXT_INSTR(i);
1271 }
1272 
1273 #endif
1274