1 /*
2 * Copyright (C) 2002-2021 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #ifndef DOSBOX_DYN_FPU_H
20 #define DOSBOX_DYN_FPU_H
21
22 #include "dosbox.h"
23
24 #if C_FPU
25
26 #include <math.h>
27 #include <float.h>
28 #include "cross.h"
29 #include "mem.h"
30 #include "fpu.h"
31 #include "cpu.h"
32
33
FPU_FDECSTP()34 static void FPU_FDECSTP(){
35 TOP = (TOP - 1) & 7;
36 }
37
FPU_FINCSTP()38 static void FPU_FINCSTP(){
39 TOP = (TOP + 1) & 7;
40 }
41
FPU_FNSTCW(PhysPt addr)42 static void FPU_FNSTCW(PhysPt addr){
43 mem_writew(addr,fpu.cw);
44 }
45
FPU_FFREE(Bitu st)46 static void FPU_FFREE(Bitu st) {
47 fpu.tags[st]=TAG_Empty;
48 }
49
50
51 #if C_FPU_X86
52 #include "../../fpu/fpu_instructions_x86.h"
53 #else
54 #include "../../fpu/fpu_instructions.h"
55 #endif
56
57
58 #define dyn_fpu_top() { \
59 gen_protectflags(); \
60 gen_load_host(&TOP,DREG(EA),4); \
61 gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm); \
62 gen_dop_word_imm(DOP_AND,true,DREG(EA),7); \
63 gen_load_host(&TOP,DREG(TMPB),4); \
64 }
65
dyn_eatree()66 static void dyn_eatree()
67 {
68 const unsigned group = (decode.modrm.val >> 3) & 7;
69 switch (group) {
70 case 0x00: /* FADD ST,STi */
71 gen_call_function((void*)&FPU_FADD_EA,"%Drd",DREG(TMPB));
72 break;
73 case 0x01: /* FMUL ST,STi */
74 gen_call_function((void*)&FPU_FMUL_EA,"%Drd",DREG(TMPB));
75 break;
76 case 0x02: /* FCOM STi */
77 gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
78 break;
79 case 0x03: /* FCOMP STi */
80 gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
81 gen_call_function((void*)&FPU_FPOP,"");
82 break;
83 case 0x04: /* FSUB ST,STi */
84 gen_call_function((void*)&FPU_FSUB_EA,"%Drd",DREG(TMPB));
85 break;
86 case 0x05: /* FSUBR ST,STi */
87 gen_call_function((void*)&FPU_FSUBR_EA,"%Drd",DREG(TMPB));
88 break;
89 case 0x06: /* FDIV ST,STi */
90 gen_call_function((void*)&FPU_FDIV_EA,"%Drd",DREG(TMPB));
91 break;
92 case 0x07: /* FDIVR ST,STi */
93 gen_call_function((void*)&FPU_FDIVR_EA,"%Drd",DREG(TMPB));
94 break;
95 default:
96 break;
97 }
98 }
99
dyn_fpu_esc0()100 static void dyn_fpu_esc0()
101 {
102 dyn_get_modrm();
103 if (decode.modrm.val >= 0xc0) {
104 dyn_fpu_top();
105 const unsigned group = (decode.modrm.val >> 3) & 7;
106 switch (group) {
107 case 0x00: //FADD ST,STi /
108 gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(TMPB),DREG(EA));
109 break;
110 case 0x01: // FMUL ST,STi /
111 gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(TMPB),DREG(EA));
112 break;
113 case 0x02: // FCOM STi /
114 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
115 break;
116 case 0x03: // FCOMP STi /
117 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
118 gen_call_function((void*)&FPU_FPOP,"");
119 break;
120 case 0x04: // FSUB ST,STi /
121 gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(TMPB),DREG(EA));
122 break;
123 case 0x05: // FSUBR ST,STi /
124 gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(TMPB),DREG(EA));
125 break;
126 case 0x06: // FDIV ST,STi /
127 gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(TMPB),DREG(EA));
128 break;
129 case 0x07: // FDIVR ST,STi /
130 gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(TMPB),DREG(EA));
131 break;
132 default:
133 break;
134 }
135 } else {
136 dyn_fill_ea();
137 gen_call_function((void*)&FPU_FLD_F32_EA,"%Drd",DREG(EA));
138 gen_load_host(&TOP,DREG(TMPB),4);
139 dyn_eatree();
140 }
141 }
142
dyn_fpu_esc1()143 static void dyn_fpu_esc1()
144 {
145 dyn_get_modrm();
146 const unsigned group = (decode.modrm.val >> 3) & 7;
147 const unsigned sub = (decode.modrm.val & 7);
148 if (decode.modrm.val >= 0xc0) {
149 switch (group) {
150 case 0x00: /* FLD STi */
151 gen_protectflags();
152 gen_load_host(&TOP,DREG(EA),4);
153 gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm);
154 gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
155 gen_call_function((void*)&FPU_PREP_PUSH,"");
156 gen_load_host(&TOP,DREG(TMPB),4);
157 gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(EA),DREG(TMPB));
158 break;
159 case 0x01: /* FXCH STi */
160 dyn_fpu_top();
161 gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
162 break;
163 case 0x02: /* FNOP */
164 gen_call_function((void*)&FPU_FNOP,"");
165 break;
166 case 0x03: /* FSTP STi */
167 dyn_fpu_top();
168 gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
169 gen_call_function((void*)&FPU_FPOP,"");
170 break;
171 case 0x04:
172 switch(sub){
173 case 0x00: /* FCHS */
174 gen_call_function((void*)&FPU_FCHS,"");
175 break;
176 case 0x01: /* FABS */
177 gen_call_function((void*)&FPU_FABS,"");
178 break;
179 case 0x02: /* UNKNOWN */
180 case 0x03: /* ILLEGAL */
181 FPU_LOG_WARN(1,false,group,sub);
182 break;
183 case 0x04: /* FTST */
184 gen_call_function((void*)&FPU_FTST,"");
185 break;
186 case 0x05: /* FXAM */
187 gen_call_function((void*)&FPU_FXAM,"");
188 break;
189 case 0x06: /* FTSTP (cyrix)*/
190 case 0x07: /* UNKNOWN */
191 FPU_LOG_WARN(1,false,group,sub);
192 break;
193 }
194 break;
195 case 0x05:
196 switch(sub){
197 case 0x00: /* FLD1 */
198 gen_call_function((void*)&FPU_FLD1,"");
199 break;
200 case 0x01: /* FLDL2T */
201 gen_call_function((void*)&FPU_FLDL2T,"");
202 break;
203 case 0x02: /* FLDL2E */
204 gen_call_function((void*)&FPU_FLDL2E,"");
205 break;
206 case 0x03: /* FLDPI */
207 gen_call_function((void*)&FPU_FLDPI,"");
208 break;
209 case 0x04: /* FLDLG2 */
210 gen_call_function((void*)&FPU_FLDLG2,"");
211 break;
212 case 0x05: /* FLDLN2 */
213 gen_call_function((void*)&FPU_FLDLN2,"");
214 break;
215 case 0x06: /* FLDZ*/
216 gen_call_function((void*)&FPU_FLDZ,"");
217 break;
218 case 0x07: /* ILLEGAL */
219 FPU_LOG_WARN(1,false,group,sub);
220 break;
221 }
222 break;
223 case 0x06:
224 switch(sub){
225 case 0x00: /* F2XM1 */
226 gen_call_function((void*)&FPU_F2XM1,"");
227 break;
228 case 0x01: /* FYL2X */
229 gen_call_function((void*)&FPU_FYL2X,"");
230 break;
231 case 0x02: /* FPTAN */
232 gen_call_function((void*)&FPU_FPTAN,"");
233 break;
234 case 0x03: /* FPATAN */
235 gen_call_function((void*)&FPU_FPATAN,"");
236 break;
237 case 0x04: /* FXTRACT */
238 gen_call_function((void*)&FPU_FXTRACT,"");
239 break;
240 case 0x05: /* FPREM1 */
241 gen_call_function((void*)&FPU_FPREM1,"");
242 break;
243 case 0x06: /* FDECSTP */
244 gen_call_function((void*)&FPU_FDECSTP,"");
245 break;
246 case 0x07: /* FINCSTP */
247 gen_call_function((void*)&FPU_FINCSTP,"");
248 break;
249 default:
250 FPU_LOG_WARN(1,false,group,sub);
251 break;
252 }
253 break;
254 case 0x07:
255 switch(sub){
256 case 0x00: /* FPREM */
257 gen_call_function((void*)&FPU_FPREM,"");
258 break;
259 case 0x01: /* FYL2XP1 */
260 gen_call_function((void*)&FPU_FYL2XP1,"");
261 break;
262 case 0x02: /* FSQRT */
263 gen_call_function((void*)&FPU_FSQRT,"");
264 break;
265 case 0x03: /* FSINCOS */
266 gen_call_function((void*)&FPU_FSINCOS,"");
267 break;
268 case 0x04: /* FRNDINT */
269 gen_call_function((void*)&FPU_FRNDINT,"");
270 break;
271 case 0x05: /* FSCALE */
272 gen_call_function((void*)&FPU_FSCALE,"");
273 break;
274 case 0x06: /* FSIN */
275 gen_call_function((void*)&FPU_FSIN,"");
276 break;
277 case 0x07: /* FCOS */
278 gen_call_function((void*)&FPU_FCOS,"");
279 break;
280 default:
281 FPU_LOG_WARN(1,false,group,sub);
282 break;
283 }
284 break;
285 default:
286 FPU_LOG_WARN(1,false,group,sub);
287 break;
288 }
289 } else {
290 dyn_fill_ea();
291 switch (group) {
292 case 0x00: /* FLD float*/
293 gen_protectflags();
294 gen_call_function((void*)&FPU_PREP_PUSH,"");
295 gen_load_host(&TOP,DREG(TMPB),4);
296 gen_call_function((void*)&FPU_FLD_F32,"%Drd%Drd",DREG(EA),DREG(TMPB));
297 break;
298 case 0x01: /* UNKNOWN */
299 FPU_LOG_WARN(1,true,group,sub);
300 break;
301 case 0x02: /* FST float*/
302 gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
303 break;
304 case 0x03: /* FSTP float*/
305 gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
306 gen_call_function((void*)&FPU_FPOP,"");
307 break;
308 case 0x04: /* FLDENV */
309 gen_call_function((void*)&FPU_FLDENV,"%Drd",DREG(EA));
310 break;
311 case 0x05: /* FLDCW */
312 gen_call_function((void *)&FPU_FLDCW,"%Drd",DREG(EA));
313 break;
314 case 0x06: /* FSTENV */
315 gen_call_function((void *)&FPU_FSTENV,"%Drd",DREG(EA));
316 break;
317 case 0x07: /* FNSTCW*/
318 gen_call_function((void *)&FPU_FNSTCW,"%Drd",DREG(EA));
319 break;
320 default:
321 FPU_LOG_WARN(1,true,group,sub);
322 break;
323 }
324 }
325 }
326
dyn_fpu_esc2()327 static void dyn_fpu_esc2()
328 {
329 dyn_get_modrm();
330 if (decode.modrm.val >= 0xc0) {
331 const unsigned group = (decode.modrm.val >> 3) & 7;
332 const unsigned sub = (decode.modrm.val & 7);
333 switch (group) {
334 case 0x05:
335 switch (sub) {
336 case 0x01: /* FUCOMPP */
337 gen_protectflags();
338 gen_load_host(&TOP,DREG(EA),4);
339 gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
340 gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
341 gen_load_host(&TOP,DREG(TMPB),4);
342 gen_call_function((void *)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
343 gen_call_function((void *)&FPU_FPOP,"");
344 gen_call_function((void *)&FPU_FPOP,"");
345 break;
346 default:
347 FPU_LOG_WARN(2,false,5,sub);
348 break;
349 }
350 break;
351 default:
352 FPU_LOG_WARN(2,false,group,sub);
353 break;
354 }
355 } else {
356 dyn_fill_ea();
357 gen_call_function((void*)&FPU_FLD_I32_EA,"%Drd",DREG(EA));
358 gen_load_host(&TOP,DREG(TMPB),4);
359 dyn_eatree();
360 }
361 }
362
dyn_fpu_esc3()363 static void dyn_fpu_esc3()
364 {
365 dyn_get_modrm();
366 const unsigned group = (decode.modrm.val >> 3) & 7;
367 const unsigned sub = (decode.modrm.val & 7);
368 if (decode.modrm.val >= 0xc0) {
369 switch (group) {
370 case 0x04:
371 switch (sub) {
372 case 0x00: //FNENI
373 case 0x01: //FNDIS
374 LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfunction: %u", sub);
375 break;
376 case 0x02: //FNCLEX FCLEX
377 gen_call_function((void*)&FPU_FCLEX,"");
378 break;
379 case 0x03: //FNINIT FINIT
380 gen_call_function((void*)&FPU_FINIT,"");
381 break;
382 case 0x04: //FNSETPM
383 case 0x05: //FRSTPM
384 // LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
385 break;
386 default:
387 E_Exit("ESC 3:ILLEGAL OPCODE group %u subfunction %u", group, sub);
388 }
389 break;
390 default:
391 FPU_LOG_WARN(3, false, group, sub);
392 break;
393 }
394 } else {
395 dyn_fill_ea();
396 switch (group) {
397 case 0x00: /* FILD */
398 gen_call_function((void*)&FPU_PREP_PUSH,"");
399 gen_protectflags();
400 gen_load_host(&TOP,DREG(TMPB),4);
401 gen_call_function((void*)&FPU_FLD_I32,"%Drd%Drd",DREG(EA),DREG(TMPB));
402 break;
403 case 0x01: /* FISTTP */
404 FPU_LOG_WARN(3, false, 1, sub);
405 break;
406 case 0x02: /* FIST */
407 gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
408 break;
409 case 0x03: /* FISTP */
410 gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
411 gen_call_function((void*)&FPU_FPOP,"");
412 break;
413 case 0x05: /* FLD 80 Bits Real */
414 gen_call_function((void*)&FPU_PREP_PUSH,"");
415 gen_call_function((void*)&FPU_FLD_F80,"%Drd",DREG(EA));
416 break;
417 case 0x07: /* FSTP 80 Bits Real */
418 gen_call_function((void*)&FPU_FST_F80,"%Drd",DREG(EA));
419 gen_call_function((void*)&FPU_FPOP,"");
420 break;
421 default:
422 FPU_LOG_WARN(3, true, group, sub);
423 break;
424 }
425 }
426 }
427
dyn_fpu_esc4()428 static void dyn_fpu_esc4()
429 {
430 dyn_get_modrm();
431 const unsigned group = (decode.modrm.val >> 3) & 7;
432 if (decode.modrm.val >= 0xc0) {
433 dyn_fpu_top();
434 switch (group) {
435 case 0x00: /* FADD STi,ST*/
436 gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
437 break;
438 case 0x01: /* FMUL STi,ST*/
439 gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
440 break;
441 case 0x02: /* FCOM*/
442 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
443 break;
444 case 0x03: /* FCOMP*/
445 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
446 gen_call_function((void*)&FPU_FPOP,"");
447 break;
448 case 0x04: /* FSUBR STi,ST*/
449 gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
450 break;
451 case 0x05: /* FSUB STi,ST*/
452 gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
453 break;
454 case 0x06: /* FDIVR STi,ST*/
455 gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
456 break;
457 case 0x07: /* FDIV STi,ST*/
458 gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
459 break;
460 default:
461 break;
462 }
463 } else {
464 dyn_fill_ea();
465 gen_call_function((void*)&FPU_FLD_F64_EA,"%Drd",DREG(EA));
466 gen_load_host(&TOP,DREG(TMPB),4);
467 dyn_eatree();
468 }
469 }
470
dyn_fpu_esc5()471 static void dyn_fpu_esc5()
472 {
473 dyn_get_modrm();
474 const unsigned group = (decode.modrm.val >> 3) & 7;
475 const unsigned sub = (decode.modrm.val & 7);
476 if (decode.modrm.val >= 0xc0) {
477 dyn_fpu_top();
478 switch (group) {
479 case 0x00: /* FFREE STi */
480 gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
481 break;
482 case 0x01: /* FXCH STi*/
483 gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
484 break;
485 case 0x02: /* FST STi */
486 gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
487 break;
488 case 0x03: /* FSTP STi*/
489 gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
490 gen_call_function((void*)&FPU_FPOP,"");
491 break;
492 case 0x04: /* FUCOM STi */
493 gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
494 break;
495 case 0x05: /*FUCOMP STi */
496 gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
497 gen_call_function((void*)&FPU_FPOP,"");
498 break;
499 default:
500 FPU_LOG_WARN(5,false,group,sub);
501 break;
502 }
503 gen_releasereg(DREG(EA));
504 gen_releasereg(DREG(TMPB));
505 } else {
506 dyn_fill_ea();
507 switch (group) {
508 case 0x00: /* FLD double real*/
509 gen_call_function((void*)&FPU_PREP_PUSH,"");
510 gen_protectflags();
511 gen_load_host(&TOP,DREG(TMPB),4);
512 gen_call_function((void*)&FPU_FLD_F64,"%Drd%Drd",DREG(EA),DREG(TMPB));
513 break;
514 case 0x01: /* FISTTP longint*/
515 FPU_LOG_WARN(5,true,1,sub);
516 break;
517 case 0x02: /* FST double real*/
518 gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
519 break;
520 case 0x03: /* FSTP double real*/
521 gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
522 gen_call_function((void*)&FPU_FPOP,"");
523 break;
524 case 0x04: /* FRSTOR */
525 gen_call_function((void*)&FPU_FRSTOR,"%Drd",DREG(EA));
526 break;
527 case 0x06: /* FSAVE */
528 gen_call_function((void*)&FPU_FSAVE,"%Drd",DREG(EA));
529 break;
530 case 0x07: /*FNSTSW */
531 gen_protectflags();
532 gen_load_host(&TOP,DREG(TMPB),4);
533 gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB));
534 gen_load_host(&fpu.sw,DREG(TMPB),4);
535 gen_call_function((void*)&mem_writew,"%Drd%Drd",DREG(EA),DREG(TMPB));
536 break;
537 default:
538 FPU_LOG_WARN(5,true,group,sub);
539 break;
540 }
541 }
542 }
543
dyn_fpu_esc6()544 static void dyn_fpu_esc6()
545 {
546 dyn_get_modrm();
547 const unsigned group = (decode.modrm.val >> 3) & 7;
548 const unsigned sub = (decode.modrm.val & 7);
549 if (decode.modrm.val >= 0xc0) {
550 dyn_fpu_top();
551 switch (group) {
552 case 0x00: /*FADDP STi,ST*/
553 gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
554 break;
555 case 0x01: /* FMULP STi,ST*/
556 gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
557 break;
558 case 0x02: /* FCOMP5*/
559 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
560 break; /* TODO IS THIS ALLRIGHT ????????? */
561 case 0x03: /*FCOMPP*/
562 if(sub != 1) {
563 FPU_LOG_WARN(6,false,3,sub);
564 return;
565 }
566 gen_load_host(&TOP,DREG(EA),4);
567 gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
568 gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
569 gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
570 gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/
571 break;
572 case 0x04: /* FSUBRP STi,ST*/
573 gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
574 break;
575 case 0x05: /* FSUBP STi,ST*/
576 gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
577 break;
578 case 0x06: /* FDIVRP STi,ST*/
579 gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
580 break;
581 case 0x07: /* FDIVP STi,ST*/
582 gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
583 break;
584 default:
585 break;
586 }
587 gen_call_function((void *)&FPU_FPOP, "");
588 } else {
589 dyn_fill_ea();
590 gen_call_function((void*)&FPU_FLD_I16_EA,"%Drd",DREG(EA));
591 gen_load_host(&TOP,DREG(TMPB),4);
592 dyn_eatree();
593 }
594 }
595
dyn_fpu_esc7()596 static void dyn_fpu_esc7()
597 {
598 dyn_get_modrm();
599 const unsigned group = (decode.modrm.val >> 3) & 7;
600 const unsigned sub = (decode.modrm.val & 7);
601 if (decode.modrm.val >= 0xc0) {
602 switch (group) {
603 case 0x00: /* FFREEP STi*/
604 dyn_fpu_top();
605 gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
606 gen_call_function((void*)&FPU_FPOP,"");
607 break;
608 case 0x01: /* FXCH STi*/
609 dyn_fpu_top();
610 gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
611 break;
612 case 0x02: /* FSTP STi*/
613 case 0x03: /* FSTP STi*/
614 dyn_fpu_top();
615 gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
616 gen_call_function((void*)&FPU_FPOP,"");
617 break;
618 case 0x04:
619 switch(sub){
620 case 0x00: /* FNSTSW AX*/
621 gen_load_host(&TOP,DREG(TMPB),4);
622 gen_call_function((void*)&FPU_SET_TOP,"%Drd",DREG(TMPB));
623 gen_mov_host(&fpu.sw,DREG(EAX),2);
624 break;
625 default:
626 FPU_LOG_WARN(7,false,4,sub);
627 break;
628 }
629 break;
630 default:
631 FPU_LOG_WARN(7,false,group,sub);
632 break;
633 }
634 } else {
635 dyn_fill_ea();
636 switch (group) {
637 case 0x00: /* FILD Bit16s */
638 gen_call_function((void*)&FPU_PREP_PUSH,"");
639 gen_load_host(&TOP,DREG(TMPB),4);
640 gen_call_function((void*)&FPU_FLD_I16,"%Drd%Drd",DREG(EA),DREG(TMPB));
641 break;
642 case 0x01:
643 FPU_LOG_WARN(7,true,group,sub);
644 break;
645 case 0x02: /* FIST Bit16s */
646 gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
647 break;
648 case 0x03: /* FISTP Bit16s */
649 gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
650 gen_call_function((void*)&FPU_FPOP,"");
651 break;
652 case 0x04: /* FBLD packed BCD */
653 gen_call_function((void*)&FPU_PREP_PUSH,"");
654 gen_load_host(&TOP,DREG(TMPB),4);
655 gen_call_function((void*)&FPU_FBLD,"%Drd%Drd",DREG(EA),DREG(TMPB));
656 break;
657 case 0x05: /* FILD Bit64s */
658 gen_call_function((void*)&FPU_PREP_PUSH,"");
659 gen_load_host(&TOP,DREG(TMPB),4);
660 gen_call_function((void*)&FPU_FLD_I64,"%Drd%Drd",DREG(EA),DREG(TMPB));
661 break;
662 case 0x06: /* FBSTP packed BCD */
663 gen_call_function((void*)&FPU_FBST,"%Drd",DREG(EA));
664 gen_call_function((void*)&FPU_FPOP,"");
665 break;
666 case 0x07: /* FISTP Bit64s */
667 gen_call_function((void*)&FPU_FST_I64,"%Drd",DREG(EA));
668 gen_call_function((void*)&FPU_FPOP,"");
669 break;
670 default:
671 FPU_LOG_WARN(7,true,group,sub);
672 break;
673 }
674 }
675 }
676
677 #endif // C_FPU
678
679 #endif
680