• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED (op1))45 void 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 
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 */
x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED (op1))101 void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
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 */
299     DECODE_CLEAR_SEGOVR();
300     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED (op1))328 void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
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
389     DECODE_CLEAR_SEGOVR();
390     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED (op1))409 void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
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
509     DECODE_CLEAR_SEGOVR();
510     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED (op1))536 void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
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
623     DECODE_CLEAR_SEGOVR();
624     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED (op1))646 void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
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
723     DECODE_CLEAR_SEGOVR();
724     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED (op1))753 void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
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
842     DECODE_CLEAR_SEGOVR();
843     END_OF_INSTR_NO_TRACE();
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 */
x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED (op1))872 void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
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
949     DECODE_CLEAR_SEGOVR();
950     END_OF_INSTR_NO_TRACE();
951 }
952