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