105b261ecSmrg/****************************************************************************
205b261ecSmrg*
305b261ecSmrg*						Realmode X86 Emulator Library
405b261ecSmrg*
505b261ecSmrg*            	Copyright (C) 1996-1999 SciTech Software, Inc.
605b261ecSmrg* 				     Copyright (C) David Mosberger-Tang
705b261ecSmrg* 					   Copyright (C) 1999 Egbert Eich
805b261ecSmrg*
905b261ecSmrg*  ========================================================================
1005b261ecSmrg*
1105b261ecSmrg*  Permission to use, copy, modify, distribute, and sell this software and
1205b261ecSmrg*  its documentation for any purpose is hereby granted without fee,
1305b261ecSmrg*  provided that the above copyright notice appear in all copies and that
1405b261ecSmrg*  both that copyright notice and this permission notice appear in
1505b261ecSmrg*  supporting documentation, and that the name of the authors not be used
1605b261ecSmrg*  in advertising or publicity pertaining to distribution of the software
1705b261ecSmrg*  without specific, written prior permission.  The authors makes no
1805b261ecSmrg*  representations about the suitability of this software for any purpose.
1905b261ecSmrg*  It is provided "as is" without express or implied warranty.
2005b261ecSmrg*
2105b261ecSmrg*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2205b261ecSmrg*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2305b261ecSmrg*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2405b261ecSmrg*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
2505b261ecSmrg*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2605b261ecSmrg*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2705b261ecSmrg*  PERFORMANCE OF THIS SOFTWARE.
2805b261ecSmrg*
2905b261ecSmrg*  ========================================================================
3005b261ecSmrg*
3105b261ecSmrg* Language:		ANSI C
3205b261ecSmrg* Environment:	Any
3305b261ecSmrg* Developer:    Kendall Bennett
3405b261ecSmrg*
3505b261ecSmrg* Description:  This file contains the code to implement the decoding and
3605b261ecSmrg*               emulation of the FPU instructions.
3705b261ecSmrg*
3805b261ecSmrg****************************************************************************/
3905b261ecSmrg
4005b261ecSmrg#include "x86emu/x86emui.h"
4105b261ecSmrg
4205b261ecSmrg/*----------------------------- Implementation ----------------------------*/
4305b261ecSmrg
4405b261ecSmrg/* opcode=0xd8 */
4535c4bbdfSmrgvoid
4635c4bbdfSmrgx86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
4705b261ecSmrg{
4805b261ecSmrg    START_OF_INSTR();
4905b261ecSmrg    DECODE_PRINTF("ESC D8\n");
5005b261ecSmrg    DECODE_CLEAR_SEGOVR();
5105b261ecSmrg    END_OF_INSTR_NO_TRACE();
5205b261ecSmrg}
5305b261ecSmrg
5405b261ecSmrg#ifdef DEBUG
5505b261ecSmrg
5635c4bbdfSmrgstatic const char *x86emu_fpu_op_d9_tab[] = {
5705b261ecSmrg    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
5805b261ecSmrg    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
5905b261ecSmrg
6005b261ecSmrg    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
6105b261ecSmrg    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
6205b261ecSmrg
6305b261ecSmrg    "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
6405b261ecSmrg    "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
6505b261ecSmrg};
6605b261ecSmrg
6735c4bbdfSmrgstatic const char *x86emu_fpu_op_d9_tab1[] = {
6805b261ecSmrg    "FLD\t", "FLD\t", "FLD\t", "FLD\t",
6905b261ecSmrg    "FLD\t", "FLD\t", "FLD\t", "FLD\t",
7005b261ecSmrg
7105b261ecSmrg    "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
7205b261ecSmrg    "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
7305b261ecSmrg
7405b261ecSmrg    "FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
7505b261ecSmrg    "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
7605b261ecSmrg
7705b261ecSmrg    "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
7805b261ecSmrg    "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
7905b261ecSmrg
8005b261ecSmrg    "FCHS", "FABS", "ESC_D9", "ESC_D9",
8105b261ecSmrg    "FTST", "FXAM", "ESC_D9", "ESC_D9",
8205b261ecSmrg
8305b261ecSmrg    "FLD1", "FLDL2T", "FLDL2E", "FLDPI",
8405b261ecSmrg    "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
8505b261ecSmrg
8605b261ecSmrg    "F2XM1", "FYL2X", "FPTAN", "FPATAN",
8705b261ecSmrg    "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
8805b261ecSmrg
8905b261ecSmrg    "FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
9005b261ecSmrg    "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
9105b261ecSmrg};
9205b261ecSmrg
9335c4bbdfSmrg#endif                          /* DEBUG */
9405b261ecSmrg
9505b261ecSmrg/* opcode=0xd9 */
9635c4bbdfSmrgvoid
9735c4bbdfSmrgx86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
9805b261ecSmrg{
9905b261ecSmrg    int mod, rl, rh;
10005b261ecSmrg    uint destoffset = 0;
10105b261ecSmrg    u8 stkelem = 0;
10205b261ecSmrg
10305b261ecSmrg    START_OF_INSTR();
10405b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
10505b261ecSmrg#ifdef DEBUG
10605b261ecSmrg    if (mod != 3) {
10705b261ecSmrg        DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
10835c4bbdfSmrg    }
10935c4bbdfSmrg    else {
11005b261ecSmrg        DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
11105b261ecSmrg    }
11205b261ecSmrg#endif
11305b261ecSmrg    switch (mod) {
11435c4bbdfSmrg    case 0:
11505b261ecSmrg        destoffset = decode_rm00_address(rl);
11605b261ecSmrg        DECODE_PRINTF("\n");
11705b261ecSmrg        break;
11835c4bbdfSmrg    case 1:
11905b261ecSmrg        destoffset = decode_rm01_address(rl);
12005b261ecSmrg        DECODE_PRINTF("\n");
12105b261ecSmrg        break;
12235c4bbdfSmrg    case 2:
12305b261ecSmrg        destoffset = decode_rm10_address(rl);
12405b261ecSmrg        DECODE_PRINTF("\n");
12505b261ecSmrg        break;
12635c4bbdfSmrg    case 3:                    /* register to register */
12735c4bbdfSmrg        stkelem = (u8) rl;
12835c4bbdfSmrg        if (rh < 4) {
12935c4bbdfSmrg            DECODE_PRINTF2("ST(%d)\n", stkelem);
13035c4bbdfSmrg        }
13135c4bbdfSmrg        else {
13235c4bbdfSmrg            DECODE_PRINTF("\n");
13335c4bbdfSmrg        }
13405b261ecSmrg        break;
13505b261ecSmrg    }
13605b261ecSmrg#ifdef X86EMU_FPU_PRESENT
13705b261ecSmrg    /* execute */
13805b261ecSmrg    switch (mod) {
13935c4bbdfSmrg    case 3:
14005b261ecSmrg        switch (rh) {
14135c4bbdfSmrg        case 0:
14205b261ecSmrg            x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
14305b261ecSmrg            break;
14435c4bbdfSmrg        case 1:
14505b261ecSmrg            x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
14605b261ecSmrg            break;
14735c4bbdfSmrg        case 2:
14805b261ecSmrg            switch (rl) {
14935c4bbdfSmrg            case 0:
15005b261ecSmrg                x86emu_fpu_R_nop();
15105b261ecSmrg                break;
15235c4bbdfSmrg            default:
15305b261ecSmrg                x86emu_fpu_illegal();
15405b261ecSmrg                break;
15505b261ecSmrg            }
15635c4bbdfSmrg        case 3:
15705b261ecSmrg            x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
15805b261ecSmrg            break;
15935c4bbdfSmrg        case 4:
16005b261ecSmrg            switch (rl) {
16105b261ecSmrg            case 0:
16205b261ecSmrg                x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
16305b261ecSmrg                break;
16405b261ecSmrg            case 1:
16505b261ecSmrg                x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
16605b261ecSmrg                break;
16705b261ecSmrg            case 4:
16805b261ecSmrg                x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
16905b261ecSmrg                break;
17005b261ecSmrg            case 5:
17105b261ecSmrg                x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
17205b261ecSmrg                break;
17305b261ecSmrg            default:
17405b261ecSmrg                /* 2,3,6,7 */
17505b261ecSmrg                x86emu_fpu_illegal();
17605b261ecSmrg                break;
17705b261ecSmrg            }
17805b261ecSmrg            break;
17905b261ecSmrg
18035c4bbdfSmrg        case 5:
18105b261ecSmrg            switch (rl) {
18235c4bbdfSmrg            case 0:
18305b261ecSmrg                x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
18405b261ecSmrg                break;
18535c4bbdfSmrg            case 1:
18605b261ecSmrg                x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
18705b261ecSmrg                break;
18835c4bbdfSmrg            case 2:
18905b261ecSmrg                x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
19005b261ecSmrg                break;
19135c4bbdfSmrg            case 3:
19205b261ecSmrg                x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
19305b261ecSmrg                break;
19435c4bbdfSmrg            case 4:
19505b261ecSmrg                x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
19605b261ecSmrg                break;
19735c4bbdfSmrg            case 5:
19805b261ecSmrg                x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
19905b261ecSmrg                break;
20035c4bbdfSmrg            case 6:
20105b261ecSmrg                x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
20205b261ecSmrg                break;
20335c4bbdfSmrg            default:
20405b261ecSmrg                /* 7 */
20505b261ecSmrg                x86emu_fpu_illegal();
20605b261ecSmrg                break;
20705b261ecSmrg            }
20805b261ecSmrg            break;
20905b261ecSmrg
21035c4bbdfSmrg        case 6:
21105b261ecSmrg            switch (rl) {
21235c4bbdfSmrg            case 0:
21305b261ecSmrg                x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
21405b261ecSmrg                break;
21535c4bbdfSmrg            case 1:
21605b261ecSmrg                x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
21705b261ecSmrg                break;
21835c4bbdfSmrg            case 2:
21905b261ecSmrg                x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
22005b261ecSmrg                break;
22135c4bbdfSmrg            case 3:
22205b261ecSmrg                x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
22305b261ecSmrg                break;
22435c4bbdfSmrg            case 4:
22505b261ecSmrg                x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
22605b261ecSmrg                break;
22735c4bbdfSmrg            case 5:
22805b261ecSmrg                x86emu_fpu_illegal();
22905b261ecSmrg                break;
23035c4bbdfSmrg            case 6:
23105b261ecSmrg                x86emu_fpu_R_decstp();
23205b261ecSmrg                break;
23335c4bbdfSmrg            case 7:
23405b261ecSmrg                x86emu_fpu_R_incstp();
23505b261ecSmrg                break;
23605b261ecSmrg            }
23705b261ecSmrg            break;
23805b261ecSmrg
23935c4bbdfSmrg        case 7:
24005b261ecSmrg            switch (rl) {
24135c4bbdfSmrg            case 0:
24205b261ecSmrg                x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
24305b261ecSmrg                break;
24435c4bbdfSmrg            case 1:
24505b261ecSmrg                x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
24605b261ecSmrg                break;
24735c4bbdfSmrg            case 2:
24805b261ecSmrg                x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
24905b261ecSmrg                break;
25035c4bbdfSmrg            case 3:
25105b261ecSmrg                x86emu_fpu_illegal();
25205b261ecSmrg                break;
25335c4bbdfSmrg            case 4:
25405b261ecSmrg                x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
25505b261ecSmrg                break;
25635c4bbdfSmrg            case 5:
25705b261ecSmrg                x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
25805b261ecSmrg                break;
25935c4bbdfSmrg            case 6:
26035c4bbdfSmrg            case 7:
26135c4bbdfSmrg            default:
26205b261ecSmrg                x86emu_fpu_illegal();
26305b261ecSmrg                break;
26405b261ecSmrg            }
26505b261ecSmrg            break;
26605b261ecSmrg
26735c4bbdfSmrg        default:
26805b261ecSmrg            switch (rh) {
26935c4bbdfSmrg            case 0:
27005b261ecSmrg                x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
27105b261ecSmrg                break;
27235c4bbdfSmrg            case 1:
27305b261ecSmrg                x86emu_fpu_illegal();
27405b261ecSmrg                break;
27535c4bbdfSmrg            case 2:
27605b261ecSmrg                x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
27705b261ecSmrg                break;
27835c4bbdfSmrg            case 3:
27905b261ecSmrg                x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
28005b261ecSmrg                break;
28135c4bbdfSmrg            case 4:
28205b261ecSmrg                x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
28305b261ecSmrg                break;
28435c4bbdfSmrg            case 5:
28505b261ecSmrg                x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
28605b261ecSmrg                break;
28735c4bbdfSmrg            case 6:
28805b261ecSmrg                x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
28905b261ecSmrg                break;
29035c4bbdfSmrg            case 7:
29105b261ecSmrg                x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
29205b261ecSmrg                break;
29305b261ecSmrg            }
29405b261ecSmrg        }
29505b261ecSmrg    }
29605b261ecSmrg#else
29735c4bbdfSmrg    (void) destoffset;
29835c4bbdfSmrg    (void) stkelem;
29935c4bbdfSmrg#endif                          /* X86EMU_FPU_PRESENT */
30005b261ecSmrg    DECODE_CLEAR_SEGOVR();
30105b261ecSmrg    END_OF_INSTR_NO_TRACE();
30205b261ecSmrg}
30305b261ecSmrg
30405b261ecSmrg#ifdef DEBUG
30505b261ecSmrg
30635c4bbdfSmrgstatic const char *x86emu_fpu_op_da_tab[] = {
30705b261ecSmrg    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
30805b261ecSmrg    "FICOMP\tDWORD PTR ",
30905b261ecSmrg    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
31005b261ecSmrg    "FIDIVR\tDWORD PTR ",
31105b261ecSmrg
31205b261ecSmrg    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
31305b261ecSmrg    "FICOMP\tDWORD PTR ",
31405b261ecSmrg    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
31505b261ecSmrg    "FIDIVR\tDWORD PTR ",
31635c4bbdfSmrg
31705b261ecSmrg    "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
31805b261ecSmrg    "FICOMP\tDWORD PTR ",
31905b261ecSmrg    "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
32005b261ecSmrg    "FIDIVR\tDWORD PTR ",
32105b261ecSmrg
32205b261ecSmrg    "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
32305b261ecSmrg    "ESC_DA     ", "ESC_DA ", "ESC_DA   ", "ESC_DA ",
32405b261ecSmrg};
32505b261ecSmrg
32635c4bbdfSmrg#endif                          /* DEBUG */
32705b261ecSmrg
32805b261ecSmrg/* opcode=0xda */
32935c4bbdfSmrgvoid
33035c4bbdfSmrgx86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
33105b261ecSmrg{
33205b261ecSmrg    int mod, rl, rh;
33305b261ecSmrg    uint destoffset = 0;
33405b261ecSmrg    u8 stkelem = 0;
33505b261ecSmrg
33605b261ecSmrg    START_OF_INSTR();
33705b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
33805b261ecSmrg    DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
33905b261ecSmrg    switch (mod) {
34035c4bbdfSmrg    case 0:
34105b261ecSmrg        destoffset = decode_rm00_address(rl);
34205b261ecSmrg        DECODE_PRINTF("\n");
34305b261ecSmrg        break;
34435c4bbdfSmrg    case 1:
34505b261ecSmrg        destoffset = decode_rm01_address(rl);
34605b261ecSmrg        DECODE_PRINTF("\n");
34705b261ecSmrg        break;
34835c4bbdfSmrg    case 2:
34905b261ecSmrg        destoffset = decode_rm10_address(rl);
35005b261ecSmrg        DECODE_PRINTF("\n");
35105b261ecSmrg        break;
35235c4bbdfSmrg    case 3:                    /* register to register */
35335c4bbdfSmrg        stkelem = (u8) rl;
35405b261ecSmrg        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
35505b261ecSmrg        break;
35605b261ecSmrg    }
35705b261ecSmrg#ifdef X86EMU_FPU_PRESENT
35805b261ecSmrg    switch (mod) {
35935c4bbdfSmrg    case 3:
36005b261ecSmrg        x86emu_fpu_illegal();
36105b261ecSmrg        break;
36235c4bbdfSmrg    default:
36305b261ecSmrg        switch (rh) {
36435c4bbdfSmrg        case 0:
36505b261ecSmrg            x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
36605b261ecSmrg            break;
36735c4bbdfSmrg        case 1:
36805b261ecSmrg            x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
36905b261ecSmrg            break;
37035c4bbdfSmrg        case 2:
37105b261ecSmrg            x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
37205b261ecSmrg            break;
37335c4bbdfSmrg        case 3:
37405b261ecSmrg            x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
37505b261ecSmrg            break;
37635c4bbdfSmrg        case 4:
37705b261ecSmrg            x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
37805b261ecSmrg            break;
37935c4bbdfSmrg        case 5:
38005b261ecSmrg            x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
38105b261ecSmrg            break;
38235c4bbdfSmrg        case 6:
38305b261ecSmrg            x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
38405b261ecSmrg            break;
38535c4bbdfSmrg        case 7:
38605b261ecSmrg            x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
38705b261ecSmrg            break;
38805b261ecSmrg        }
38905b261ecSmrg    }
39005b261ecSmrg#else
39135c4bbdfSmrg    (void) destoffset;
39235c4bbdfSmrg    (void) stkelem;
39305b261ecSmrg#endif
39405b261ecSmrg    DECODE_CLEAR_SEGOVR();
39505b261ecSmrg    END_OF_INSTR_NO_TRACE();
39605b261ecSmrg}
39705b261ecSmrg
39805b261ecSmrg#ifdef DEBUG
39905b261ecSmrg
40035c4bbdfSmrgstatic const char *x86emu_fpu_op_db_tab[] = {
40105b261ecSmrg    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
40205b261ecSmrg    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
40305b261ecSmrg
40405b261ecSmrg    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
40505b261ecSmrg    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
40605b261ecSmrg
40705b261ecSmrg    "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
40805b261ecSmrg    "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
40905b261ecSmrg};
41005b261ecSmrg
41135c4bbdfSmrg#endif                          /* DEBUG */
41205b261ecSmrg
41305b261ecSmrg/* opcode=0xdb */
41435c4bbdfSmrgvoid
41535c4bbdfSmrgx86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
41605b261ecSmrg{
41705b261ecSmrg    int mod, rl, rh;
41805b261ecSmrg    uint destoffset = 0;
41905b261ecSmrg
42005b261ecSmrg    START_OF_INSTR();
42105b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
42205b261ecSmrg#ifdef DEBUG
42305b261ecSmrg    if (mod != 3) {
42405b261ecSmrg        DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
42535c4bbdfSmrg    }
42635c4bbdfSmrg    else if (rh == 4) {         /* === 11 10 0 nnn */
42705b261ecSmrg        switch (rl) {
42835c4bbdfSmrg        case 0:
42905b261ecSmrg            DECODE_PRINTF("FENI\n");
43005b261ecSmrg            break;
43135c4bbdfSmrg        case 1:
43205b261ecSmrg            DECODE_PRINTF("FDISI\n");
43305b261ecSmrg            break;
43435c4bbdfSmrg        case 2:
43505b261ecSmrg            DECODE_PRINTF("FCLEX\n");
43605b261ecSmrg            break;
43735c4bbdfSmrg        case 3:
43805b261ecSmrg            DECODE_PRINTF("FINIT\n");
43905b261ecSmrg            break;
44005b261ecSmrg        }
44135c4bbdfSmrg    }
44235c4bbdfSmrg    else {
44305b261ecSmrg        DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
44405b261ecSmrg    }
44535c4bbdfSmrg#endif                          /* DEBUG */
44605b261ecSmrg    switch (mod) {
44735c4bbdfSmrg    case 0:
44805b261ecSmrg        destoffset = decode_rm00_address(rl);
44905b261ecSmrg        break;
45035c4bbdfSmrg    case 1:
45105b261ecSmrg        destoffset = decode_rm01_address(rl);
45205b261ecSmrg        break;
45335c4bbdfSmrg    case 2:
45405b261ecSmrg        destoffset = decode_rm10_address(rl);
45505b261ecSmrg        break;
45635c4bbdfSmrg    case 3:                    /* register to register */
45705b261ecSmrg        break;
45805b261ecSmrg    }
45905b261ecSmrg#ifdef X86EMU_FPU_PRESENT
46005b261ecSmrg    /* execute */
46105b261ecSmrg    switch (mod) {
46235c4bbdfSmrg    case 3:
46305b261ecSmrg        switch (rh) {
46435c4bbdfSmrg        case 4:
46505b261ecSmrg            switch (rl) {
46635c4bbdfSmrg            case 0:
46705b261ecSmrg                x86emu_fpu_R_feni();
46805b261ecSmrg                break;
46935c4bbdfSmrg            case 1:
47005b261ecSmrg                x86emu_fpu_R_fdisi();
47105b261ecSmrg                break;
47235c4bbdfSmrg            case 2:
47305b261ecSmrg                x86emu_fpu_R_fclex();
47405b261ecSmrg                break;
47535c4bbdfSmrg            case 3:
47605b261ecSmrg                x86emu_fpu_R_finit();
47705b261ecSmrg                break;
47835c4bbdfSmrg            default:
47905b261ecSmrg                x86emu_fpu_illegal();
48005b261ecSmrg                break;
48105b261ecSmrg            }
48205b261ecSmrg            break;
48335c4bbdfSmrg        default:
48405b261ecSmrg            x86emu_fpu_illegal();
48505b261ecSmrg            break;
48605b261ecSmrg        }
48705b261ecSmrg        break;
48835c4bbdfSmrg    default:
48905b261ecSmrg        switch (rh) {
49035c4bbdfSmrg        case 0:
49105b261ecSmrg            x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
49205b261ecSmrg            break;
49335c4bbdfSmrg        case 1:
49405b261ecSmrg            x86emu_fpu_illegal();
49505b261ecSmrg            break;
49635c4bbdfSmrg        case 2:
49705b261ecSmrg            x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
49805b261ecSmrg            break;
49935c4bbdfSmrg        case 3:
50005b261ecSmrg            x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
50105b261ecSmrg            break;
50235c4bbdfSmrg        case 4:
50305b261ecSmrg            x86emu_fpu_illegal();
50405b261ecSmrg            break;
50535c4bbdfSmrg        case 5:
50605b261ecSmrg            x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
50705b261ecSmrg            break;
50835c4bbdfSmrg        case 6:
50905b261ecSmrg            x86emu_fpu_illegal();
51005b261ecSmrg            break;
51135c4bbdfSmrg        case 7:
51205b261ecSmrg            x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
51305b261ecSmrg            break;
51405b261ecSmrg        }
51505b261ecSmrg    }
51605b261ecSmrg#else
51735c4bbdfSmrg    (void) destoffset;
51805b261ecSmrg#endif
51905b261ecSmrg    DECODE_CLEAR_SEGOVR();
52005b261ecSmrg    END_OF_INSTR_NO_TRACE();
52105b261ecSmrg}
52205b261ecSmrg
52305b261ecSmrg#ifdef DEBUG
52435c4bbdfSmrgstatic const char *x86emu_fpu_op_dc_tab[] = {
52505b261ecSmrg    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
52605b261ecSmrg    "FCOMP\tQWORD PTR ",
52705b261ecSmrg    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
52805b261ecSmrg    "FDIVR\tQWORD PTR ",
52905b261ecSmrg
53005b261ecSmrg    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
53105b261ecSmrg    "FCOMP\tQWORD PTR ",
53205b261ecSmrg    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
53305b261ecSmrg    "FDIVR\tQWORD PTR ",
53405b261ecSmrg
53505b261ecSmrg    "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
53605b261ecSmrg    "FCOMP\tQWORD PTR ",
53705b261ecSmrg    "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
53805b261ecSmrg    "FDIVR\tQWORD PTR ",
53905b261ecSmrg
54005b261ecSmrg    "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
54105b261ecSmrg    "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
54205b261ecSmrg};
54335c4bbdfSmrg#endif                          /* DEBUG */
54405b261ecSmrg
54505b261ecSmrg/* opcode=0xdc */
54635c4bbdfSmrgvoid
54735c4bbdfSmrgx86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
54805b261ecSmrg{
54905b261ecSmrg    int mod, rl, rh;
55005b261ecSmrg    uint destoffset = 0;
55105b261ecSmrg    u8 stkelem = 0;
55205b261ecSmrg
55305b261ecSmrg    START_OF_INSTR();
55405b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
55505b261ecSmrg    DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
55605b261ecSmrg    switch (mod) {
55735c4bbdfSmrg    case 0:
55805b261ecSmrg        destoffset = decode_rm00_address(rl);
55905b261ecSmrg        DECODE_PRINTF("\n");
56005b261ecSmrg        break;
56135c4bbdfSmrg    case 1:
56205b261ecSmrg        destoffset = decode_rm01_address(rl);
56305b261ecSmrg        DECODE_PRINTF("\n");
56405b261ecSmrg        break;
56535c4bbdfSmrg    case 2:
56605b261ecSmrg        destoffset = decode_rm10_address(rl);
56705b261ecSmrg        DECODE_PRINTF("\n");
56805b261ecSmrg        break;
56935c4bbdfSmrg    case 3:                    /* register to register */
57035c4bbdfSmrg        stkelem = (u8) rl;
57105b261ecSmrg        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
57205b261ecSmrg        break;
57305b261ecSmrg    }
57405b261ecSmrg#ifdef X86EMU_FPU_PRESENT
57505b261ecSmrg    /* execute */
57605b261ecSmrg    switch (mod) {
57735c4bbdfSmrg    case 3:
57805b261ecSmrg        switch (rh) {
57935c4bbdfSmrg        case 0:
58005b261ecSmrg            x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
58105b261ecSmrg            break;
58235c4bbdfSmrg        case 1:
58305b261ecSmrg            x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
58405b261ecSmrg            break;
58535c4bbdfSmrg        case 2:
58605b261ecSmrg            x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
58705b261ecSmrg            break;
58835c4bbdfSmrg        case 3:
58905b261ecSmrg            x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
59005b261ecSmrg            break;
59135c4bbdfSmrg        case 4:
59205b261ecSmrg            x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
59305b261ecSmrg            break;
59435c4bbdfSmrg        case 5:
59505b261ecSmrg            x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
59605b261ecSmrg            break;
59735c4bbdfSmrg        case 6:
59805b261ecSmrg            x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
59905b261ecSmrg            break;
60035c4bbdfSmrg        case 7:
60105b261ecSmrg            x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
60205b261ecSmrg            break;
60305b261ecSmrg        }
60405b261ecSmrg        break;
60535c4bbdfSmrg    default:
60605b261ecSmrg        switch (rh) {
60735c4bbdfSmrg        case 0:
60805b261ecSmrg            x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
60905b261ecSmrg            break;
61035c4bbdfSmrg        case 1:
61105b261ecSmrg            x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
61205b261ecSmrg            break;
61335c4bbdfSmrg        case 2:
61405b261ecSmrg            x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
61505b261ecSmrg            break;
61635c4bbdfSmrg        case 3:
61705b261ecSmrg            x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
61805b261ecSmrg            break;
61935c4bbdfSmrg        case 4:
62005b261ecSmrg            x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
62105b261ecSmrg            break;
62235c4bbdfSmrg        case 5:
62305b261ecSmrg            x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
62405b261ecSmrg            break;
62535c4bbdfSmrg        case 6:
62605b261ecSmrg            x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
62705b261ecSmrg            break;
62835c4bbdfSmrg        case 7:
62905b261ecSmrg            x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
63005b261ecSmrg            break;
63105b261ecSmrg        }
63205b261ecSmrg    }
63305b261ecSmrg#else
63435c4bbdfSmrg    (void) destoffset;
63535c4bbdfSmrg    (void) stkelem;
63605b261ecSmrg#endif
63705b261ecSmrg    DECODE_CLEAR_SEGOVR();
63805b261ecSmrg    END_OF_INSTR_NO_TRACE();
63905b261ecSmrg}
64005b261ecSmrg
64105b261ecSmrg#ifdef DEBUG
64205b261ecSmrg
64335c4bbdfSmrgstatic const char *x86emu_fpu_op_dd_tab[] = {
64405b261ecSmrg    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
64505b261ecSmrg    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
64605b261ecSmrg
64705b261ecSmrg    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
64805b261ecSmrg    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
64905b261ecSmrg
65005b261ecSmrg    "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
65105b261ecSmrg    "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
65205b261ecSmrg
65305b261ecSmrg    "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
65405b261ecSmrg    "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
65505b261ecSmrg};
65605b261ecSmrg
65735c4bbdfSmrg#endif                          /* DEBUG */
65805b261ecSmrg
65905b261ecSmrg/* opcode=0xdd */
66035c4bbdfSmrgvoid
66135c4bbdfSmrgx86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
66205b261ecSmrg{
66305b261ecSmrg    int mod, rl, rh;
66405b261ecSmrg    uint destoffset = 0;
66505b261ecSmrg    u8 stkelem = 0;
66605b261ecSmrg
66705b261ecSmrg    START_OF_INSTR();
66805b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
66905b261ecSmrg    DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
67005b261ecSmrg    switch (mod) {
67135c4bbdfSmrg    case 0:
67205b261ecSmrg        destoffset = decode_rm00_address(rl);
67305b261ecSmrg        DECODE_PRINTF("\n");
67405b261ecSmrg        break;
67535c4bbdfSmrg    case 1:
67605b261ecSmrg        destoffset = decode_rm01_address(rl);
67705b261ecSmrg        DECODE_PRINTF("\n");
67805b261ecSmrg        break;
67935c4bbdfSmrg    case 2:
68005b261ecSmrg        destoffset = decode_rm10_address(rl);
68105b261ecSmrg        DECODE_PRINTF("\n");
68205b261ecSmrg        break;
68335c4bbdfSmrg    case 3:                    /* register to register */
68435c4bbdfSmrg        stkelem = (u8) rl;
68505b261ecSmrg        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
68605b261ecSmrg        break;
68705b261ecSmrg    }
68805b261ecSmrg#ifdef X86EMU_FPU_PRESENT
68905b261ecSmrg    switch (mod) {
69035c4bbdfSmrg    case 3:
69105b261ecSmrg        switch (rh) {
69235c4bbdfSmrg        case 0:
69305b261ecSmrg            x86emu_fpu_R_ffree(stkelem);
69405b261ecSmrg            break;
69535c4bbdfSmrg        case 1:
69605b261ecSmrg            x86emu_fpu_R_fxch(stkelem);
69705b261ecSmrg            break;
69835c4bbdfSmrg        case 2:
69905b261ecSmrg            x86emu_fpu_R_fst(stkelem);  /* register version */
70005b261ecSmrg            break;
70135c4bbdfSmrg        case 3:
70205b261ecSmrg            x86emu_fpu_R_fstp(stkelem); /* register version */
70305b261ecSmrg            break;
70435c4bbdfSmrg        default:
70505b261ecSmrg            x86emu_fpu_illegal();
70605b261ecSmrg            break;
70705b261ecSmrg        }
70805b261ecSmrg        break;
70935c4bbdfSmrg    default:
71005b261ecSmrg        switch (rh) {
71135c4bbdfSmrg        case 0:
71205b261ecSmrg            x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
71305b261ecSmrg            break;
71435c4bbdfSmrg        case 1:
71505b261ecSmrg            x86emu_fpu_illegal();
71605b261ecSmrg            break;
71735c4bbdfSmrg        case 2:
71805b261ecSmrg            x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
71905b261ecSmrg            break;
72035c4bbdfSmrg        case 3:
72105b261ecSmrg            x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
72205b261ecSmrg            break;
72335c4bbdfSmrg        case 4:
72405b261ecSmrg            x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
72505b261ecSmrg            break;
72635c4bbdfSmrg        case 5:
72705b261ecSmrg            x86emu_fpu_illegal();
72805b261ecSmrg            break;
72935c4bbdfSmrg        case 6:
73005b261ecSmrg            x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
73105b261ecSmrg            break;
73235c4bbdfSmrg        case 7:
73305b261ecSmrg            x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
73405b261ecSmrg            break;
73505b261ecSmrg        }
73605b261ecSmrg    }
73705b261ecSmrg#else
73835c4bbdfSmrg    (void) destoffset;
73935c4bbdfSmrg    (void) stkelem;
74005b261ecSmrg#endif
74105b261ecSmrg    DECODE_CLEAR_SEGOVR();
74205b261ecSmrg    END_OF_INSTR_NO_TRACE();
74305b261ecSmrg}
74405b261ecSmrg
74505b261ecSmrg#ifdef DEBUG
74605b261ecSmrg
74735c4bbdfSmrgstatic const char *x86emu_fpu_op_de_tab[] = {
74805b261ecSmrg    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
74905b261ecSmrg    "FICOMP\tWORD PTR ",
75005b261ecSmrg    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
75105b261ecSmrg    "FIDIVR\tWORD PTR ",
75205b261ecSmrg
75305b261ecSmrg    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
75405b261ecSmrg    "FICOMP\tWORD PTR ",
75505b261ecSmrg    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
75605b261ecSmrg    "FIDIVR\tWORD PTR ",
75705b261ecSmrg
75805b261ecSmrg    "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
75905b261ecSmrg    "FICOMP\tWORD PTR ",
76005b261ecSmrg    "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
76105b261ecSmrg    "FIDIVR\tWORD PTR ",
76205b261ecSmrg
76305b261ecSmrg    "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
76405b261ecSmrg    "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
76505b261ecSmrg};
76605b261ecSmrg
76735c4bbdfSmrg#endif                          /* DEBUG */
76805b261ecSmrg
76905b261ecSmrg/* opcode=0xde */
77035c4bbdfSmrgvoid
77135c4bbdfSmrgx86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
77205b261ecSmrg{
77305b261ecSmrg    int mod, rl, rh;
77405b261ecSmrg    uint destoffset = 0;
77505b261ecSmrg    u8 stkelem = 0;
77605b261ecSmrg
77705b261ecSmrg    START_OF_INSTR();
77805b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
77905b261ecSmrg    DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
78005b261ecSmrg    switch (mod) {
78135c4bbdfSmrg    case 0:
78205b261ecSmrg        destoffset = decode_rm00_address(rl);
78305b261ecSmrg        DECODE_PRINTF("\n");
78405b261ecSmrg        break;
78535c4bbdfSmrg    case 1:
78605b261ecSmrg        destoffset = decode_rm01_address(rl);
78705b261ecSmrg        DECODE_PRINTF("\n");
78805b261ecSmrg        break;
78935c4bbdfSmrg    case 2:
79005b261ecSmrg        destoffset = decode_rm10_address(rl);
79105b261ecSmrg        DECODE_PRINTF("\n");
79205b261ecSmrg        break;
79335c4bbdfSmrg    case 3:                    /* register to register */
79435c4bbdfSmrg        stkelem = (u8) rl;
79505b261ecSmrg        DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
79605b261ecSmrg        break;
79705b261ecSmrg    }
79805b261ecSmrg#ifdef X86EMU_FPU_PRESENT
79905b261ecSmrg    switch (mod) {
80035c4bbdfSmrg    case 3:
80105b261ecSmrg        switch (rh) {
80235c4bbdfSmrg        case 0:
80305b261ecSmrg            x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
80405b261ecSmrg            break;
80535c4bbdfSmrg        case 1:
80605b261ecSmrg            x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
80705b261ecSmrg            break;
80835c4bbdfSmrg        case 2:
80905b261ecSmrg            x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
81005b261ecSmrg            break;
81135c4bbdfSmrg        case 3:
81205b261ecSmrg            if (stkelem == 1)
81335c4bbdfSmrg                x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
81405b261ecSmrg            else
81535c4bbdfSmrg                x86emu_fpu_illegal();
81605b261ecSmrg            break;
81735c4bbdfSmrg        case 4:
81805b261ecSmrg            x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
81905b261ecSmrg            break;
82035c4bbdfSmrg        case 5:
82105b261ecSmrg            x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
82205b261ecSmrg            break;
82335c4bbdfSmrg        case 6:
82405b261ecSmrg            x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
82505b261ecSmrg            break;
82635c4bbdfSmrg        case 7:
82705b261ecSmrg            x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
82805b261ecSmrg            break;
82905b261ecSmrg        }
83005b261ecSmrg        break;
83135c4bbdfSmrg    default:
83205b261ecSmrg        switch (rh) {
83335c4bbdfSmrg        case 0:
83405b261ecSmrg            x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
83505b261ecSmrg            break;
83635c4bbdfSmrg        case 1:
83705b261ecSmrg            x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
83805b261ecSmrg            break;
83935c4bbdfSmrg        case 2:
84005b261ecSmrg            x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
84105b261ecSmrg            break;
84235c4bbdfSmrg        case 3:
84305b261ecSmrg            x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
84405b261ecSmrg            break;
84535c4bbdfSmrg        case 4:
84605b261ecSmrg            x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
84705b261ecSmrg            break;
84835c4bbdfSmrg        case 5:
84905b261ecSmrg            x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
85005b261ecSmrg            break;
85135c4bbdfSmrg        case 6:
85205b261ecSmrg            x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
85305b261ecSmrg            break;
85435c4bbdfSmrg        case 7:
85505b261ecSmrg            x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
85605b261ecSmrg            break;
85705b261ecSmrg        }
85805b261ecSmrg    }
85905b261ecSmrg#else
86035c4bbdfSmrg    (void) destoffset;
86135c4bbdfSmrg    (void) stkelem;
86205b261ecSmrg#endif
86305b261ecSmrg    DECODE_CLEAR_SEGOVR();
86405b261ecSmrg    END_OF_INSTR_NO_TRACE();
86505b261ecSmrg}
86605b261ecSmrg
86705b261ecSmrg#ifdef DEBUG
86805b261ecSmrg
86935c4bbdfSmrgstatic const char *x86emu_fpu_op_df_tab[] = {
87005b261ecSmrg    /* mod == 00 */
87105b261ecSmrg    "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
87205b261ecSmrg    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
87305b261ecSmrg    "FISTP\tQWORD PTR ",
87405b261ecSmrg
87505b261ecSmrg    /* mod == 01 */
87605b261ecSmrg    "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
87705b261ecSmrg    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
87805b261ecSmrg    "FISTP\tQWORD PTR ",
87905b261ecSmrg
88005b261ecSmrg    /* mod == 10 */
88105b261ecSmrg    "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
88205b261ecSmrg    "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
88305b261ecSmrg    "FISTP\tQWORD PTR ",
88405b261ecSmrg
88505b261ecSmrg    /* mod == 11 */
88605b261ecSmrg    "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
88705b261ecSmrg    "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
88805b261ecSmrg};
88905b261ecSmrg
89035c4bbdfSmrg#endif                          /* DEBUG */
89105b261ecSmrg
89205b261ecSmrg/* opcode=0xdf */
89335c4bbdfSmrgvoid
89435c4bbdfSmrgx86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
89505b261ecSmrg{
89605b261ecSmrg    int mod, rl, rh;
89705b261ecSmrg    uint destoffset = 0;
89805b261ecSmrg    u8 stkelem = 0;
89905b261ecSmrg
90005b261ecSmrg    START_OF_INSTR();
90105b261ecSmrg    FETCH_DECODE_MODRM(mod, rh, rl);
90205b261ecSmrg    DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
90305b261ecSmrg    switch (mod) {
90435c4bbdfSmrg    case 0:
90505b261ecSmrg        destoffset = decode_rm00_address(rl);
90605b261ecSmrg        DECODE_PRINTF("\n");
90705b261ecSmrg        break;
90835c4bbdfSmrg    case 1:
90905b261ecSmrg        destoffset = decode_rm01_address(rl);
91005b261ecSmrg        DECODE_PRINTF("\n");
91105b261ecSmrg        break;
91235c4bbdfSmrg    case 2:
91305b261ecSmrg        destoffset = decode_rm10_address(rl);
91405b261ecSmrg        DECODE_PRINTF("\n");
91505b261ecSmrg        break;
91635c4bbdfSmrg    case 3:                    /* register to register */
91735c4bbdfSmrg        stkelem = (u8) rl;
91805b261ecSmrg        DECODE_PRINTF2("\tST(%d)\n", stkelem);
91905b261ecSmrg        break;
92005b261ecSmrg    }
92105b261ecSmrg#ifdef X86EMU_FPU_PRESENT
92205b261ecSmrg    switch (mod) {
92335c4bbdfSmrg    case 3:
92405b261ecSmrg        switch (rh) {
92535c4bbdfSmrg        case 0:
92605b261ecSmrg            x86emu_fpu_R_ffree(stkelem);
92705b261ecSmrg            break;
92835c4bbdfSmrg        case 1:
92905b261ecSmrg            x86emu_fpu_R_fxch(stkelem);
93005b261ecSmrg            break;
93135c4bbdfSmrg        case 2:
93205b261ecSmrg            x86emu_fpu_R_fst(stkelem);  /* register version */
93305b261ecSmrg            break;
93435c4bbdfSmrg        case 3:
93505b261ecSmrg            x86emu_fpu_R_fstp(stkelem); /* register version */
93605b261ecSmrg            break;
93735c4bbdfSmrg        default:
93805b261ecSmrg            x86emu_fpu_illegal();
93905b261ecSmrg            break;
94005b261ecSmrg        }
94105b261ecSmrg        break;
94235c4bbdfSmrg    default:
94305b261ecSmrg        switch (rh) {
94435c4bbdfSmrg        case 0:
94505b261ecSmrg            x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
94605b261ecSmrg            break;
94735c4bbdfSmrg        case 1:
94805b261ecSmrg            x86emu_fpu_illegal();
94905b261ecSmrg            break;
95035c4bbdfSmrg        case 2:
95105b261ecSmrg            x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
95205b261ecSmrg            break;
95335c4bbdfSmrg        case 3:
95405b261ecSmrg            x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
95505b261ecSmrg            break;
95635c4bbdfSmrg        case 4:
95705b261ecSmrg            x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
95805b261ecSmrg            break;
95935c4bbdfSmrg        case 5:
96005b261ecSmrg            x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
96105b261ecSmrg            break;
96235c4bbdfSmrg        case 6:
96305b261ecSmrg            x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
96405b261ecSmrg            break;
96535c4bbdfSmrg        case 7:
96605b261ecSmrg            x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
96705b261ecSmrg            break;
96805b261ecSmrg        }
96905b261ecSmrg    }
97005b261ecSmrg#else
97135c4bbdfSmrg    (void) destoffset;
97235c4bbdfSmrg    (void) stkelem;
97305b261ecSmrg#endif
97405b261ecSmrg    DECODE_CLEAR_SEGOVR();
97505b261ecSmrg    END_OF_INSTR_NO_TRACE();
97605b261ecSmrg}
977