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