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