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