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