1 /////////////////////////////////////////////////////////////////////////
2 // $Id: fpu_load_store.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 
31 #include "cpu/decoder/ia_opcodes.h"
32 
33 #define swap_values16u(a, b) { Bit16u tmp = a; a = b; b = tmp; }
34 
35 extern float_status_t i387cw_to_softfloat_status_word(Bit16u control_word);
36 
37 #include "softfloatx80.h"
38 
FLD_STi(bxInstruction_c * i)39 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_STi(bxInstruction_c *i)
40 {
41   BX_CPU_THIS_PTR prepareFPU(i);
42   FPU_update_last_instruction(i);
43 
44   clear_C1();
45 
46   if (! IS_TAG_EMPTY(-1))
47   {
48     FPU_stack_overflow(i);
49     BX_NEXT_INSTR(i);
50   }
51 
52   floatx80 sti_reg = floatx80_default_nan;
53 
54   if (IS_TAG_EMPTY(i->src()))
55   {
56     FPU_exception(i, FPU_EX_Stack_Underflow);
57 
58     if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
59       BX_NEXT_INSTR(i);
60   }
61   else {
62     sti_reg = BX_READ_FPU_REG(i->src());
63   }
64 
65   BX_CPU_THIS_PTR the_i387.FPU_push();
66   BX_WRITE_FPU_REG(sti_reg, 0);
67 
68   BX_NEXT_INSTR(i);
69 }
70 
FLD_SINGLE_REAL(bxInstruction_c * i)71 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_SINGLE_REAL(bxInstruction_c *i)
72 {
73   BX_CPU_THIS_PTR prepareFPU(i);
74 
75   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
76   float32 load_reg = read_virtual_dword(i->seg(), RMAddr(i));
77 
78   FPU_update_last_instruction(i);
79 
80   clear_C1();
81 
82   if (! IS_TAG_EMPTY(-1)) {
83     FPU_stack_overflow(i);
84     BX_NEXT_INSTR(i);
85   }
86 
87   float_status_t status =
88     i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
89 
90   // convert to floatx80 format
91   floatx80 result = float32_to_floatx80(load_reg, status);
92 
93   unsigned unmasked = FPU_exception(i, status.float_exception_flags);
94   if (! (unmasked & FPU_CW_Invalid)) {
95     BX_CPU_THIS_PTR the_i387.FPU_push();
96     BX_WRITE_FPU_REG(result, 0);
97   }
98 
99   BX_NEXT_INSTR(i);
100 }
101 
FLD_DOUBLE_REAL(bxInstruction_c * i)102 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i)
103 {
104   BX_CPU_THIS_PTR prepareFPU(i);
105 
106   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
107   float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));
108 
109   FPU_update_last_instruction(i);
110 
111   clear_C1();
112 
113   if (! IS_TAG_EMPTY(-1)) {
114     FPU_stack_overflow(i);
115     BX_NEXT_INSTR(i);
116   }
117 
118   float_status_t status =
119     i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
120 
121   // convert to floatx80 format
122   floatx80 result = float64_to_floatx80(load_reg, status);
123 
124   unsigned unmasked = FPU_exception(i, status.float_exception_flags);
125   if (! (unmasked & FPU_CW_Invalid)) {
126     BX_CPU_THIS_PTR the_i387.FPU_push();
127     BX_WRITE_FPU_REG(result, 0);
128   }
129 
130   BX_NEXT_INSTR(i);
131 }
132 
FLD_EXTENDED_REAL(bxInstruction_c * i)133 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_EXTENDED_REAL(bxInstruction_c *i)
134 {
135   BX_CPU_THIS_PTR prepareFPU(i);
136 
137   floatx80 result;
138 
139   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
140   result.fraction = read_virtual_qword(i->seg(), RMAddr(i));
141   result.exp      = read_virtual_word(i->seg(), (RMAddr(i)+8) & i->asize_mask());
142 
143   FPU_update_last_instruction(i);
144 
145   clear_C1();
146 
147   if (! IS_TAG_EMPTY(-1)) {
148     FPU_stack_overflow(i);
149   }
150   else {
151     BX_CPU_THIS_PTR the_i387.FPU_push();
152     BX_WRITE_FPU_REG(result, 0);
153   }
154 
155   BX_NEXT_INSTR(i);
156 }
157 
158 /* DF /0 */
FILD_WORD_INTEGER(bxInstruction_c * i)159 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_WORD_INTEGER(bxInstruction_c *i)
160 {
161   BX_CPU_THIS_PTR prepareFPU(i);
162 
163   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
164   Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));
165 
166   FPU_update_last_instruction(i);
167 
168   clear_C1();
169 
170   if (! IS_TAG_EMPTY(-1)) {
171     FPU_stack_overflow(i);
172   }
173   else {
174     floatx80 result = int32_to_floatx80((Bit32s) load_reg);
175     BX_CPU_THIS_PTR the_i387.FPU_push();
176     BX_WRITE_FPU_REG(result, 0);
177   }
178 
179   BX_NEXT_INSTR(i);
180 }
181 
182 /* DB /0 */
FILD_DWORD_INTEGER(bxInstruction_c * i)183 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_DWORD_INTEGER(bxInstruction_c *i)
184 {
185   BX_CPU_THIS_PTR prepareFPU(i);
186 
187   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
188   Bit32s load_reg = (Bit32s) read_virtual_dword(i->seg(), RMAddr(i));
189 
190   FPU_update_last_instruction(i);
191 
192   clear_C1();
193 
194   if (! IS_TAG_EMPTY(-1)) {
195     FPU_stack_overflow(i);
196   }
197   else {
198     floatx80 result = int32_to_floatx80(load_reg);
199     BX_CPU_THIS_PTR the_i387.FPU_push();
200     BX_WRITE_FPU_REG(result, 0);
201   }
202 
203   BX_NEXT_INSTR(i);
204 }
205 
206 /* DF /5 */
FILD_QWORD_INTEGER(bxInstruction_c * i)207 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i)
208 {
209   BX_CPU_THIS_PTR prepareFPU(i);
210 
211   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
212   Bit64s load_reg = (Bit64s) read_virtual_qword(i->seg(), RMAddr(i));
213 
214   FPU_update_last_instruction(i);
215 
216   clear_C1();
217 
218   if (! IS_TAG_EMPTY(-1)) {
219     FPU_stack_overflow(i);
220   }
221   else {
222     floatx80 result = int64_to_floatx80(load_reg);
223     BX_CPU_THIS_PTR the_i387.FPU_push();
224     BX_WRITE_FPU_REG(result, 0);
225   }
226 
227   BX_NEXT_INSTR(i);
228 }
229 
230 /* DF /4 */
FBLD_PACKED_BCD(bxInstruction_c * i)231 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i)
232 {
233   BX_CPU_THIS_PTR prepareFPU(i);
234 
235   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
236   Bit16u hi2 = read_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask());
237   Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i));
238 
239   FPU_update_last_instruction(i);
240 
241   clear_C1();
242 
243   if (! IS_TAG_EMPTY(-1))
244   {
245     FPU_stack_overflow(i);
246     BX_NEXT_INSTR(i);
247   }
248 
249   // convert packed BCD to 64-bit integer
250   Bit64s scale = 1;
251   Bit64s val64 = 0;
252 
253   for (int n = 0; n < 16; n++)
254   {
255     val64 += (lo8 & 0x0f) * scale;
256     lo8 >>= 4;
257     scale *= 10;
258   }
259 
260   val64 += (hi2 & 0x0f) * scale;
261   val64 += ((hi2>>4) & 0x0f) * scale * 10;
262 
263   floatx80 result = int64_to_floatx80(val64);
264   if (hi2 & 0x8000)        // set negative
265       floatx80_chs(result);
266 
267   BX_CPU_THIS_PTR the_i387.FPU_push();
268   BX_WRITE_FPU_REG(result, 0);
269 
270   BX_NEXT_INSTR(i);
271 }
272 
FST_STi(bxInstruction_c * i)273 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_STi(bxInstruction_c *i)
274 {
275   BX_CPU_THIS_PTR prepareFPU(i);
276   FPU_update_last_instruction(i);
277 
278   int pop_stack = 0;
279   if (i->getIaOpcode() == BX_IA_FSTP_STi)
280       pop_stack = 1;
281 
282   clear_C1();
283 
284   if (IS_TAG_EMPTY(0)) {
285     FPU_stack_underflow(i, i->dst(), pop_stack);
286   }
287   else {
288     floatx80 st0_reg = BX_READ_FPU_REG(0);
289 
290     BX_WRITE_FPU_REG(st0_reg, i->dst());
291     if (pop_stack)
292       BX_CPU_THIS_PTR the_i387.FPU_pop();
293   }
294 
295   BX_NEXT_INSTR(i);
296 }
297 
FST_SINGLE_REAL(bxInstruction_c * i)298 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_SINGLE_REAL(bxInstruction_c *i)
299 {
300   BX_CPU_THIS_PTR prepareFPU(i);
301 
302   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
303 
304   FPU_update_last_instruction(i);
305 
306   Bit16u x87_sw = FPU_PARTIAL_STATUS;
307 
308   clear_C1();
309 
310   float32 save_reg = float32_default_nan; /* The masked response */
311 
312   int pop_stack = 0;
313   if (i->getIaOpcode() == BX_IA_FSTP_SINGLE_REAL)
314       pop_stack = 1;
315 
316   if (IS_TAG_EMPTY(0))
317   {
318      FPU_exception(i, FPU_EX_Stack_Underflow);
319 
320      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
321         BX_NEXT_INSTR(i);
322   }
323   else
324   {
325      float_status_t status =
326          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
327 
328      save_reg = floatx80_to_float32(BX_READ_FPU_REG(0), status);
329 
330      if (FPU_exception(i, status.float_exception_flags, 1))
331         BX_NEXT_INSTR(i);
332   }
333 
334   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
335   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
336 
337   write_virtual_dword(i->seg(), RMAddr(i), save_reg);
338 
339   FPU_PARTIAL_STATUS = x87_sw;
340   if (pop_stack)
341      BX_CPU_THIS_PTR the_i387.FPU_pop();
342 
343   BX_NEXT_INSTR(i);
344 }
345 
FST_DOUBLE_REAL(bxInstruction_c * i)346 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_DOUBLE_REAL(bxInstruction_c *i)
347 {
348   BX_CPU_THIS_PTR prepareFPU(i);
349 
350   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
351 
352   FPU_update_last_instruction(i);
353 
354   Bit16u x87_sw = FPU_PARTIAL_STATUS;
355 
356   clear_C1();
357 
358   float64 save_reg = float64_default_nan; /* The masked response */
359 
360   int pop_stack = 0;
361   if (i->getIaOpcode() == BX_IA_FSTP_DOUBLE_REAL)
362       pop_stack = 1;
363 
364   if (IS_TAG_EMPTY(0))
365   {
366      FPU_exception(i, FPU_EX_Stack_Underflow);
367 
368      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
369         BX_NEXT_INSTR(i);
370   }
371   else
372   {
373      float_status_t status =
374          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
375 
376      save_reg = floatx80_to_float64(BX_READ_FPU_REG(0), status);
377 
378      if (FPU_exception(i, status.float_exception_flags, 1))
379         BX_NEXT_INSTR(i);
380   }
381 
382   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
383   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
384 
385   write_virtual_qword(i->seg(), RMAddr(i), save_reg);
386 
387   FPU_PARTIAL_STATUS = x87_sw;
388   if (pop_stack)
389      BX_CPU_THIS_PTR the_i387.FPU_pop();
390 
391   BX_NEXT_INSTR(i);
392 }
393 
394 /* DB /7 */
FSTP_EXTENDED_REAL(bxInstruction_c * i)395 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i)
396 {
397   BX_CPU_THIS_PTR prepareFPU(i);
398 
399   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
400 
401   FPU_update_last_instruction(i);
402 
403   clear_C1();
404 
405   floatx80 save_reg = floatx80_default_nan; /* The masked response */
406 
407   if (IS_TAG_EMPTY(0))
408   {
409      FPU_exception(i, FPU_EX_Stack_Underflow);
410 
411      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
412         BX_NEXT_INSTR(i);
413   }
414   else
415   {
416      save_reg = BX_READ_FPU_REG(0);
417   }
418 
419   write_virtual_qword(i->seg(), RMAddr(i), save_reg.fraction);
420   write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg.exp);
421 
422   BX_CPU_THIS_PTR the_i387.FPU_pop();
423 
424   BX_NEXT_INSTR(i);
425 }
426 
FIST_WORD_INTEGER(bxInstruction_c * i)427 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_WORD_INTEGER(bxInstruction_c *i)
428 {
429   BX_CPU_THIS_PTR prepareFPU(i);
430 
431   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
432 
433   FPU_update_last_instruction(i);
434 
435   Bit16u x87_sw = FPU_PARTIAL_STATUS;
436 
437   Bit16s save_reg = int16_indefinite;
438 
439   int pop_stack = 0;
440   if (i->getIaOpcode() == BX_IA_FISTP_WORD_INTEGER)
441       pop_stack = 1;
442 
443   clear_C1();
444 
445   if (IS_TAG_EMPTY(0))
446   {
447      FPU_exception(i, FPU_EX_Stack_Underflow);
448 
449      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
450         BX_NEXT_INSTR(i);
451   }
452   else
453   {
454      float_status_t status =
455          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
456 
457      save_reg = floatx80_to_int16(BX_READ_FPU_REG(0), status);
458 
459      if (FPU_exception(i, status.float_exception_flags, 1))
460         BX_NEXT_INSTR(i);
461   }
462 
463   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
464   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
465 
466   write_virtual_word(i->seg(), RMAddr(i), (Bit16u)(save_reg));
467 
468   FPU_PARTIAL_STATUS = x87_sw;
469   if (pop_stack)
470      BX_CPU_THIS_PTR the_i387.FPU_pop();
471 
472   BX_NEXT_INSTR(i);
473 }
474 
FIST_DWORD_INTEGER(bxInstruction_c * i)475 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_DWORD_INTEGER(bxInstruction_c *i)
476 {
477   BX_CPU_THIS_PTR prepareFPU(i);
478 
479   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
480 
481   FPU_update_last_instruction(i);
482 
483   Bit16u x87_sw = FPU_PARTIAL_STATUS;
484 
485   Bit32s save_reg = int32_indefinite; /* The masked response */
486 
487   int pop_stack = 0;
488   if (i->getIaOpcode() == BX_IA_FISTP_DWORD_INTEGER)
489       pop_stack = 1;
490 
491   clear_C1();
492 
493   if (IS_TAG_EMPTY(0))
494   {
495      FPU_exception(i, FPU_EX_Stack_Underflow);
496 
497      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
498         BX_NEXT_INSTR(i);
499   }
500   else
501   {
502      float_status_t status =
503          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
504 
505      save_reg = floatx80_to_int32(BX_READ_FPU_REG(0), status);
506 
507      if (FPU_exception(i, status.float_exception_flags, 1))
508          BX_NEXT_INSTR(i);
509   }
510 
511   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
512   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
513 
514   write_virtual_dword(i->seg(), RMAddr(i), (Bit32u)(save_reg));
515 
516   FPU_PARTIAL_STATUS = x87_sw;
517   if (pop_stack)
518      BX_CPU_THIS_PTR the_i387.FPU_pop();
519 
520   BX_NEXT_INSTR(i);
521 }
522 
FISTP_QWORD_INTEGER(bxInstruction_c * i)523 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTP_QWORD_INTEGER(bxInstruction_c *i)
524 {
525   BX_CPU_THIS_PTR prepareFPU(i);
526 
527   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
528 
529   FPU_update_last_instruction(i);
530 
531   Bit16u x87_sw = FPU_PARTIAL_STATUS;
532 
533   Bit64s save_reg = int64_indefinite; /* The masked response */
534 
535   clear_C1();
536 
537   if (IS_TAG_EMPTY(0))
538   {
539      FPU_exception(i, FPU_EX_Stack_Underflow);
540 
541      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
542         BX_NEXT_INSTR(i);
543   }
544   else
545   {
546      float_status_t status =
547          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
548 
549      save_reg = floatx80_to_int64(BX_READ_FPU_REG(0), status);
550 
551      if (FPU_exception(i, status.float_exception_flags, 1))
552          BX_NEXT_INSTR(i);
553   }
554 
555   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
556   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
557 
558   write_virtual_qword(i->seg(), RMAddr(i), (Bit64u)(save_reg));
559 
560   FPU_PARTIAL_STATUS = x87_sw;
561 
562   BX_CPU_THIS_PTR the_i387.FPU_pop();
563 
564   BX_NEXT_INSTR(i);
565 }
566 
FBSTP_PACKED_BCD(bxInstruction_c * i)567 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i)
568 {
569   BX_CPU_THIS_PTR prepareFPU(i);
570 
571   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
572 
573   FPU_update_last_instruction(i);
574 
575   Bit16u x87_sw = FPU_PARTIAL_STATUS;
576 
577   /*
578    * The packed BCD integer indefinite encoding (FFFFC000000000000000H)
579    * is stored in response to a masked floating-point invalid-operation
580    * exception.
581    */
582   Bit16u save_reg_hi = 0xFFFF;
583   Bit64u save_reg_lo = BX_CONST64(0xC000000000000000);
584 
585   clear_C1();
586 
587   if (IS_TAG_EMPTY(0))
588   {
589      FPU_exception(i, FPU_EX_Stack_Underflow);
590 
591      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
592         BX_NEXT_INSTR(i);
593   }
594   else
595   {
596      float_status_t status =
597         i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
598 
599      floatx80 reg = BX_READ_FPU_REG(0);
600 
601      Bit64s save_val = floatx80_to_int64(reg, status);
602 
603      int sign = (reg.exp & 0x8000) != 0;
604      if (sign)
605         save_val = -save_val;
606 
607      if (save_val > BX_CONST64(999999999999999999)) {
608         status.float_exception_flags = float_flag_invalid; // throw away other flags
609      }
610 
611      if (! (status.float_exception_flags & float_flag_invalid))
612      {
613         save_reg_hi = (sign) ? 0x8000 : 0;
614         save_reg_lo = 0;
615 
616         for (int i=0; i<16; i++) {
617            save_reg_lo += ((Bit64u)(save_val % 10)) << (4*i);
618            save_val /= 10;
619         }
620 
621         save_reg_hi += (Bit16u)(save_val % 10);
622         save_val /= 10;
623         save_reg_hi += (Bit16u)(save_val % 10) << 4;
624     }
625 
626     /* check for fpu arithmetic exceptions */
627     if (FPU_exception(i, status.float_exception_flags, 1))
628         BX_NEXT_INSTR(i);
629   }
630 
631   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
632   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
633 
634   // write packed bcd to memory
635   write_virtual_qword(i->seg(), RMAddr(i), save_reg_lo);
636   write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg_hi);
637 
638   FPU_PARTIAL_STATUS = x87_sw;
639 
640   BX_CPU_THIS_PTR the_i387.FPU_pop();
641 
642   BX_NEXT_INSTR(i);
643 }
644 
645 /* DF /1 */
FISTTP16(bxInstruction_c * i)646 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP16(bxInstruction_c *i)
647 {
648   BX_CPU_THIS_PTR prepareFPU(i);
649 
650   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
651 
652   FPU_update_last_instruction(i);
653 
654   Bit16u x87_sw = FPU_PARTIAL_STATUS;
655 
656   Bit16s save_reg = int16_indefinite; /* The masked response */
657 
658   clear_C1();
659 
660   if (IS_TAG_EMPTY(0))
661   {
662      FPU_exception(i, FPU_EX_Stack_Underflow);
663 
664      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
665         BX_NEXT_INSTR(i);
666   }
667   else
668   {
669      float_status_t status =
670          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
671 
672      save_reg = floatx80_to_int16_round_to_zero(BX_READ_FPU_REG(0), status);
673 
674      if (FPU_exception(i, status.float_exception_flags, 1))
675         BX_NEXT_INSTR(i);
676   }
677 
678   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
679   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
680 
681   write_virtual_word(i->seg(), RMAddr(i), (Bit16u)(save_reg));
682 
683   FPU_PARTIAL_STATUS = x87_sw;
684 
685   BX_CPU_THIS_PTR the_i387.FPU_pop();
686 
687   BX_NEXT_INSTR(i);
688 }
689 
690 /* DB /1 */
FISTTP32(bxInstruction_c * i)691 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP32(bxInstruction_c *i)
692 {
693   BX_CPU_THIS_PTR prepareFPU(i);
694 
695   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
696 
697   FPU_update_last_instruction(i);
698 
699   Bit16u x87_sw = FPU_PARTIAL_STATUS;
700 
701   Bit32s save_reg = int32_indefinite; /* The masked response */
702 
703   clear_C1();
704 
705   if (IS_TAG_EMPTY(0))
706   {
707      FPU_exception(i, FPU_EX_Stack_Underflow);
708 
709      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
710         BX_NEXT_INSTR(i);
711   }
712   else
713   {
714      float_status_t status =
715          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
716 
717      save_reg = floatx80_to_int32_round_to_zero(BX_READ_FPU_REG(0), status);
718 
719      if (FPU_exception(i, status.float_exception_flags, 1))
720         BX_NEXT_INSTR(i);
721   }
722 
723   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
724   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
725 
726   write_virtual_dword(i->seg(), RMAddr(i), (Bit32u)(save_reg));
727 
728   FPU_PARTIAL_STATUS = x87_sw;
729 
730   BX_CPU_THIS_PTR the_i387.FPU_pop();
731 
732   BX_NEXT_INSTR(i);
733 }
734 
735 /* DD /1 */
FISTTP64(bxInstruction_c * i)736 void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP64(bxInstruction_c *i)
737 {
738   BX_CPU_THIS_PTR prepareFPU(i);
739 
740   RMAddr(i) = BX_CPU_RESOLVE_ADDR(i);
741 
742   FPU_update_last_instruction(i);
743 
744   Bit16u x87_sw = FPU_PARTIAL_STATUS;
745 
746   Bit64s save_reg = int64_indefinite; /* The masked response */
747 
748   clear_C1();
749 
750   if (IS_TAG_EMPTY(0))
751   {
752      FPU_exception(i, FPU_EX_Stack_Underflow);
753 
754      if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
755         BX_NEXT_INSTR(i);
756   }
757   else
758   {
759      float_status_t status =
760          i387cw_to_softfloat_status_word(BX_CPU_THIS_PTR the_i387.get_control_word());
761 
762      save_reg = floatx80_to_int64_round_to_zero(BX_READ_FPU_REG(0), status);
763 
764      if (FPU_exception(i, status.float_exception_flags, 1))
765         BX_NEXT_INSTR(i);
766   }
767 
768   // store to the memory might generate an exception, in this case origial FPU_SW must be kept
769   swap_values16u(x87_sw, FPU_PARTIAL_STATUS);
770 
771   write_virtual_qword(i->seg(), RMAddr(i), (Bit64u)(save_reg));
772 
773   FPU_PARTIAL_STATUS = x87_sw;
774 
775   BX_CPU_THIS_PTR the_i387.FPU_pop();
776 
777   BX_NEXT_INSTR(i);
778 }
779 
780 #endif
781