blob: 7edebd424430cd1be6ee8eeb627a6861fe29e630 [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
34*
35* Description: This file contains the code to implement the decoding and
36* emulation of the FPU instructions.
37*
38****************************************************************************/
39
40#include "x86emui.h"
41
42/*----------------------------- Implementation ----------------------------*/
43
44/* opcode=0xd8 */
45void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
46{
47 START_OF_INSTR();
48 DECODE_PRINTF("ESC D8\n");
49 DECODE_CLEAR_SEGOVR();
50 END_OF_INSTR_NO_TRACE();
51}
52
Stefan Reinauerd17fe512011-10-04 10:34:37 -070053#ifdef X86EMU_FPU_PRESENT
54#define X86EMU_FPU_ONLY(x) x
55#else
56#define X86EMU_FPU_ONLY(x) X86EMU_UNUSED(x)
57#endif
58
Myles Watson8e9234f2010-02-19 19:08:11 +000059#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000060
Uwe Hermann01ce6012010-03-05 10:03:50 +000061static const char *x86emu_fpu_op_d9_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000062 "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
63 "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
64
65 "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
66 "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
67
68 "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
69 "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
70};
71
Uwe Hermann01ce6012010-03-05 10:03:50 +000072static const char *x86emu_fpu_op_d9_tab1[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000073 "FLD\t", "FLD\t", "FLD\t", "FLD\t",
74 "FLD\t", "FLD\t", "FLD\t", "FLD\t",
75
76 "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
77 "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
78
79 "FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
80 "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
81
82 "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
83 "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
84
85 "FCHS", "FABS", "ESC_D9", "ESC_D9",
86 "FTST", "FXAM", "ESC_D9", "ESC_D9",
87
88 "FLD1", "FLDL2T", "FLDL2E", "FLDPI",
89 "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
90
91 "F2XM1", "FYL2X", "FPTAN", "FPATAN",
92 "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
93
94 "FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
95 "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
96};
97
Myles Watson8e9234f2010-02-19 19:08:11 +000098#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000099
100/* opcode=0xd9 */
101void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
102{
103 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700104 uint X86EMU_FPU_ONLY(destoffset);
105 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000106
107 START_OF_INSTR();
108 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +0000109#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000110 if (mod != 3) {
111 DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
112 } else {
113 DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
114 }
115#endif
116 switch (mod) {
117 case 0:
118 destoffset = decode_rm00_address(rl);
119 DECODE_PRINTF("\n");
120 break;
121 case 1:
122 destoffset = decode_rm01_address(rl);
123 DECODE_PRINTF("\n");
124 break;
125 case 2:
126 destoffset = decode_rm10_address(rl);
127 DECODE_PRINTF("\n");
128 break;
129 case 3: /* register to register */
130 stkelem = (u8)rl;
131 if (rh < 4) {
132 DECODE_PRINTF2("ST(%d)\n", stkelem);
133 } else {
134 DECODE_PRINTF("\n");
135 }
136 break;
137 }
138#ifdef X86EMU_FPU_PRESENT
139 /* execute */
140 switch (mod) {
141 case 3:
142 switch (rh) {
143 case 0:
144 x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
145 break;
146 case 1:
147 x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
148 break;
149 case 2:
150 switch (rl) {
151 case 0:
152 x86emu_fpu_R_nop();
153 break;
154 default:
155 x86emu_fpu_illegal();
156 break;
157 }
158 case 3:
159 x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
160 break;
161 case 4:
162 switch (rl) {
163 case 0:
164 x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
165 break;
166 case 1:
167 x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
168 break;
169 case 4:
170 x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
171 break;
172 case 5:
173 x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
174 break;
175 default:
176 /* 2,3,6,7 */
177 x86emu_fpu_illegal();
178 break;
179 }
180 break;
181
182 case 5:
183 switch (rl) {
184 case 0:
185 x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
186 break;
187 case 1:
188 x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
189 break;
190 case 2:
191 x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
192 break;
193 case 3:
194 x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
195 break;
196 case 4:
197 x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
198 break;
199 case 5:
200 x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
201 break;
202 case 6:
203 x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
204 break;
205 default:
206 /* 7 */
207 x86emu_fpu_illegal();
208 break;
209 }
210 break;
211
212 case 6:
213 switch (rl) {
214 case 0:
215 x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
216 break;
217 case 1:
218 x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
219 break;
220 case 2:
221 x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
222 break;
223 case 3:
224 x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
225 break;
226 case 4:
227 x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
228 break;
229 case 5:
230 x86emu_fpu_illegal();
231 break;
232 case 6:
233 x86emu_fpu_R_decstp();
234 break;
235 case 7:
236 x86emu_fpu_R_incstp();
237 break;
238 }
239 break;
240
241 case 7:
242 switch (rl) {
243 case 0:
244 x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
245 break;
246 case 1:
247 x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
248 break;
249 case 2:
250 x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
251 break;
252 case 3:
253 x86emu_fpu_illegal();
254 break;
255 case 4:
256 x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
257 break;
258 case 5:
259 x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
260 break;
261 case 6:
262 case 7:
263 default:
264 x86emu_fpu_illegal();
265 break;
266 }
267 break;
268
269 default:
270 switch (rh) {
271 case 0:
272 x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
273 break;
274 case 1:
275 x86emu_fpu_illegal();
276 break;
277 case 2:
278 x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
279 break;
280 case 3:
281 x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
282 break;
283 case 4:
284 x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
285 break;
286 case 5:
287 x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
288 break;
289 case 6:
290 x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
291 break;
292 case 7:
293 x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
294 break;
295 }
296 }
297 }
298#endif /* X86EMU_FPU_PRESENT */
299 DECODE_CLEAR_SEGOVR();
300 END_OF_INSTR_NO_TRACE();
301}
302
Myles Watson8e9234f2010-02-19 19:08:11 +0000303#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000304
Uwe Hermann01ce6012010-03-05 10:03:50 +0000305static const char *x86emu_fpu_op_da_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000306 "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
307 "FICOMP\tDWORD PTR ",
308 "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
309 "FIDIVR\tDWORD PTR ",
310
311 "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
312 "FICOMP\tDWORD PTR ",
313 "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
314 "FIDIVR\tDWORD PTR ",
315
316 "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
317 "FICOMP\tDWORD PTR ",
318 "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
319 "FIDIVR\tDWORD PTR ",
320
321 "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
322 "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
323};
324
Myles Watson8e9234f2010-02-19 19:08:11 +0000325#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000326
327/* opcode=0xda */
328void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
329{
330 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700331 uint X86EMU_FPU_ONLY(destoffset);
332 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000333
334 START_OF_INSTR();
335 FETCH_DECODE_MODRM(mod, rh, rl);
336 DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
337 switch (mod) {
338 case 0:
339 destoffset = decode_rm00_address(rl);
340 DECODE_PRINTF("\n");
341 break;
342 case 1:
343 destoffset = decode_rm01_address(rl);
344 DECODE_PRINTF("\n");
345 break;
346 case 2:
347 destoffset = decode_rm10_address(rl);
348 DECODE_PRINTF("\n");
349 break;
350 case 3: /* register to register */
351 stkelem = (u8)rl;
352 DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
353 break;
354 }
355#ifdef X86EMU_FPU_PRESENT
356 switch (mod) {
357 case 3:
358 x86emu_fpu_illegal();
359 break;
360 default:
361 switch (rh) {
362 case 0:
363 x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
364 break;
365 case 1:
366 x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
367 break;
368 case 2:
369 x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
370 break;
371 case 3:
372 x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
373 break;
374 case 4:
375 x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
376 break;
377 case 5:
378 x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
379 break;
380 case 6:
381 x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
382 break;
383 case 7:
384 x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
385 break;
386 }
387 }
388#endif
389 DECODE_CLEAR_SEGOVR();
390 END_OF_INSTR_NO_TRACE();
391}
392
Myles Watson8e9234f2010-02-19 19:08:11 +0000393#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000394
Uwe Hermann01ce6012010-03-05 10:03:50 +0000395static const char *x86emu_fpu_op_db_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000396 "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
397 "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
398
399 "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
400 "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
401
402 "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
403 "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
404};
405
Myles Watson8e9234f2010-02-19 19:08:11 +0000406#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000407
408/* opcode=0xdb */
409void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
410{
411 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700412 uint X86EMU_FPU_ONLY(destoffset);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000413
414 START_OF_INSTR();
415 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +0000416#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000417 if (mod != 3) {
418 DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
419 } else if (rh == 4) { /* === 11 10 0 nnn */
420 switch (rl) {
421 case 0:
422 DECODE_PRINTF("FENI\n");
423 break;
424 case 1:
425 DECODE_PRINTF("FDISI\n");
426 break;
427 case 2:
428 DECODE_PRINTF("FCLEX\n");
429 break;
430 case 3:
431 DECODE_PRINTF("FINIT\n");
432 break;
433 }
434 } else {
435 DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
436 }
Myles Watson8e9234f2010-02-19 19:08:11 +0000437#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000438 switch (mod) {
439 case 0:
440 destoffset = decode_rm00_address(rl);
441 break;
442 case 1:
443 destoffset = decode_rm01_address(rl);
444 break;
445 case 2:
446 destoffset = decode_rm10_address(rl);
447 break;
448 case 3: /* register to register */
449 break;
450 }
451#ifdef X86EMU_FPU_PRESENT
452 /* execute */
453 switch (mod) {
454 case 3:
455 switch (rh) {
456 case 4:
457 switch (rl) {
458 case 0:
459 x86emu_fpu_R_feni();
460 break;
461 case 1:
462 x86emu_fpu_R_fdisi();
463 break;
464 case 2:
465 x86emu_fpu_R_fclex();
466 break;
467 case 3:
468 x86emu_fpu_R_finit();
469 break;
470 default:
471 x86emu_fpu_illegal();
472 break;
473 }
474 break;
475 default:
476 x86emu_fpu_illegal();
477 break;
478 }
479 break;
480 default:
481 switch (rh) {
482 case 0:
483 x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
484 break;
485 case 1:
486 x86emu_fpu_illegal();
487 break;
488 case 2:
489 x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
490 break;
491 case 3:
492 x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
493 break;
494 case 4:
495 x86emu_fpu_illegal();
496 break;
497 case 5:
498 x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
499 break;
500 case 6:
501 x86emu_fpu_illegal();
502 break;
503 case 7:
504 x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
505 break;
506 }
507 }
508#endif
509 DECODE_CLEAR_SEGOVR();
510 END_OF_INSTR_NO_TRACE();
511}
512
Myles Watson8e9234f2010-02-19 19:08:11 +0000513#ifdef DEBUG
Uwe Hermann01ce6012010-03-05 10:03:50 +0000514static const char *x86emu_fpu_op_dc_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000515 "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
516 "FCOMP\tQWORD PTR ",
517 "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
518 "FDIVR\tQWORD PTR ",
519
520 "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
521 "FCOMP\tQWORD PTR ",
522 "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
523 "FDIVR\tQWORD PTR ",
524
525 "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
526 "FCOMP\tQWORD PTR ",
527 "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
528 "FDIVR\tQWORD PTR ",
529
530 "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
531 "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
532};
Myles Watson8e9234f2010-02-19 19:08:11 +0000533#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000534
535/* opcode=0xdc */
536void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
537{
538 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700539 uint X86EMU_FPU_ONLY(destoffset);
540 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000541
542 START_OF_INSTR();
543 FETCH_DECODE_MODRM(mod, rh, rl);
544 DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
545 switch (mod) {
546 case 0:
547 destoffset = decode_rm00_address(rl);
548 DECODE_PRINTF("\n");
549 break;
550 case 1:
551 destoffset = decode_rm01_address(rl);
552 DECODE_PRINTF("\n");
553 break;
554 case 2:
555 destoffset = decode_rm10_address(rl);
556 DECODE_PRINTF("\n");
557 break;
558 case 3: /* register to register */
559 stkelem = (u8)rl;
560 DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
561 break;
562 }
563#ifdef X86EMU_FPU_PRESENT
564 /* execute */
565 switch (mod) {
566 case 3:
567 switch (rh) {
568 case 0:
569 x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
570 break;
571 case 1:
572 x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
573 break;
574 case 2:
575 x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
576 break;
577 case 3:
578 x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
579 break;
580 case 4:
581 x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
582 break;
583 case 5:
584 x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
585 break;
586 case 6:
587 x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
588 break;
589 case 7:
590 x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
591 break;
592 }
593 break;
594 default:
595 switch (rh) {
596 case 0:
597 x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
598 break;
599 case 1:
600 x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
601 break;
602 case 2:
603 x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
604 break;
605 case 3:
606 x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
607 break;
608 case 4:
609 x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
610 break;
611 case 5:
612 x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
613 break;
614 case 6:
615 x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
616 break;
617 case 7:
618 x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
619 break;
620 }
621 }
622#endif
623 DECODE_CLEAR_SEGOVR();
624 END_OF_INSTR_NO_TRACE();
625}
626
Myles Watson8e9234f2010-02-19 19:08:11 +0000627#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000628
Uwe Hermann01ce6012010-03-05 10:03:50 +0000629static const char *x86emu_fpu_op_dd_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000630 "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
631 "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
632
633 "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
634 "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
635
636 "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
637 "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
638
639 "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
640 "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
641};
642
Myles Watson8e9234f2010-02-19 19:08:11 +0000643#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000644
645/* opcode=0xdd */
646void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
647{
648 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700649 uint X86EMU_FPU_ONLY(destoffset);
650 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000651
652 START_OF_INSTR();
653 FETCH_DECODE_MODRM(mod, rh, rl);
654 DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
655 switch (mod) {
656 case 0:
657 destoffset = decode_rm00_address(rl);
658 DECODE_PRINTF("\n");
659 break;
660 case 1:
661 destoffset = decode_rm01_address(rl);
662 DECODE_PRINTF("\n");
663 break;
664 case 2:
665 destoffset = decode_rm10_address(rl);
666 DECODE_PRINTF("\n");
667 break;
668 case 3: /* register to register */
669 stkelem = (u8)rl;
670 DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
671 break;
672 }
673#ifdef X86EMU_FPU_PRESENT
674 switch (mod) {
675 case 3:
676 switch (rh) {
677 case 0:
678 x86emu_fpu_R_ffree(stkelem);
679 break;
680 case 1:
681 x86emu_fpu_R_fxch(stkelem);
682 break;
683 case 2:
684 x86emu_fpu_R_fst(stkelem); /* register version */
685 break;
686 case 3:
687 x86emu_fpu_R_fstp(stkelem); /* register version */
688 break;
689 default:
690 x86emu_fpu_illegal();
691 break;
692 }
693 break;
694 default:
695 switch (rh) {
696 case 0:
697 x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
698 break;
699 case 1:
700 x86emu_fpu_illegal();
701 break;
702 case 2:
703 x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
704 break;
705 case 3:
706 x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
707 break;
708 case 4:
709 x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
710 break;
711 case 5:
712 x86emu_fpu_illegal();
713 break;
714 case 6:
715 x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
716 break;
717 case 7:
718 x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
719 break;
720 }
721 }
722#endif
723 DECODE_CLEAR_SEGOVR();
724 END_OF_INSTR_NO_TRACE();
725}
726
Myles Watson8e9234f2010-02-19 19:08:11 +0000727#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000728
Uwe Hermann01ce6012010-03-05 10:03:50 +0000729static const char *x86emu_fpu_op_de_tab[] =
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000730{
731 "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
732 "FICOMP\tWORD PTR ",
733 "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
734 "FIDIVR\tWORD PTR ",
735
736 "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
737 "FICOMP\tWORD PTR ",
738 "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
739 "FIDIVR\tWORD PTR ",
740
741 "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
742 "FICOMP\tWORD PTR ",
743 "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
744 "FIDIVR\tWORD PTR ",
745
746 "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
747 "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
748};
749
Myles Watson8e9234f2010-02-19 19:08:11 +0000750#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000751
752/* opcode=0xde */
753void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
754{
755 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700756 uint X86EMU_FPU_ONLY(destoffset);
757 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000758
759 START_OF_INSTR();
760 FETCH_DECODE_MODRM(mod, rh, rl);
761 DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
762 switch (mod) {
763 case 0:
764 destoffset = decode_rm00_address(rl);
765 DECODE_PRINTF("\n");
766 break;
767 case 1:
768 destoffset = decode_rm01_address(rl);
769 DECODE_PRINTF("\n");
770 break;
771 case 2:
772 destoffset = decode_rm10_address(rl);
773 DECODE_PRINTF("\n");
774 break;
775 case 3: /* register to register */
776 stkelem = (u8)rl;
777 DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
778 break;
779 }
780#ifdef X86EMU_FPU_PRESENT
781 switch (mod) {
782 case 3:
783 switch (rh) {
784 case 0:
785 x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
786 break;
787 case 1:
788 x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
789 break;
790 case 2:
791 x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
792 break;
793 case 3:
794 if (stkelem == 1)
795 x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
796 else
797 x86emu_fpu_illegal();
798 break;
799 case 4:
800 x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
801 break;
802 case 5:
803 x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
804 break;
805 case 6:
806 x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
807 break;
808 case 7:
809 x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
810 break;
811 }
812 break;
813 default:
814 switch (rh) {
815 case 0:
816 x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
817 break;
818 case 1:
819 x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
820 break;
821 case 2:
822 x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
823 break;
824 case 3:
825 x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
826 break;
827 case 4:
828 x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
829 break;
830 case 5:
831 x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
832 break;
833 case 6:
834 x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
835 break;
836 case 7:
837 x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
838 break;
839 }
840 }
841#endif
842 DECODE_CLEAR_SEGOVR();
843 END_OF_INSTR_NO_TRACE();
844}
845
Myles Watson8e9234f2010-02-19 19:08:11 +0000846#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000847
Uwe Hermann01ce6012010-03-05 10:03:50 +0000848static const char *x86emu_fpu_op_df_tab[] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000849 /* mod == 00 */
850 "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
851 "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
852 "FISTP\tQWORD PTR ",
853
854 /* mod == 01 */
855 "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
856 "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
857 "FISTP\tQWORD PTR ",
858
859 /* mod == 10 */
860 "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
861 "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
862 "FISTP\tQWORD PTR ",
863
864 /* mod == 11 */
865 "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
866 "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
867};
868
Myles Watson8e9234f2010-02-19 19:08:11 +0000869#endif /* DEBUG */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000870
871/* opcode=0xdf */
872void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
873{
874 int mod, rl, rh;
Stefan Reinauerd17fe512011-10-04 10:34:37 -0700875 uint X86EMU_FPU_ONLY(destoffset);
876 u8 X86EMU_FPU_ONLY(stkelem);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000877
878 START_OF_INSTR();
879 FETCH_DECODE_MODRM(mod, rh, rl);
880 DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
881 switch (mod) {
882 case 0:
883 destoffset = decode_rm00_address(rl);
884 DECODE_PRINTF("\n");
885 break;
886 case 1:
887 destoffset = decode_rm01_address(rl);
888 DECODE_PRINTF("\n");
889 break;
890 case 2:
891 destoffset = decode_rm10_address(rl);
892 DECODE_PRINTF("\n");
893 break;
894 case 3: /* register to register */
895 stkelem = (u8)rl;
896 DECODE_PRINTF2("\tST(%d)\n", stkelem);
897 break;
898 }
899#ifdef X86EMU_FPU_PRESENT
900 switch (mod) {
901 case 3:
902 switch (rh) {
903 case 0:
904 x86emu_fpu_R_ffree(stkelem);
905 break;
906 case 1:
907 x86emu_fpu_R_fxch(stkelem);
908 break;
909 case 2:
910 x86emu_fpu_R_fst(stkelem); /* register version */
911 break;
912 case 3:
913 x86emu_fpu_R_fstp(stkelem); /* register version */
914 break;
915 default:
916 x86emu_fpu_illegal();
917 break;
918 }
919 break;
920 default:
921 switch (rh) {
922 case 0:
923 x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
924 break;
925 case 1:
926 x86emu_fpu_illegal();
927 break;
928 case 2:
929 x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
930 break;
931 case 3:
932 x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
933 break;
934 case 4:
935 x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
936 break;
937 case 5:
938 x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
939 break;
940 case 6:
941 x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
942 break;
943 case 7:
944 x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
945 break;
946 }
947 }
948#endif
949 DECODE_CLEAR_SEGOVR();
950 END_OF_INSTR_NO_TRACE();
951}