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