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