coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fpu.c
Go to the documentation of this file.
1 /****************************************************************************
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 */
46 {
48  DECODE_PRINTF("ESC D8\n");
51 }
52 
53 #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 
59 #ifdef DEBUG
60 
61 static const char *x86emu_fpu_op_d9_tab[] = {
62  "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 
72 static const char *x86emu_fpu_op_d9_tab1[] = {
73  "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 
98 #endif /* DEBUG */
99 
100 /* opcode=0xd9 */
102 {
103  int mod, rl, rh;
104  uint X86EMU_FPU_ONLY(destoffset);
105  u8 X86EMU_FPU_ONLY(stkelem);
106 
107  START_OF_INSTR();
108  FETCH_DECODE_MODRM(mod, rh, rl);
109 #ifdef DEBUG
110  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 */
301 }
302 
303 #ifdef DEBUG
304 
305 static const char *x86emu_fpu_op_da_tab[] = {
306  "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 
325 #endif /* DEBUG */
326 
327 /* opcode=0xda */
329 {
330  int mod, rl, rh;
331  uint X86EMU_FPU_ONLY(destoffset);
332  u8 X86EMU_FPU_ONLY(stkelem);
333 
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
391 }
392 
393 #ifdef DEBUG
394 
395 static const char *x86emu_fpu_op_db_tab[] = {
396  "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 
406 #endif /* DEBUG */
407 
408 /* opcode=0xdb */
410 {
411  int mod, rl, rh;
412  uint X86EMU_FPU_ONLY(destoffset);
413 
414  START_OF_INSTR();
415  FETCH_DECODE_MODRM(mod, rh, rl);
416 #ifdef DEBUG
417  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  }
437 #endif /* DEBUG */
438  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
511 }
512 
513 #ifdef DEBUG
514 static const char *x86emu_fpu_op_dc_tab[] = {
515  "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 };
533 #endif /* DEBUG */
534 
535 /* opcode=0xdc */
537 {
538  int mod, rl, rh;
539  uint X86EMU_FPU_ONLY(destoffset);
540  u8 X86EMU_FPU_ONLY(stkelem);
541 
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
625 }
626 
627 #ifdef DEBUG
628 
629 static const char *x86emu_fpu_op_dd_tab[] = {
630  "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 
643 #endif /* DEBUG */
644 
645 /* opcode=0xdd */
647 {
648  int mod, rl, rh;
649  uint X86EMU_FPU_ONLY(destoffset);
650  u8 X86EMU_FPU_ONLY(stkelem);
651 
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
725 }
726 
727 #ifdef DEBUG
728 
729 static const char *x86emu_fpu_op_de_tab[] =
730 {
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 
750 #endif /* DEBUG */
751 
752 /* opcode=0xde */
754 {
755  int mod, rl, rh;
756  uint X86EMU_FPU_ONLY(destoffset);
757  u8 X86EMU_FPU_ONLY(stkelem);
758 
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
844 }
845 
846 #ifdef DEBUG
847 
848 static const char *x86emu_fpu_op_df_tab[] = {
849  /* 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 
869 #endif /* DEBUG */
870 
871 /* opcode=0xdf */
873 {
874  int mod, rl, rh;
875  uint X86EMU_FPU_ONLY(destoffset);
876  u8 X86EMU_FPU_ONLY(stkelem);
877 
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
951 }
unsigned int decode_rm01_address(int rm)
Definition: decode.c:957
unsigned int decode_rm10_address(int rm)
Definition: decode.c:1046
unsigned int decode_rm00_address(int rm)
Definition: decode.c:877
#define FETCH_DECODE_MODRM(mod, rh, rl)
Definition: decode.h:46
#define DECODE_CLEAR_SEGOVR()
Definition: decode.h:50
unsigned int uint
Definition: types.h:44
#define END_OF_INSTR_NO_TRACE()
Definition: debug.h:169
#define START_OF_INSTR()
Definition: debug.h:167
#define DECODE_PRINTF(x)
Definition: debug.h:136
#define DECODE_PRINTF2(x, y)
Definition: debug.h:137
#define X86EMU_FPU_ONLY(x)
Definition: fpu.c:56
void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:872
void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:328
void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:45
void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:753
void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:101
void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:536
void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:409
void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
Definition: fpu.c:646
#define DECODE_PRINTINSTR32(t, mod, rh, rl)
Definition: fpu_regs.h:111
uint8_t u8
Definition: stdint.h:45
#define X86EMU_UNUSED(v)
Definition: x86emui.h:60