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