Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / x86emu / fpu.c
CommitLineData
a09e091a
JB
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 */
45void
46x86emuOp_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
56static 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
67static 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 */
96void
97x86emuOp_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
306static 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 */
329void
330x86emuOp_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
400static 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 */
414void
415x86emuOp_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
524static 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 */
546void
547x86emuOp_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
643static 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 */
660void
661x86emuOp_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
747static 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 */
770void
771x86emuOp_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
869static 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 */
893void
894x86emuOp_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}