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