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