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