xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

fpu.c (27121B)


      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 }