uboot/drivers/bios_emulator/x86emu/ops.c
<<
>>
Prefs
   1/****************************************************************************
   2*                       Realmode X86 Emulator Library
   3*
   4*  Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
   5*  Jason Jin <Jason.jin@freescale.com>
   6*
   7*               Copyright (C) 1991-2004 SciTech Software, Inc.
   8*                                    Copyright (C) David Mosberger-Tang
   9*                                          Copyright (C) 1999 Egbert Eich
  10*
  11*  ========================================================================
  12*
  13*  Permission to use, copy, modify, distribute, and sell this software and
  14*  its documentation for any purpose is hereby granted without fee,
  15*  provided that the above copyright notice appear in all copies and that
  16*  both that copyright notice and this permission notice appear in
  17*  supporting documentation, and that the name of the authors not be used
  18*  in advertising or publicity pertaining to distribution of the software
  19*  without specific, written prior permission.  The authors makes no
  20*  representations about the suitability of this software for any purpose.
  21*  It is provided "as is" without express or implied warranty.
  22*
  23*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  24*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  25*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  26*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  27*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  28*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  29*  PERFORMANCE OF THIS SOFTWARE.
  30*
  31*  ========================================================================
  32*
  33* Language:             ANSI C
  34* Environment:  Any
  35* Developer:    Kendall Bennett
  36*
  37* Description:  This file includes subroutines to implement the decoding
  38*               and emulation of all the x86 processor instructions.
  39*
  40* There are approximately 250 subroutines in here, which correspond
  41* to the 256 byte-"opcodes" found on the 8086.  The table which
  42* dispatches this is found in the files optab.[ch].
  43*
  44* Each opcode proc has a comment preceeding it which gives it's table
  45* address.  Several opcodes are missing (undefined) in the table.
  46*
  47* Each proc includes information for decoding (DECODE_PRINTF and
  48* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
  49* functions (START_OF_INSTR, END_OF_INSTR).
  50*
  51* Many of the procedures are *VERY* similar in coding.  This has
  52* allowed for a very large amount of code to be generated in a fairly
  53* short amount of time (i.e. cut, paste, and modify).  The result is
  54* that much of the code below could have been folded into subroutines
  55* for a large reduction in size of this file.  The downside would be
  56* that there would be a penalty in execution speed.  The file could
  57* also have been *MUCH* larger by inlining certain functions which
  58* were called.  This could have resulted even faster execution.  The
  59* prime directive I used to decide whether to inline the code or to
  60* modularize it, was basically: 1) no unnecessary subroutine calls,
  61* 2) no routines more than about 200 lines in size, and 3) modularize
  62* any code that I might not get right the first time.  The fetch_*
  63* subroutines fall into the latter category.  The The decode_* fall
  64* into the second category.  The coding of the "switch(mod){ .... }"
  65* in many of the subroutines below falls into the first category.
  66* Especially, the coding of {add,and,or,sub,...}_{byte,word}
  67* subroutines are an especially glaring case of the third guideline.
  68* Since so much of the code is cloned from other modules (compare
  69* opcode #00 to opcode #01), making the basic operations subroutine
  70* calls is especially important; otherwise mistakes in coding an
  71* "add" would represent a nightmare in maintenance.
  72*
  73* Jason ported this file to u-boot. place all the function pointer in
  74* the got2 sector. Removed some opcode.
  75*
  76****************************************************************************/
  77
  78#include <common.h>
  79#include "x86emu/x86emui.h"
  80
  81/*----------------------------- Implementation ----------------------------*/
  82
  83/* constant arrays to do several instructions in just one function */
  84
  85#ifdef DEBUG
  86static char *x86emu_GenOpName[8] = {
  87    "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
  88#endif
  89
  90/* used by several opcodes  */
  91static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
  92{
  93    add_byte,           /* 00 */
  94    or_byte,            /* 01 */
  95    adc_byte,           /* 02 */
  96    sbb_byte,           /* 03 */
  97    and_byte,           /* 04 */
  98    sub_byte,           /* 05 */
  99    xor_byte,           /* 06 */
 100    cmp_byte,           /* 07 */
 101};
 102
 103static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(GOT2_TYPE))) =
 104{
 105    add_word,           /*00 */
 106    or_word,            /*01 */
 107    adc_word,           /*02 */
 108    sbb_word,           /*03 */
 109    and_word,           /*04 */
 110    sub_word,           /*05 */
 111    xor_word,           /*06 */
 112    cmp_word,           /*07 */
 113};
 114
 115static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(GOT2_TYPE))) =
 116{
 117    add_long,           /*00 */
 118    or_long,            /*01 */
 119    adc_long,           /*02 */
 120    sbb_long,           /*03 */
 121    and_long,           /*04 */
 122    sub_long,           /*05 */
 123    xor_long,           /*06 */
 124    cmp_long,           /*07 */
 125};
 126
 127/* used by opcodes 80, c0, d0, and d2. */
 128static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
 129{
 130    rol_byte,
 131    ror_byte,
 132    rcl_byte,
 133    rcr_byte,
 134    shl_byte,
 135    shr_byte,
 136    shl_byte,           /* sal_byte === shl_byte  by definition */
 137    sar_byte,
 138};
 139
 140/* used by opcodes c1, d1, and d3. */
 141static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
 142{
 143    rol_word,
 144    ror_word,
 145    rcl_word,
 146    rcr_word,
 147    shl_word,
 148    shr_word,
 149    shl_word,           /* sal_byte === shl_byte  by definition */
 150    sar_word,
 151};
 152
 153/* used by opcodes c1, d1, and d3. */
 154static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
 155{
 156    rol_long,
 157    ror_long,
 158    rcl_long,
 159    rcr_long,
 160    shl_long,
 161    shr_long,
 162    shl_long,           /* sal_byte === shl_byte  by definition */
 163    sar_long,
 164};
 165
 166#ifdef DEBUG
 167
 168static char *opF6_names[8] =
 169  { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
 170
 171#endif
 172
 173/****************************************************************************
 174PARAMETERS:
 175op1 - Instruction op code
 176
 177REMARKS:
 178Handles illegal opcodes.
 179****************************************************************************/
 180void x86emuOp_illegal_op(
 181    u8 op1)
 182{
 183    START_OF_INSTR();
 184    if (M.x86.R_SP != 0) {
 185        DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
 186        TRACE_REGS();
 187        DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
 188            M.x86.R_CS, M.x86.R_IP-1,op1));
 189        HALT_SYS();
 190        }
 191    else {
 192        /* If we get here, it means the stack pointer is back to zero
 193         * so we are just returning from an emulator service call
 194         * so therte is no need to display an error message. We trap
 195         * the emulator with an 0xF1 opcode to finish the service
 196         * call.
 197         */
 198        X86EMU_halt_sys();
 199        }
 200    END_OF_INSTR();
 201}
 202
 203/****************************************************************************
 204REMARKS:
 205Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
 206****************************************************************************/
 207void x86emuOp_genop_byte_RM_R(u8 op1)
 208{
 209    int mod, rl, rh;
 210    uint destoffset;
 211    u8 *destreg, *srcreg;
 212    u8 destval;
 213
 214    op1 = (op1 >> 3) & 0x7;
 215
 216    START_OF_INSTR();
 217    DECODE_PRINTF(x86emu_GenOpName[op1]);
 218    DECODE_PRINTF("\t");
 219    FETCH_DECODE_MODRM(mod, rh, rl);
 220    if(mod<3)
 221        { destoffset = decode_rmXX_address(mod,rl);
 222        DECODE_PRINTF(",");
 223        destval = fetch_data_byte(destoffset);
 224        srcreg = DECODE_RM_BYTE_REGISTER(rh);
 225        DECODE_PRINTF("\n");
 226        TRACE_AND_STEP();
 227        destval = genop_byte_operation[op1](destval, *srcreg);
 228        store_data_byte(destoffset, destval);
 229        }
 230    else
 231        {                       /* register to register */
 232        destreg = DECODE_RM_BYTE_REGISTER(rl);
 233        DECODE_PRINTF(",");
 234        srcreg = DECODE_RM_BYTE_REGISTER(rh);
 235        DECODE_PRINTF("\n");
 236        TRACE_AND_STEP();
 237        *destreg = genop_byte_operation[op1](*destreg, *srcreg);
 238        }
 239    DECODE_CLEAR_SEGOVR();
 240    END_OF_INSTR();
 241}
 242
 243/****************************************************************************
 244REMARKS:
 245Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
 246****************************************************************************/
 247void x86emuOp_genop_word_RM_R(u8 op1)
 248{
 249    int mod, rl, rh;
 250    uint destoffset;
 251
 252    op1 = (op1 >> 3) & 0x7;
 253
 254    START_OF_INSTR();
 255    DECODE_PRINTF(x86emu_GenOpName[op1]);
 256    DECODE_PRINTF("\t");
 257    FETCH_DECODE_MODRM(mod, rh, rl);
 258
 259    if(mod<3) {
 260        destoffset = decode_rmXX_address(mod,rl);
 261        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 262            u32 destval;
 263            u32 *srcreg;
 264
 265            DECODE_PRINTF(",");
 266            destval = fetch_data_long(destoffset);
 267            srcreg = DECODE_RM_LONG_REGISTER(rh);
 268            DECODE_PRINTF("\n");
 269            TRACE_AND_STEP();
 270            destval = genop_long_operation[op1](destval, *srcreg);
 271            store_data_long(destoffset, destval);
 272        } else {
 273            u16 destval;
 274            u16 *srcreg;
 275
 276            DECODE_PRINTF(",");
 277            destval = fetch_data_word(destoffset);
 278            srcreg = DECODE_RM_WORD_REGISTER(rh);
 279            DECODE_PRINTF("\n");
 280            TRACE_AND_STEP();
 281            destval = genop_word_operation[op1](destval, *srcreg);
 282            store_data_word(destoffset, destval);
 283        }
 284    } else {                    /* register to register */
 285        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 286            u32 *destreg,*srcreg;
 287
 288            destreg = DECODE_RM_LONG_REGISTER(rl);
 289            DECODE_PRINTF(",");
 290            srcreg = DECODE_RM_LONG_REGISTER(rh);
 291            DECODE_PRINTF("\n");
 292            TRACE_AND_STEP();
 293            *destreg = genop_long_operation[op1](*destreg, *srcreg);
 294        } else {
 295            u16 *destreg,*srcreg;
 296
 297            destreg = DECODE_RM_WORD_REGISTER(rl);
 298            DECODE_PRINTF(",");
 299            srcreg = DECODE_RM_WORD_REGISTER(rh);
 300            DECODE_PRINTF("\n");
 301            TRACE_AND_STEP();
 302            *destreg = genop_word_operation[op1](*destreg, *srcreg);
 303        }
 304    }
 305    DECODE_CLEAR_SEGOVR();
 306    END_OF_INSTR();
 307}
 308
 309/****************************************************************************
 310REMARKS:
 311Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
 312****************************************************************************/
 313void x86emuOp_genop_byte_R_RM(u8 op1)
 314{
 315    int mod, rl, rh;
 316    u8 *destreg, *srcreg;
 317    uint srcoffset;
 318    u8 srcval;
 319
 320    op1 = (op1 >> 3) & 0x7;
 321
 322    START_OF_INSTR();
 323    DECODE_PRINTF(x86emu_GenOpName[op1]);
 324    DECODE_PRINTF("\t");
 325    FETCH_DECODE_MODRM(mod, rh, rl);
 326    if (mod < 3) {
 327        destreg = DECODE_RM_BYTE_REGISTER(rh);
 328        DECODE_PRINTF(",");
 329        srcoffset = decode_rmXX_address(mod,rl);
 330        srcval = fetch_data_byte(srcoffset);
 331    } else {     /* register to register */
 332        destreg = DECODE_RM_BYTE_REGISTER(rh);
 333        DECODE_PRINTF(",");
 334        srcreg = DECODE_RM_BYTE_REGISTER(rl);
 335        srcval = *srcreg;
 336    }
 337    DECODE_PRINTF("\n");
 338    TRACE_AND_STEP();
 339    *destreg = genop_byte_operation[op1](*destreg, srcval);
 340
 341    DECODE_CLEAR_SEGOVR();
 342    END_OF_INSTR();
 343}
 344
 345/****************************************************************************
 346REMARKS:
 347Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
 348****************************************************************************/
 349void x86emuOp_genop_word_R_RM(u8 op1)
 350{
 351    int mod, rl, rh;
 352    uint srcoffset;
 353    u32 *destreg32, srcval;
 354    u16 *destreg;
 355
 356    op1 = (op1 >> 3) & 0x7;
 357
 358    START_OF_INSTR();
 359    DECODE_PRINTF(x86emu_GenOpName[op1]);
 360    DECODE_PRINTF("\t");
 361    FETCH_DECODE_MODRM(mod, rh, rl);
 362    if (mod < 3) {
 363        srcoffset = decode_rmXX_address(mod,rl);
 364        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 365            destreg32 = DECODE_RM_LONG_REGISTER(rh);
 366            DECODE_PRINTF(",");
 367            srcval = fetch_data_long(srcoffset);
 368            DECODE_PRINTF("\n");
 369            TRACE_AND_STEP();
 370            *destreg32 = genop_long_operation[op1](*destreg32, srcval);
 371        } else {
 372            destreg = DECODE_RM_WORD_REGISTER(rh);
 373            DECODE_PRINTF(",");
 374            srcval = fetch_data_word(srcoffset);
 375            DECODE_PRINTF("\n");
 376            TRACE_AND_STEP();
 377            *destreg = genop_word_operation[op1](*destreg, srcval);
 378        }
 379    } else {                     /* register to register */
 380        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 381            u32 *srcreg;
 382            destreg32 = DECODE_RM_LONG_REGISTER(rh);
 383            DECODE_PRINTF(",");
 384            srcreg = DECODE_RM_LONG_REGISTER(rl);
 385            DECODE_PRINTF("\n");
 386            TRACE_AND_STEP();
 387            *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
 388        } else {
 389            u16 *srcreg;
 390            destreg = DECODE_RM_WORD_REGISTER(rh);
 391            DECODE_PRINTF(",");
 392            srcreg = DECODE_RM_WORD_REGISTER(rl);
 393            DECODE_PRINTF("\n");
 394            TRACE_AND_STEP();
 395            *destreg = genop_word_operation[op1](*destreg, *srcreg);
 396        }
 397    }
 398    DECODE_CLEAR_SEGOVR();
 399    END_OF_INSTR();
 400}
 401
 402/****************************************************************************
 403REMARKS:
 404Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
 405****************************************************************************/
 406void x86emuOp_genop_byte_AL_IMM(u8 op1)
 407{
 408    u8 srcval;
 409
 410    op1 = (op1 >> 3) & 0x7;
 411
 412    START_OF_INSTR();
 413    DECODE_PRINTF(x86emu_GenOpName[op1]);
 414    DECODE_PRINTF("\tAL,");
 415    srcval = fetch_byte_imm();
 416    DECODE_PRINTF2("%x\n", srcval);
 417    TRACE_AND_STEP();
 418    M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
 419    DECODE_CLEAR_SEGOVR();
 420    END_OF_INSTR();
 421}
 422
 423/****************************************************************************
 424REMARKS:
 425Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
 426****************************************************************************/
 427void x86emuOp_genop_word_AX_IMM(u8 op1)
 428{
 429    u32 srcval;
 430
 431    op1 = (op1 >> 3) & 0x7;
 432
 433    START_OF_INSTR();
 434    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 435        DECODE_PRINTF(x86emu_GenOpName[op1]);
 436        DECODE_PRINTF("\tEAX,");
 437        srcval = fetch_long_imm();
 438    } else {
 439        DECODE_PRINTF(x86emu_GenOpName[op1]);
 440        DECODE_PRINTF("\tAX,");
 441        srcval = fetch_word_imm();
 442    }
 443    DECODE_PRINTF2("%x\n", srcval);
 444    TRACE_AND_STEP();
 445    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 446        M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
 447    } else {
 448        M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
 449    }
 450    DECODE_CLEAR_SEGOVR();
 451    END_OF_INSTR();
 452}
 453
 454/****************************************************************************
 455REMARKS:
 456Handles opcode 0x06
 457****************************************************************************/
 458void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
 459{
 460    START_OF_INSTR();
 461    DECODE_PRINTF("PUSH\tES\n");
 462    TRACE_AND_STEP();
 463    push_word(M.x86.R_ES);
 464    DECODE_CLEAR_SEGOVR();
 465    END_OF_INSTR();
 466}
 467
 468/****************************************************************************
 469REMARKS:
 470Handles opcode 0x07
 471****************************************************************************/
 472void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
 473{
 474    START_OF_INSTR();
 475    DECODE_PRINTF("POP\tES\n");
 476    TRACE_AND_STEP();
 477    M.x86.R_ES = pop_word();
 478    DECODE_CLEAR_SEGOVR();
 479    END_OF_INSTR();
 480}
 481
 482/****************************************************************************
 483REMARKS:
 484Handles opcode 0x0e
 485****************************************************************************/
 486void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
 487{
 488    START_OF_INSTR();
 489    DECODE_PRINTF("PUSH\tCS\n");
 490    TRACE_AND_STEP();
 491    push_word(M.x86.R_CS);
 492    DECODE_CLEAR_SEGOVR();
 493    END_OF_INSTR();
 494}
 495
 496/****************************************************************************
 497REMARKS:
 498Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
 499****************************************************************************/
 500void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
 501{
 502    u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
 503    INC_DECODED_INST_LEN(1);
 504    (*x86emu_optab2[op2])(op2);
 505}
 506
 507/****************************************************************************
 508REMARKS:
 509Handles opcode 0x16
 510****************************************************************************/
 511void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
 512{
 513    START_OF_INSTR();
 514    DECODE_PRINTF("PUSH\tSS\n");
 515    TRACE_AND_STEP();
 516    push_word(M.x86.R_SS);
 517    DECODE_CLEAR_SEGOVR();
 518    END_OF_INSTR();
 519}
 520
 521/****************************************************************************
 522REMARKS:
 523Handles opcode 0x17
 524****************************************************************************/
 525void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
 526{
 527    START_OF_INSTR();
 528    DECODE_PRINTF("POP\tSS\n");
 529    TRACE_AND_STEP();
 530    M.x86.R_SS = pop_word();
 531    DECODE_CLEAR_SEGOVR();
 532    END_OF_INSTR();
 533}
 534
 535/****************************************************************************
 536REMARKS:
 537Handles opcode 0x1e
 538****************************************************************************/
 539void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
 540{
 541    START_OF_INSTR();
 542    DECODE_PRINTF("PUSH\tDS\n");
 543    TRACE_AND_STEP();
 544    push_word(M.x86.R_DS);
 545    DECODE_CLEAR_SEGOVR();
 546    END_OF_INSTR();
 547}
 548
 549/****************************************************************************
 550REMARKS:
 551Handles opcode 0x1f
 552****************************************************************************/
 553void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
 554{
 555    START_OF_INSTR();
 556    DECODE_PRINTF("POP\tDS\n");
 557    TRACE_AND_STEP();
 558    M.x86.R_DS = pop_word();
 559    DECODE_CLEAR_SEGOVR();
 560    END_OF_INSTR();
 561}
 562
 563/****************************************************************************
 564REMARKS:
 565Handles opcode 0x26
 566****************************************************************************/
 567void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
 568{
 569    START_OF_INSTR();
 570    DECODE_PRINTF("ES:\n");
 571    TRACE_AND_STEP();
 572    M.x86.mode |= SYSMODE_SEGOVR_ES;
 573    /*
 574     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
 575     * opcode subroutines we do not want to do this.
 576     */
 577    END_OF_INSTR();
 578}
 579
 580/****************************************************************************
 581REMARKS:
 582Handles opcode 0x27
 583****************************************************************************/
 584void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
 585{
 586    START_OF_INSTR();
 587    DECODE_PRINTF("DAA\n");
 588    TRACE_AND_STEP();
 589    M.x86.R_AL = daa_byte(M.x86.R_AL);
 590    DECODE_CLEAR_SEGOVR();
 591    END_OF_INSTR();
 592}
 593
 594/****************************************************************************
 595REMARKS:
 596Handles opcode 0x2e
 597****************************************************************************/
 598void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
 599{
 600    START_OF_INSTR();
 601    DECODE_PRINTF("CS:\n");
 602    TRACE_AND_STEP();
 603    M.x86.mode |= SYSMODE_SEGOVR_CS;
 604    /* note no DECODE_CLEAR_SEGOVR here. */
 605    END_OF_INSTR();
 606}
 607
 608/****************************************************************************
 609REMARKS:
 610Handles opcode 0x2f
 611****************************************************************************/
 612void x86emuOp_das(u8 X86EMU_UNUSED(op1))
 613{
 614    START_OF_INSTR();
 615    DECODE_PRINTF("DAS\n");
 616    TRACE_AND_STEP();
 617    M.x86.R_AL = das_byte(M.x86.R_AL);
 618    DECODE_CLEAR_SEGOVR();
 619    END_OF_INSTR();
 620}
 621
 622/****************************************************************************
 623REMARKS:
 624Handles opcode 0x36
 625****************************************************************************/
 626void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
 627{
 628    START_OF_INSTR();
 629    DECODE_PRINTF("SS:\n");
 630    TRACE_AND_STEP();
 631    M.x86.mode |= SYSMODE_SEGOVR_SS;
 632    /* no DECODE_CLEAR_SEGOVR ! */
 633    END_OF_INSTR();
 634}
 635
 636/****************************************************************************
 637REMARKS:
 638Handles opcode 0x37
 639****************************************************************************/
 640void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
 641{
 642    START_OF_INSTR();
 643    DECODE_PRINTF("AAA\n");
 644    TRACE_AND_STEP();
 645    M.x86.R_AX = aaa_word(M.x86.R_AX);
 646    DECODE_CLEAR_SEGOVR();
 647    END_OF_INSTR();
 648}
 649
 650/****************************************************************************
 651REMARKS:
 652Handles opcode 0x3e
 653****************************************************************************/
 654void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
 655{
 656    START_OF_INSTR();
 657    DECODE_PRINTF("DS:\n");
 658    TRACE_AND_STEP();
 659    M.x86.mode |= SYSMODE_SEGOVR_DS;
 660    /* NO DECODE_CLEAR_SEGOVR! */
 661    END_OF_INSTR();
 662}
 663
 664/****************************************************************************
 665REMARKS:
 666Handles opcode 0x3f
 667****************************************************************************/
 668void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
 669{
 670    START_OF_INSTR();
 671    DECODE_PRINTF("AAS\n");
 672    TRACE_AND_STEP();
 673    M.x86.R_AX = aas_word(M.x86.R_AX);
 674    DECODE_CLEAR_SEGOVR();
 675    END_OF_INSTR();
 676}
 677
 678/****************************************************************************
 679REMARKS:
 680Handles opcode 0x40 - 0x47
 681****************************************************************************/
 682void x86emuOp_inc_register(u8 op1)
 683{
 684    START_OF_INSTR();
 685    op1 &= 0x7;
 686    DECODE_PRINTF("INC\t");
 687    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 688        u32 *reg;
 689        reg = DECODE_RM_LONG_REGISTER(op1);
 690        DECODE_PRINTF("\n");
 691        TRACE_AND_STEP();
 692        *reg = inc_long(*reg);
 693    } else {
 694        u16 *reg;
 695        reg = DECODE_RM_WORD_REGISTER(op1);
 696        DECODE_PRINTF("\n");
 697        TRACE_AND_STEP();
 698        *reg = inc_word(*reg);
 699    }
 700    DECODE_CLEAR_SEGOVR();
 701    END_OF_INSTR();
 702}
 703
 704/****************************************************************************
 705REMARKS:
 706Handles opcode 0x48 - 0x4F
 707****************************************************************************/
 708void x86emuOp_dec_register(u8 op1)
 709{
 710    START_OF_INSTR();
 711    op1 &= 0x7;
 712    DECODE_PRINTF("DEC\t");
 713    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 714        u32 *reg;
 715        reg = DECODE_RM_LONG_REGISTER(op1);
 716        DECODE_PRINTF("\n");
 717        TRACE_AND_STEP();
 718        *reg = dec_long(*reg);
 719    } else {
 720        u16 *reg;
 721        reg = DECODE_RM_WORD_REGISTER(op1);
 722        DECODE_PRINTF("\n");
 723        TRACE_AND_STEP();
 724        *reg = dec_word(*reg);
 725    }
 726    DECODE_CLEAR_SEGOVR();
 727    END_OF_INSTR();
 728}
 729
 730/****************************************************************************
 731REMARKS:
 732Handles opcode 0x50 - 0x57
 733****************************************************************************/
 734void x86emuOp_push_register(u8 op1)
 735{
 736    START_OF_INSTR();
 737    op1 &= 0x7;
 738    DECODE_PRINTF("PUSH\t");
 739    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 740        u32 *reg;
 741        reg = DECODE_RM_LONG_REGISTER(op1);
 742        DECODE_PRINTF("\n");
 743        TRACE_AND_STEP();
 744        push_long(*reg);
 745    } else {
 746        u16 *reg;
 747        reg = DECODE_RM_WORD_REGISTER(op1);
 748        DECODE_PRINTF("\n");
 749        TRACE_AND_STEP();
 750        push_word(*reg);
 751    }
 752    DECODE_CLEAR_SEGOVR();
 753    END_OF_INSTR();
 754}
 755
 756/****************************************************************************
 757REMARKS:
 758Handles opcode 0x58 - 0x5F
 759****************************************************************************/
 760void x86emuOp_pop_register(u8 op1)
 761{
 762    START_OF_INSTR();
 763    op1 &= 0x7;
 764    DECODE_PRINTF("POP\t");
 765    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 766        u32 *reg;
 767        reg = DECODE_RM_LONG_REGISTER(op1);
 768        DECODE_PRINTF("\n");
 769        TRACE_AND_STEP();
 770        *reg = pop_long();
 771    } else {
 772        u16 *reg;
 773        reg = DECODE_RM_WORD_REGISTER(op1);
 774        DECODE_PRINTF("\n");
 775        TRACE_AND_STEP();
 776        *reg = pop_word();
 777    }
 778    DECODE_CLEAR_SEGOVR();
 779    END_OF_INSTR();
 780}
 781
 782/****************************************************************************
 783REMARKS:
 784Handles opcode 0x60
 785****************************************************************************/
 786void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
 787{
 788    START_OF_INSTR();
 789    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 790        DECODE_PRINTF("PUSHAD\n");
 791    } else {
 792        DECODE_PRINTF("PUSHA\n");
 793    }
 794    TRACE_AND_STEP();
 795    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 796        u32 old_sp = M.x86.R_ESP;
 797
 798        push_long(M.x86.R_EAX);
 799        push_long(M.x86.R_ECX);
 800        push_long(M.x86.R_EDX);
 801        push_long(M.x86.R_EBX);
 802        push_long(old_sp);
 803        push_long(M.x86.R_EBP);
 804        push_long(M.x86.R_ESI);
 805        push_long(M.x86.R_EDI);
 806    } else {
 807        u16 old_sp = M.x86.R_SP;
 808
 809        push_word(M.x86.R_AX);
 810        push_word(M.x86.R_CX);
 811        push_word(M.x86.R_DX);
 812        push_word(M.x86.R_BX);
 813        push_word(old_sp);
 814        push_word(M.x86.R_BP);
 815        push_word(M.x86.R_SI);
 816        push_word(M.x86.R_DI);
 817    }
 818    DECODE_CLEAR_SEGOVR();
 819    END_OF_INSTR();
 820}
 821
 822/****************************************************************************
 823REMARKS:
 824Handles opcode 0x61
 825****************************************************************************/
 826void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
 827{
 828    START_OF_INSTR();
 829    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 830        DECODE_PRINTF("POPAD\n");
 831    } else {
 832        DECODE_PRINTF("POPA\n");
 833    }
 834    TRACE_AND_STEP();
 835    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 836        M.x86.R_EDI = pop_long();
 837        M.x86.R_ESI = pop_long();
 838        M.x86.R_EBP = pop_long();
 839        M.x86.R_ESP += 4;              /* skip ESP */
 840        M.x86.R_EBX = pop_long();
 841        M.x86.R_EDX = pop_long();
 842        M.x86.R_ECX = pop_long();
 843        M.x86.R_EAX = pop_long();
 844    } else {
 845        M.x86.R_DI = pop_word();
 846        M.x86.R_SI = pop_word();
 847        M.x86.R_BP = pop_word();
 848        M.x86.R_SP += 2;               /* skip SP */
 849        M.x86.R_BX = pop_word();
 850        M.x86.R_DX = pop_word();
 851        M.x86.R_CX = pop_word();
 852        M.x86.R_AX = pop_word();
 853    }
 854    DECODE_CLEAR_SEGOVR();
 855    END_OF_INSTR();
 856}
 857
 858/*opcode 0x62   ILLEGAL OP, calls x86emuOp_illegal_op() */
 859/*opcode 0x63   ILLEGAL OP, calls x86emuOp_illegal_op() */
 860
 861/****************************************************************************
 862REMARKS:
 863Handles opcode 0x64
 864****************************************************************************/
 865void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
 866{
 867    START_OF_INSTR();
 868    DECODE_PRINTF("FS:\n");
 869    TRACE_AND_STEP();
 870    M.x86.mode |= SYSMODE_SEGOVR_FS;
 871    /*
 872     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
 873     * opcode subroutines we do not want to do this.
 874     */
 875    END_OF_INSTR();
 876}
 877
 878/****************************************************************************
 879REMARKS:
 880Handles opcode 0x65
 881****************************************************************************/
 882void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
 883{
 884    START_OF_INSTR();
 885    DECODE_PRINTF("GS:\n");
 886    TRACE_AND_STEP();
 887    M.x86.mode |= SYSMODE_SEGOVR_GS;
 888    /*
 889     * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
 890     * opcode subroutines we do not want to do this.
 891     */
 892    END_OF_INSTR();
 893}
 894
 895/****************************************************************************
 896REMARKS:
 897Handles opcode 0x66 - prefix for 32-bit register
 898****************************************************************************/
 899void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
 900{
 901    START_OF_INSTR();
 902    DECODE_PRINTF("DATA:\n");
 903    TRACE_AND_STEP();
 904    M.x86.mode |= SYSMODE_PREFIX_DATA;
 905    /* note no DECODE_CLEAR_SEGOVR here. */
 906    END_OF_INSTR();
 907}
 908
 909/****************************************************************************
 910REMARKS:
 911Handles opcode 0x67 - prefix for 32-bit address
 912****************************************************************************/
 913void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
 914{
 915    START_OF_INSTR();
 916    DECODE_PRINTF("ADDR:\n");
 917    TRACE_AND_STEP();
 918    M.x86.mode |= SYSMODE_PREFIX_ADDR;
 919    /* note no DECODE_CLEAR_SEGOVR here. */
 920    END_OF_INSTR();
 921}
 922
 923/****************************************************************************
 924REMARKS:
 925Handles opcode 0x68
 926****************************************************************************/
 927void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
 928{
 929    u32 imm;
 930
 931    START_OF_INSTR();
 932    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 933        imm = fetch_long_imm();
 934    } else {
 935        imm = fetch_word_imm();
 936    }
 937    DECODE_PRINTF2("PUSH\t%x\n", imm);
 938    TRACE_AND_STEP();
 939    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 940        push_long(imm);
 941    } else {
 942        push_word((u16)imm);
 943    }
 944    DECODE_CLEAR_SEGOVR();
 945    END_OF_INSTR();
 946}
 947
 948/****************************************************************************
 949REMARKS:
 950Handles opcode 0x69
 951****************************************************************************/
 952void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
 953{
 954    int mod, rl, rh;
 955    uint srcoffset;
 956
 957    START_OF_INSTR();
 958    DECODE_PRINTF("IMUL\t");
 959    FETCH_DECODE_MODRM(mod, rh, rl);
 960    if (mod < 3) {
 961        srcoffset = decode_rmXX_address(mod, rl);
 962        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
 963            u32 *destreg;
 964            u32 srcval;
 965            u32 res_lo,res_hi;
 966            s32 imm;
 967
 968            destreg = DECODE_RM_LONG_REGISTER(rh);
 969            DECODE_PRINTF(",");
 970            srcval = fetch_data_long(srcoffset);
 971            imm = fetch_long_imm();
 972            DECODE_PRINTF2(",%d\n", (s32)imm);
 973            TRACE_AND_STEP();
 974            imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
 975            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
 976                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
 977                CLEAR_FLAG(F_CF);
 978                CLEAR_FLAG(F_OF);
 979            } else {
 980                SET_FLAG(F_CF);
 981                SET_FLAG(F_OF);
 982            }
 983            *destreg = (u32)res_lo;
 984        } else {
 985            u16 *destreg;
 986            u16 srcval;
 987            u32 res;
 988            s16 imm;
 989
 990            destreg = DECODE_RM_WORD_REGISTER(rh);
 991            DECODE_PRINTF(",");
 992            srcval = fetch_data_word(srcoffset);
 993            imm = fetch_word_imm();
 994            DECODE_PRINTF2(",%d\n", (s32)imm);
 995            TRACE_AND_STEP();
 996            res = (s16)srcval * (s16)imm;
 997            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
 998                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
 999                CLEAR_FLAG(F_CF);
1000                CLEAR_FLAG(F_OF);
1001            } else {
1002                SET_FLAG(F_CF);
1003                SET_FLAG(F_OF);
1004            }
1005            *destreg = (u16)res;
1006        }
1007    } else {                     /* register to register */
1008        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1009            u32 *destreg,*srcreg;
1010            u32 res_lo,res_hi;
1011            s32 imm;
1012
1013            destreg = DECODE_RM_LONG_REGISTER(rh);
1014            DECODE_PRINTF(",");
1015            srcreg = DECODE_RM_LONG_REGISTER(rl);
1016            imm = fetch_long_imm();
1017            DECODE_PRINTF2(",%d\n", (s32)imm);
1018            TRACE_AND_STEP();
1019            imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1020            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1021                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1022                CLEAR_FLAG(F_CF);
1023                CLEAR_FLAG(F_OF);
1024            } else {
1025                SET_FLAG(F_CF);
1026                SET_FLAG(F_OF);
1027            }
1028            *destreg = (u32)res_lo;
1029        } else {
1030            u16 *destreg,*srcreg;
1031            u32 res;
1032            s16 imm;
1033
1034            destreg = DECODE_RM_WORD_REGISTER(rh);
1035            DECODE_PRINTF(",");
1036            srcreg = DECODE_RM_WORD_REGISTER(rl);
1037            imm = fetch_word_imm();
1038            DECODE_PRINTF2(",%d\n", (s32)imm);
1039            res = (s16)*srcreg * (s16)imm;
1040            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1041                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1042                CLEAR_FLAG(F_CF);
1043                CLEAR_FLAG(F_OF);
1044            } else {
1045                SET_FLAG(F_CF);
1046                SET_FLAG(F_OF);
1047            }
1048            *destreg = (u16)res;
1049        }
1050    }
1051    DECODE_CLEAR_SEGOVR();
1052    END_OF_INSTR();
1053}
1054
1055/****************************************************************************
1056REMARKS:
1057Handles opcode 0x6a
1058****************************************************************************/
1059void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1060{
1061    s16 imm;
1062
1063    START_OF_INSTR();
1064    imm = (s8)fetch_byte_imm();
1065    DECODE_PRINTF2("PUSH\t%d\n", imm);
1066    TRACE_AND_STEP();
1067    push_word(imm);
1068    DECODE_CLEAR_SEGOVR();
1069    END_OF_INSTR();
1070}
1071
1072/****************************************************************************
1073REMARKS:
1074Handles opcode 0x6b
1075****************************************************************************/
1076void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1077{
1078    int mod, rl, rh;
1079    uint srcoffset;
1080    s8  imm;
1081
1082    START_OF_INSTR();
1083    DECODE_PRINTF("IMUL\t");
1084    FETCH_DECODE_MODRM(mod, rh, rl);
1085    if (mod < 3) {
1086        srcoffset = decode_rmXX_address(mod, rl);
1087        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1088            u32 *destreg;
1089            u32 srcval;
1090            u32 res_lo,res_hi;
1091
1092            destreg = DECODE_RM_LONG_REGISTER(rh);
1093            DECODE_PRINTF(",");
1094            srcval = fetch_data_long(srcoffset);
1095            imm = fetch_byte_imm();
1096            DECODE_PRINTF2(",%d\n", (s32)imm);
1097            TRACE_AND_STEP();
1098            imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1099            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1100                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1101                CLEAR_FLAG(F_CF);
1102                CLEAR_FLAG(F_OF);
1103            } else {
1104                SET_FLAG(F_CF);
1105                SET_FLAG(F_OF);
1106            }
1107            *destreg = (u32)res_lo;
1108        } else {
1109            u16 *destreg;
1110            u16 srcval;
1111            u32 res;
1112
1113            destreg = DECODE_RM_WORD_REGISTER(rh);
1114            DECODE_PRINTF(",");
1115            srcval = fetch_data_word(srcoffset);
1116            imm = fetch_byte_imm();
1117            DECODE_PRINTF2(",%d\n", (s32)imm);
1118            TRACE_AND_STEP();
1119            res = (s16)srcval * (s16)imm;
1120            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1121                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1122                CLEAR_FLAG(F_CF);
1123                CLEAR_FLAG(F_OF);
1124            } else {
1125                SET_FLAG(F_CF);
1126                SET_FLAG(F_OF);
1127            }
1128            *destreg = (u16)res;
1129        }
1130    } else {                     /* register to register */
1131        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1132            u32 *destreg,*srcreg;
1133            u32 res_lo,res_hi;
1134
1135            destreg = DECODE_RM_LONG_REGISTER(rh);
1136            DECODE_PRINTF(",");
1137            srcreg = DECODE_RM_LONG_REGISTER(rl);
1138            imm = fetch_byte_imm();
1139            DECODE_PRINTF2(",%d\n", (s32)imm);
1140            TRACE_AND_STEP();
1141            imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1142            if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1143                (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1144                CLEAR_FLAG(F_CF);
1145                CLEAR_FLAG(F_OF);
1146            } else {
1147                SET_FLAG(F_CF);
1148                SET_FLAG(F_OF);
1149            }
1150            *destreg = (u32)res_lo;
1151        } else {
1152            u16 *destreg,*srcreg;
1153            u32 res;
1154
1155            destreg = DECODE_RM_WORD_REGISTER(rh);
1156            DECODE_PRINTF(",");
1157            srcreg = DECODE_RM_WORD_REGISTER(rl);
1158            imm = fetch_byte_imm();
1159            DECODE_PRINTF2(",%d\n", (s32)imm);
1160            TRACE_AND_STEP();
1161            res = (s16)*srcreg * (s16)imm;
1162            if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1163                (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1164                CLEAR_FLAG(F_CF);
1165                CLEAR_FLAG(F_OF);
1166            } else {
1167                SET_FLAG(F_CF);
1168                SET_FLAG(F_OF);
1169            }
1170            *destreg = (u16)res;
1171        }
1172    }
1173    DECODE_CLEAR_SEGOVR();
1174    END_OF_INSTR();
1175}
1176
1177/****************************************************************************
1178REMARKS:
1179Handles opcode 0x6c
1180****************************************************************************/
1181void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1182{
1183    START_OF_INSTR();
1184    DECODE_PRINTF("INSB\n");
1185    ins(1);
1186    TRACE_AND_STEP();
1187    DECODE_CLEAR_SEGOVR();
1188    END_OF_INSTR();
1189}
1190
1191/****************************************************************************
1192REMARKS:
1193Handles opcode 0x6d
1194****************************************************************************/
1195void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1196{
1197    START_OF_INSTR();
1198    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1199        DECODE_PRINTF("INSD\n");
1200        ins(4);
1201    } else {
1202        DECODE_PRINTF("INSW\n");
1203        ins(2);
1204    }
1205    TRACE_AND_STEP();
1206    DECODE_CLEAR_SEGOVR();
1207    END_OF_INSTR();
1208}
1209
1210/****************************************************************************
1211REMARKS:
1212Handles opcode 0x6e
1213****************************************************************************/
1214void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1215{
1216    START_OF_INSTR();
1217    DECODE_PRINTF("OUTSB\n");
1218    outs(1);
1219    TRACE_AND_STEP();
1220    DECODE_CLEAR_SEGOVR();
1221    END_OF_INSTR();
1222}
1223
1224/****************************************************************************
1225REMARKS:
1226Handles opcode 0x6f
1227****************************************************************************/
1228void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1229{
1230    START_OF_INSTR();
1231    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1232        DECODE_PRINTF("OUTSD\n");
1233        outs(4);
1234    } else {
1235        DECODE_PRINTF("OUTSW\n");
1236        outs(2);
1237    }
1238    TRACE_AND_STEP();
1239    DECODE_CLEAR_SEGOVR();
1240    END_OF_INSTR();
1241}
1242
1243/****************************************************************************
1244REMARKS:
1245Handles opcode 0x70 - 0x7F
1246****************************************************************************/
1247int x86emu_check_jump_condition(u8 op);
1248
1249void x86emuOp_jump_near_cond(u8 op1)
1250{
1251    s8 offset;
1252    u16 target;
1253    int cond;
1254
1255    /* jump to byte offset if overflow flag is set */
1256    START_OF_INSTR();
1257    cond = x86emu_check_jump_condition(op1 & 0xF);
1258    offset = (s8)fetch_byte_imm();
1259    target = (u16)(M.x86.R_IP + (s16)offset);
1260    DECODE_PRINTF2("%x\n", target);
1261    TRACE_AND_STEP();
1262    if (cond)
1263        M.x86.R_IP = target;
1264    DECODE_CLEAR_SEGOVR();
1265    END_OF_INSTR();
1266}
1267
1268/****************************************************************************
1269REMARKS:
1270Handles opcode 0x80
1271****************************************************************************/
1272void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1273{
1274    int mod, rl, rh;
1275    u8 *destreg;
1276    uint destoffset;
1277    u8 imm;
1278    u8 destval;
1279
1280    /*
1281     * Weirdo special case instruction format.  Part of the opcode
1282     * held below in "RH".  Doubly nested case would result, except
1283     * that the decoded instruction
1284     */
1285    START_OF_INSTR();
1286    FETCH_DECODE_MODRM(mod, rh, rl);
1287#ifdef DEBUG
1288    if (DEBUG_DECODE()) {
1289        /* XXX DECODE_PRINTF may be changed to something more
1290           general, so that it is important to leave the strings
1291           in the same format, even though the result is that the
1292           above test is done twice. */
1293
1294        switch (rh) {
1295        case 0:
1296            DECODE_PRINTF("ADD\t");
1297            break;
1298        case 1:
1299            DECODE_PRINTF("OR\t");
1300            break;
1301        case 2:
1302            DECODE_PRINTF("ADC\t");
1303            break;
1304        case 3:
1305            DECODE_PRINTF("SBB\t");
1306            break;
1307        case 4:
1308            DECODE_PRINTF("AND\t");
1309            break;
1310        case 5:
1311            DECODE_PRINTF("SUB\t");
1312            break;
1313        case 6:
1314            DECODE_PRINTF("XOR\t");
1315            break;
1316        case 7:
1317            DECODE_PRINTF("CMP\t");
1318            break;
1319        }
1320    }
1321#endif
1322    /* know operation, decode the mod byte to find the addressing
1323       mode. */
1324    if (mod < 3) {
1325        DECODE_PRINTF("BYTE PTR ");
1326        destoffset = decode_rmXX_address(mod, rl);
1327        DECODE_PRINTF(",");
1328        destval = fetch_data_byte(destoffset);
1329        imm = fetch_byte_imm();
1330        DECODE_PRINTF2("%x\n", imm);
1331        TRACE_AND_STEP();
1332        destval = (*genop_byte_operation[rh]) (destval, imm);
1333        if (rh != 7)
1334            store_data_byte(destoffset, destval);
1335    } else {                     /* register to register */
1336        destreg = DECODE_RM_BYTE_REGISTER(rl);
1337        DECODE_PRINTF(",");
1338        imm = fetch_byte_imm();
1339        DECODE_PRINTF2("%x\n", imm);
1340        TRACE_AND_STEP();
1341        destval = (*genop_byte_operation[rh]) (*destreg, imm);
1342        if (rh != 7)
1343            *destreg = destval;
1344    }
1345    DECODE_CLEAR_SEGOVR();
1346    END_OF_INSTR();
1347}
1348
1349/****************************************************************************
1350REMARKS:
1351Handles opcode 0x81
1352****************************************************************************/
1353void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1354{
1355    int mod, rl, rh;
1356    uint destoffset;
1357
1358    /*
1359     * Weirdo special case instruction format.  Part of the opcode
1360     * held below in "RH".  Doubly nested case would result, except
1361     * that the decoded instruction
1362     */
1363    START_OF_INSTR();
1364    FETCH_DECODE_MODRM(mod, rh, rl);
1365#ifdef DEBUG
1366    if (DEBUG_DECODE()) {
1367        /* XXX DECODE_PRINTF may be changed to something more
1368           general, so that it is important to leave the strings
1369           in the same format, even though the result is that the
1370           above test is done twice. */
1371
1372        switch (rh) {
1373        case 0:
1374            DECODE_PRINTF("ADD\t");
1375            break;
1376        case 1:
1377            DECODE_PRINTF("OR\t");
1378            break;
1379        case 2:
1380            DECODE_PRINTF("ADC\t");
1381            break;
1382        case 3:
1383            DECODE_PRINTF("SBB\t");
1384            break;
1385        case 4:
1386            DECODE_PRINTF("AND\t");
1387            break;
1388        case 5:
1389            DECODE_PRINTF("SUB\t");
1390            break;
1391        case 6:
1392            DECODE_PRINTF("XOR\t");
1393            break;
1394        case 7:
1395            DECODE_PRINTF("CMP\t");
1396            break;
1397        }
1398    }
1399#endif
1400    /*
1401     * Know operation, decode the mod byte to find the addressing
1402     * mode.
1403     */
1404    if (mod < 3) {
1405        DECODE_PRINTF("DWORD PTR ");
1406        destoffset = decode_rmXX_address(mod, rl);
1407        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1408            u32 destval,imm;
1409
1410            DECODE_PRINTF(",");
1411            destval = fetch_data_long(destoffset);
1412            imm = fetch_long_imm();
1413            DECODE_PRINTF2("%x\n", imm);
1414            TRACE_AND_STEP();
1415            destval = (*genop_long_operation[rh]) (destval, imm);
1416            if (rh != 7)
1417                store_data_long(destoffset, destval);
1418        } else {
1419            u16 destval,imm;
1420
1421            DECODE_PRINTF(",");
1422            destval = fetch_data_word(destoffset);
1423            imm = fetch_word_imm();
1424            DECODE_PRINTF2("%x\n", imm);
1425            TRACE_AND_STEP();
1426            destval = (*genop_word_operation[rh]) (destval, imm);
1427            if (rh != 7)
1428                store_data_word(destoffset, destval);
1429        }
1430    } else {                     /* register to register */
1431        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1432            u32 *destreg;
1433            u32 destval,imm;
1434
1435            destreg = DECODE_RM_LONG_REGISTER(rl);
1436            DECODE_PRINTF(",");
1437            imm = fetch_long_imm();
1438            DECODE_PRINTF2("%x\n", imm);
1439            TRACE_AND_STEP();
1440            destval = (*genop_long_operation[rh]) (*destreg, imm);
1441            if (rh != 7)
1442                *destreg = destval;
1443        } else {
1444            u16 *destreg;
1445            u16 destval,imm;
1446
1447            destreg = DECODE_RM_WORD_REGISTER(rl);
1448            DECODE_PRINTF(",");
1449            imm = fetch_word_imm();
1450            DECODE_PRINTF2("%x\n", imm);
1451            TRACE_AND_STEP();
1452            destval = (*genop_word_operation[rh]) (*destreg, imm);
1453            if (rh != 7)
1454                *destreg = destval;
1455        }
1456    }
1457    DECODE_CLEAR_SEGOVR();
1458    END_OF_INSTR();
1459}
1460
1461/****************************************************************************
1462REMARKS:
1463Handles opcode 0x82
1464****************************************************************************/
1465void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1466{
1467    int mod, rl, rh;
1468    u8 *destreg;
1469    uint destoffset;
1470    u8 imm;
1471    u8 destval;
1472
1473    /*
1474     * Weirdo special case instruction format.  Part of the opcode
1475     * held below in "RH".  Doubly nested case would result, except
1476     * that the decoded instruction Similar to opcode 81, except that
1477     * the immediate byte is sign extended to a word length.
1478     */
1479    START_OF_INSTR();
1480    FETCH_DECODE_MODRM(mod, rh, rl);
1481#ifdef DEBUG
1482    if (DEBUG_DECODE()) {
1483        /* XXX DECODE_PRINTF may be changed to something more
1484           general, so that it is important to leave the strings
1485           in the same format, even though the result is that the
1486           above test is done twice. */
1487        switch (rh) {
1488        case 0:
1489            DECODE_PRINTF("ADD\t");
1490            break;
1491        case 1:
1492            DECODE_PRINTF("OR\t");
1493            break;
1494        case 2:
1495            DECODE_PRINTF("ADC\t");
1496            break;
1497        case 3:
1498            DECODE_PRINTF("SBB\t");
1499            break;
1500        case 4:
1501            DECODE_PRINTF("AND\t");
1502            break;
1503        case 5:
1504            DECODE_PRINTF("SUB\t");
1505            break;
1506        case 6:
1507            DECODE_PRINTF("XOR\t");
1508            break;
1509        case 7:
1510            DECODE_PRINTF("CMP\t");
1511            break;
1512        }
1513    }
1514#endif
1515    /* know operation, decode the mod byte to find the addressing
1516       mode. */
1517    if (mod < 3) {
1518        DECODE_PRINTF("BYTE PTR ");
1519        destoffset = decode_rmXX_address(mod, rl);
1520        destval = fetch_data_byte(destoffset);
1521        imm = fetch_byte_imm();
1522        DECODE_PRINTF2(",%x\n", imm);
1523        TRACE_AND_STEP();
1524        destval = (*genop_byte_operation[rh]) (destval, imm);
1525        if (rh != 7)
1526            store_data_byte(destoffset, destval);
1527    } else {                     /* register to register */
1528        destreg = DECODE_RM_BYTE_REGISTER(rl);
1529        imm = fetch_byte_imm();
1530        DECODE_PRINTF2(",%x\n", imm);
1531        TRACE_AND_STEP();
1532        destval = (*genop_byte_operation[rh]) (*destreg, imm);
1533        if (rh != 7)
1534            *destreg = destval;
1535    }
1536    DECODE_CLEAR_SEGOVR();
1537    END_OF_INSTR();
1538}
1539
1540/****************************************************************************
1541REMARKS:
1542Handles opcode 0x83
1543****************************************************************************/
1544void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1545{
1546    int mod, rl, rh;
1547    uint destoffset;
1548
1549    /*
1550     * Weirdo special case instruction format.  Part of the opcode
1551     * held below in "RH".  Doubly nested case would result, except
1552     * that the decoded instruction Similar to opcode 81, except that
1553     * the immediate byte is sign extended to a word length.
1554     */
1555    START_OF_INSTR();
1556    FETCH_DECODE_MODRM(mod, rh, rl);
1557#ifdef DEBUG
1558    if (DEBUG_DECODE()) {
1559        /* XXX DECODE_PRINTF may be changed to something more
1560           general, so that it is important to leave the strings
1561           in the same format, even though the result is that the
1562           above test is done twice. */
1563       switch (rh) {
1564        case 0:
1565            DECODE_PRINTF("ADD\t");
1566            break;
1567        case 1:
1568            DECODE_PRINTF("OR\t");
1569            break;
1570        case 2:
1571            DECODE_PRINTF("ADC\t");
1572            break;
1573        case 3:
1574            DECODE_PRINTF("SBB\t");
1575            break;
1576        case 4:
1577            DECODE_PRINTF("AND\t");
1578            break;
1579        case 5:
1580            DECODE_PRINTF("SUB\t");
1581            break;
1582        case 6:
1583            DECODE_PRINTF("XOR\t");
1584            break;
1585        case 7:
1586            DECODE_PRINTF("CMP\t");
1587            break;
1588        }
1589    }
1590#endif
1591    /* know operation, decode the mod byte to find the addressing
1592       mode. */
1593    if (mod < 3) {
1594        DECODE_PRINTF("DWORD PTR ");
1595        destoffset = decode_rmXX_address(mod,rl);
1596
1597        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1598            u32 destval,imm;
1599
1600            destval = fetch_data_long(destoffset);
1601            imm = (s8) fetch_byte_imm();
1602            DECODE_PRINTF2(",%x\n", imm);
1603            TRACE_AND_STEP();
1604            destval = (*genop_long_operation[rh]) (destval, imm);
1605            if (rh != 7)
1606                store_data_long(destoffset, destval);
1607        } else {
1608            u16 destval,imm;
1609
1610            destval = fetch_data_word(destoffset);
1611            imm = (s8) fetch_byte_imm();
1612            DECODE_PRINTF2(",%x\n", imm);
1613            TRACE_AND_STEP();
1614            destval = (*genop_word_operation[rh]) (destval, imm);
1615            if (rh != 7)
1616                store_data_word(destoffset, destval);
1617        }
1618    } else {                     /* register to register */
1619        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1620            u32 *destreg;
1621            u32 destval,imm;
1622
1623            destreg = DECODE_RM_LONG_REGISTER(rl);
1624            imm = (s8) fetch_byte_imm();
1625            DECODE_PRINTF2(",%x\n", imm);
1626            TRACE_AND_STEP();
1627            destval = (*genop_long_operation[rh]) (*destreg, imm);
1628            if (rh != 7)
1629                *destreg = destval;
1630        } else {
1631            u16 *destreg;
1632            u16 destval,imm;
1633
1634            destreg = DECODE_RM_WORD_REGISTER(rl);
1635            imm = (s8) fetch_byte_imm();
1636            DECODE_PRINTF2(",%x\n", imm);
1637            TRACE_AND_STEP();
1638            destval = (*genop_word_operation[rh]) (*destreg, imm);
1639            if (rh != 7)
1640                *destreg = destval;
1641        }
1642    }
1643    DECODE_CLEAR_SEGOVR();
1644    END_OF_INSTR();
1645}
1646
1647/****************************************************************************
1648REMARKS:
1649Handles opcode 0x84
1650****************************************************************************/
1651void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1652{
1653    int mod, rl, rh;
1654    u8 *destreg, *srcreg;
1655    uint destoffset;
1656    u8 destval;
1657
1658    START_OF_INSTR();
1659    DECODE_PRINTF("TEST\t");
1660    FETCH_DECODE_MODRM(mod, rh, rl);
1661    if (mod < 3) {
1662        destoffset = decode_rmXX_address(mod, rl);
1663        DECODE_PRINTF(",");
1664        destval = fetch_data_byte(destoffset);
1665        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1666        DECODE_PRINTF("\n");
1667        TRACE_AND_STEP();
1668        test_byte(destval, *srcreg);
1669    } else {                     /* register to register */
1670        destreg = DECODE_RM_BYTE_REGISTER(rl);
1671        DECODE_PRINTF(",");
1672        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1673        DECODE_PRINTF("\n");
1674        TRACE_AND_STEP();
1675        test_byte(*destreg, *srcreg);
1676    }
1677    DECODE_CLEAR_SEGOVR();
1678    END_OF_INSTR();
1679}
1680
1681/****************************************************************************
1682REMARKS:
1683Handles opcode 0x85
1684****************************************************************************/
1685void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1686{
1687    int mod, rl, rh;
1688    uint destoffset;
1689
1690    START_OF_INSTR();
1691    DECODE_PRINTF("TEST\t");
1692    FETCH_DECODE_MODRM(mod, rh, rl);
1693    if (mod < 3) {
1694        destoffset = decode_rmXX_address(mod, rl);
1695        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1696            u32 destval;
1697            u32 *srcreg;
1698
1699            DECODE_PRINTF(",");
1700            destval = fetch_data_long(destoffset);
1701            srcreg = DECODE_RM_LONG_REGISTER(rh);
1702            DECODE_PRINTF("\n");
1703            TRACE_AND_STEP();
1704            test_long(destval, *srcreg);
1705        } else {
1706            u16 destval;
1707            u16 *srcreg;
1708
1709            DECODE_PRINTF(",");
1710            destval = fetch_data_word(destoffset);
1711            srcreg = DECODE_RM_WORD_REGISTER(rh);
1712            DECODE_PRINTF("\n");
1713            TRACE_AND_STEP();
1714            test_word(destval, *srcreg);
1715        }
1716    } else {                     /* register to register */
1717        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1718            u32 *destreg,*srcreg;
1719
1720            destreg = DECODE_RM_LONG_REGISTER(rl);
1721            DECODE_PRINTF(",");
1722            srcreg = DECODE_RM_LONG_REGISTER(rh);
1723            DECODE_PRINTF("\n");
1724            TRACE_AND_STEP();
1725            test_long(*destreg, *srcreg);
1726        } else {
1727            u16 *destreg,*srcreg;
1728
1729            destreg = DECODE_RM_WORD_REGISTER(rl);
1730            DECODE_PRINTF(",");
1731            srcreg = DECODE_RM_WORD_REGISTER(rh);
1732            DECODE_PRINTF("\n");
1733            TRACE_AND_STEP();
1734            test_word(*destreg, *srcreg);
1735        }
1736    }
1737    DECODE_CLEAR_SEGOVR();
1738    END_OF_INSTR();
1739}
1740
1741/****************************************************************************
1742REMARKS:
1743Handles opcode 0x86
1744****************************************************************************/
1745void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1746{
1747    int mod, rl, rh;
1748    u8 *destreg, *srcreg;
1749    uint destoffset;
1750    u8 destval;
1751    u8 tmp;
1752
1753    START_OF_INSTR();
1754    DECODE_PRINTF("XCHG\t");
1755    FETCH_DECODE_MODRM(mod, rh, rl);
1756    if (mod < 3) {
1757        destoffset = decode_rmXX_address(mod, rl);
1758        DECODE_PRINTF(",");
1759        destval = fetch_data_byte(destoffset);
1760        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1761        DECODE_PRINTF("\n");
1762        TRACE_AND_STEP();
1763        tmp = *srcreg;
1764        *srcreg = destval;
1765        destval = tmp;
1766        store_data_byte(destoffset, destval);
1767    } else {                     /* register to register */
1768        destreg = DECODE_RM_BYTE_REGISTER(rl);
1769        DECODE_PRINTF(",");
1770        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1771        DECODE_PRINTF("\n");
1772        TRACE_AND_STEP();
1773        tmp = *srcreg;
1774        *srcreg = *destreg;
1775        *destreg = tmp;
1776    }
1777    DECODE_CLEAR_SEGOVR();
1778    END_OF_INSTR();
1779}
1780
1781/****************************************************************************
1782REMARKS:
1783Handles opcode 0x87
1784****************************************************************************/
1785void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1786{
1787    int mod, rl, rh;
1788    uint destoffset;
1789
1790    START_OF_INSTR();
1791    DECODE_PRINTF("XCHG\t");
1792    FETCH_DECODE_MODRM(mod, rh, rl);
1793    if (mod < 3) {
1794        destoffset = decode_rmXX_address(mod, rl);
1795        DECODE_PRINTF(",");
1796        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1797            u32 *srcreg;
1798            u32 destval,tmp;
1799
1800            destval = fetch_data_long(destoffset);
1801            srcreg = DECODE_RM_LONG_REGISTER(rh);
1802            DECODE_PRINTF("\n");
1803            TRACE_AND_STEP();
1804            tmp = *srcreg;
1805            *srcreg = destval;
1806            destval = tmp;
1807            store_data_long(destoffset, destval);
1808        } else {
1809            u16 *srcreg;
1810            u16 destval,tmp;
1811
1812            destval = fetch_data_word(destoffset);
1813            srcreg = DECODE_RM_WORD_REGISTER(rh);
1814            DECODE_PRINTF("\n");
1815            TRACE_AND_STEP();
1816            tmp = *srcreg;
1817            *srcreg = destval;
1818            destval = tmp;
1819            store_data_word(destoffset, destval);
1820        }
1821    } else {                     /* register to register */
1822        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1823            u32 *destreg,*srcreg;
1824            u32 tmp;
1825
1826            destreg = DECODE_RM_LONG_REGISTER(rl);
1827            DECODE_PRINTF(",");
1828            srcreg = DECODE_RM_LONG_REGISTER(rh);
1829            DECODE_PRINTF("\n");
1830            TRACE_AND_STEP();
1831            tmp = *srcreg;
1832            *srcreg = *destreg;
1833            *destreg = tmp;
1834        } else {
1835            u16 *destreg,*srcreg;
1836            u16 tmp;
1837
1838            destreg = DECODE_RM_WORD_REGISTER(rl);
1839            DECODE_PRINTF(",");
1840            srcreg = DECODE_RM_WORD_REGISTER(rh);
1841            DECODE_PRINTF("\n");
1842            TRACE_AND_STEP();
1843            tmp = *srcreg;
1844            *srcreg = *destreg;
1845            *destreg = tmp;
1846        }
1847    }
1848    DECODE_CLEAR_SEGOVR();
1849    END_OF_INSTR();
1850}
1851
1852/****************************************************************************
1853REMARKS:
1854Handles opcode 0x88
1855****************************************************************************/
1856void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1857{
1858    int mod, rl, rh;
1859    u8 *destreg, *srcreg;
1860    uint destoffset;
1861
1862    START_OF_INSTR();
1863    DECODE_PRINTF("MOV\t");
1864    FETCH_DECODE_MODRM(mod, rh, rl);
1865    if (mod < 3) {
1866        destoffset = decode_rmXX_address(mod, rl);
1867        DECODE_PRINTF(",");
1868        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1869        DECODE_PRINTF("\n");
1870        TRACE_AND_STEP();
1871        store_data_byte(destoffset, *srcreg);
1872    } else {                     /* register to register */
1873        destreg = DECODE_RM_BYTE_REGISTER(rl);
1874        DECODE_PRINTF(",");
1875        srcreg = DECODE_RM_BYTE_REGISTER(rh);
1876        DECODE_PRINTF("\n");
1877        TRACE_AND_STEP();
1878        *destreg = *srcreg;
1879    }
1880    DECODE_CLEAR_SEGOVR();
1881    END_OF_INSTR();
1882}
1883
1884/****************************************************************************
1885REMARKS:
1886Handles opcode 0x89
1887****************************************************************************/
1888void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1889{
1890    int mod, rl, rh;
1891    uint destoffset;
1892
1893    START_OF_INSTR();
1894    DECODE_PRINTF("MOV\t");
1895    FETCH_DECODE_MODRM(mod, rh, rl);
1896    if (mod < 3) {
1897        destoffset = decode_rmXX_address(mod, rl);
1898        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1899            u32 *srcreg;
1900
1901            DECODE_PRINTF(",");
1902            srcreg = DECODE_RM_LONG_REGISTER(rh);
1903            DECODE_PRINTF("\n");
1904            TRACE_AND_STEP();
1905            store_data_long(destoffset, *srcreg);
1906        } else {
1907            u16 *srcreg;
1908
1909            DECODE_PRINTF(",");
1910            srcreg = DECODE_RM_WORD_REGISTER(rh);
1911            DECODE_PRINTF("\n");
1912            TRACE_AND_STEP();
1913            store_data_word(destoffset, *srcreg);
1914        }
1915    } else {                     /* register to register */
1916        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1917            u32 *destreg,*srcreg;
1918
1919            destreg = DECODE_RM_LONG_REGISTER(rl);
1920            DECODE_PRINTF(",");
1921            srcreg = DECODE_RM_LONG_REGISTER(rh);
1922            DECODE_PRINTF("\n");
1923            TRACE_AND_STEP();
1924            *destreg = *srcreg;
1925        } else {
1926            u16 *destreg,*srcreg;
1927
1928            destreg = DECODE_RM_WORD_REGISTER(rl);
1929            DECODE_PRINTF(",");
1930            srcreg = DECODE_RM_WORD_REGISTER(rh);
1931            DECODE_PRINTF("\n");
1932            TRACE_AND_STEP();
1933            *destreg = *srcreg;
1934        }
1935    }
1936    DECODE_CLEAR_SEGOVR();
1937    END_OF_INSTR();
1938}
1939
1940/****************************************************************************
1941REMARKS:
1942Handles opcode 0x8a
1943****************************************************************************/
1944void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1945{
1946    int mod, rl, rh;
1947    u8 *destreg, *srcreg;
1948    uint srcoffset;
1949    u8 srcval;
1950
1951    START_OF_INSTR();
1952    DECODE_PRINTF("MOV\t");
1953    FETCH_DECODE_MODRM(mod, rh, rl);
1954    if (mod < 3) {
1955        destreg = DECODE_RM_BYTE_REGISTER(rh);
1956        DECODE_PRINTF(",");
1957        srcoffset = decode_rmXX_address(mod, rl);
1958        srcval = fetch_data_byte(srcoffset);
1959        DECODE_PRINTF("\n");
1960        TRACE_AND_STEP();
1961        *destreg = srcval;
1962    } else {                     /* register to register */
1963        destreg = DECODE_RM_BYTE_REGISTER(rh);
1964        DECODE_PRINTF(",");
1965        srcreg = DECODE_RM_BYTE_REGISTER(rl);
1966        DECODE_PRINTF("\n");
1967        TRACE_AND_STEP();
1968        *destreg = *srcreg;
1969    }
1970    DECODE_CLEAR_SEGOVR();
1971    END_OF_INSTR();
1972}
1973
1974/****************************************************************************
1975REMARKS:
1976Handles opcode 0x8b
1977****************************************************************************/
1978void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1979{
1980    int mod, rl, rh;
1981    uint srcoffset;
1982
1983    START_OF_INSTR();
1984    DECODE_PRINTF("MOV\t");
1985    FETCH_DECODE_MODRM(mod, rh, rl);
1986    if (mod < 3) {
1987        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1988            u32 *destreg;
1989            u32 srcval;
1990
1991            destreg = DECODE_RM_LONG_REGISTER(rh);
1992            DECODE_PRINTF(",");
1993            srcoffset = decode_rmXX_address(mod, rl);
1994            srcval = fetch_data_long(srcoffset);
1995            DECODE_PRINTF("\n");
1996            TRACE_AND_STEP();
1997            *destreg = srcval;
1998        } else {
1999            u16 *destreg;
2000            u16 srcval;
2001
2002            destreg = DECODE_RM_WORD_REGISTER(rh);
2003            DECODE_PRINTF(",");
2004            srcoffset = decode_rmXX_address(mod, rl);
2005            srcval = fetch_data_word(srcoffset);
2006            DECODE_PRINTF("\n");
2007            TRACE_AND_STEP();
2008            *destreg = srcval;
2009        }
2010    } else {                     /* register to register */
2011        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2012            u32 *destreg, *srcreg;
2013
2014            destreg = DECODE_RM_LONG_REGISTER(rh);
2015            DECODE_PRINTF(",");
2016            srcreg = DECODE_RM_LONG_REGISTER(rl);
2017            DECODE_PRINTF("\n");
2018            TRACE_AND_STEP();
2019            *destreg = *srcreg;
2020        } else {
2021            u16 *destreg, *srcreg;
2022
2023            destreg = DECODE_RM_WORD_REGISTER(rh);
2024            DECODE_PRINTF(",");
2025            srcreg = DECODE_RM_WORD_REGISTER(rl);
2026            DECODE_PRINTF("\n");
2027            TRACE_AND_STEP();
2028            *destreg = *srcreg;
2029        }
2030    }
2031    DECODE_CLEAR_SEGOVR();
2032    END_OF_INSTR();
2033}
2034
2035/****************************************************************************
2036REMARKS:
2037Handles opcode 0x8c
2038****************************************************************************/
2039void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2040{
2041    int mod, rl, rh;
2042    u16 *destreg, *srcreg;
2043    uint destoffset;
2044    u16 destval;
2045
2046    START_OF_INSTR();
2047    DECODE_PRINTF("MOV\t");
2048    FETCH_DECODE_MODRM(mod, rh, rl);
2049    if (mod < 3) {
2050        destoffset = decode_rmXX_address(mod, rl);
2051        DECODE_PRINTF(",");
2052        srcreg = decode_rm_seg_register(rh);
2053        DECODE_PRINTF("\n");
2054        TRACE_AND_STEP();
2055        destval = *srcreg;
2056        store_data_word(destoffset, destval);
2057    } else {                     /* register to register */
2058        destreg = DECODE_RM_WORD_REGISTER(rl);
2059        DECODE_PRINTF(",");
2060        srcreg = decode_rm_seg_register(rh);
2061        DECODE_PRINTF("\n");
2062        TRACE_AND_STEP();
2063        *destreg = *srcreg;
2064    }
2065    DECODE_CLEAR_SEGOVR();
2066    END_OF_INSTR();
2067}
2068
2069/****************************************************************************
2070REMARKS:
2071Handles opcode 0x8d
2072****************************************************************************/
2073void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2074{
2075    int mod, rl, rh;
2076    u16 *srcreg;
2077    uint destoffset;
2078
2079/*
2080 * TODO: Need to handle address size prefix!
2081 *
2082 * lea  eax,[eax+ebx*2] ??
2083 */
2084
2085    START_OF_INSTR();
2086    DECODE_PRINTF("LEA\t");
2087    FETCH_DECODE_MODRM(mod, rh, rl);
2088    if (mod < 3) {
2089        srcreg = DECODE_RM_WORD_REGISTER(rh);
2090        DECODE_PRINTF(",");
2091        destoffset = decode_rmXX_address(mod, rl);
2092        DECODE_PRINTF("\n");
2093        TRACE_AND_STEP();
2094        *srcreg = (u16)destoffset;
2095        }
2096    /* } else { undefined.  Do nothing. } */
2097    DECODE_CLEAR_SEGOVR();
2098    END_OF_INSTR();
2099}
2100
2101/****************************************************************************
2102REMARKS:
2103Handles opcode 0x8e
2104****************************************************************************/
2105void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2106{
2107    int mod, rl, rh;
2108    u16 *destreg, *srcreg;
2109    uint srcoffset;
2110    u16 srcval;
2111
2112    START_OF_INSTR();
2113    DECODE_PRINTF("MOV\t");
2114    FETCH_DECODE_MODRM(mod, rh, rl);
2115    if (mod < 3) {
2116        destreg = decode_rm_seg_register(rh);
2117        DECODE_PRINTF(",");
2118        srcoffset = decode_rmXX_address(mod, rl);
2119        srcval = fetch_data_word(srcoffset);
2120        DECODE_PRINTF("\n");
2121        TRACE_AND_STEP();
2122        *destreg = srcval;
2123    } else {                     /* register to register */
2124        destreg = decode_rm_seg_register(rh);
2125        DECODE_PRINTF(",");
2126        srcreg = DECODE_RM_WORD_REGISTER(rl);
2127        DECODE_PRINTF("\n");
2128        TRACE_AND_STEP();
2129        *destreg = *srcreg;
2130    }
2131    /*
2132     * Clean up, and reset all the R_xSP pointers to the correct
2133     * locations.  This is about 3x too much overhead (doing all the
2134     * segreg ptrs when only one is needed, but this instruction
2135     * *cannot* be that common, and this isn't too much work anyway.
2136     */
2137    DECODE_CLEAR_SEGOVR();
2138    END_OF_INSTR();
2139}
2140
2141/****************************************************************************
2142REMARKS:
2143Handles opcode 0x8f
2144****************************************************************************/
2145void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2146{
2147    int mod, rl, rh;
2148    uint destoffset;
2149
2150    START_OF_INSTR();
2151    DECODE_PRINTF("POP\t");
2152    FETCH_DECODE_MODRM(mod, rh, rl);
2153    if (rh != 0) {
2154        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2155        HALT_SYS();
2156    }
2157    if (mod < 3) {
2158        destoffset = decode_rmXX_address(mod, rl);
2159        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2160            u32 destval;
2161
2162            DECODE_PRINTF("\n");
2163            TRACE_AND_STEP();
2164            destval = pop_long();
2165            store_data_long(destoffset, destval);
2166        } else {
2167            u16 destval;
2168
2169            DECODE_PRINTF("\n");
2170            TRACE_AND_STEP();
2171            destval = pop_word();
2172            store_data_word(destoffset, destval);
2173        }
2174    } else {                    /* register to register */
2175        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2176            u32 *destreg;
2177
2178            destreg = DECODE_RM_LONG_REGISTER(rl);
2179            DECODE_PRINTF("\n");
2180            TRACE_AND_STEP();
2181            *destreg = pop_long();
2182        } else {
2183            u16 *destreg;
2184
2185            destreg = DECODE_RM_WORD_REGISTER(rl);
2186            DECODE_PRINTF("\n");
2187            TRACE_AND_STEP();
2188            *destreg = pop_word();
2189        }
2190    }
2191    DECODE_CLEAR_SEGOVR();
2192    END_OF_INSTR();
2193}
2194
2195/****************************************************************************
2196REMARKS:
2197Handles opcode 0x90
2198****************************************************************************/
2199void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2200{
2201    START_OF_INSTR();
2202    DECODE_PRINTF("NOP\n");
2203    TRACE_AND_STEP();
2204    DECODE_CLEAR_SEGOVR();
2205    END_OF_INSTR();
2206}
2207
2208/****************************************************************************
2209REMARKS:
2210Handles opcode 0x91-0x97
2211****************************************************************************/
2212void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2213{
2214    u32 tmp;
2215
2216    op1 &= 0x7;
2217
2218    START_OF_INSTR();
2219
2220    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2221        u32 *reg32;
2222        DECODE_PRINTF("XCHG\tEAX,");
2223        reg32 = DECODE_RM_LONG_REGISTER(op1);
2224        DECODE_PRINTF("\n");
2225        TRACE_AND_STEP();
2226        tmp = M.x86.R_EAX;
2227        M.x86.R_EAX = *reg32;
2228        *reg32 = tmp;
2229    } else {
2230        u16 *reg16;
2231        DECODE_PRINTF("XCHG\tAX,");
2232        reg16 = DECODE_RM_WORD_REGISTER(op1);
2233        DECODE_PRINTF("\n");
2234        TRACE_AND_STEP();
2235        tmp = M.x86.R_AX;
2236        M.x86.R_EAX = *reg16;
2237        *reg16 = (u16)tmp;
2238    }
2239    DECODE_CLEAR_SEGOVR();
2240    END_OF_INSTR();
2241}
2242
2243/****************************************************************************
2244REMARKS:
2245Handles opcode 0x98
2246****************************************************************************/
2247void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2248{
2249    START_OF_INSTR();
2250    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2251        DECODE_PRINTF("CWDE\n");
2252    } else {
2253        DECODE_PRINTF("CBW\n");
2254    }
2255    TRACE_AND_STEP();
2256    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2257        if (M.x86.R_AX & 0x8000) {
2258            M.x86.R_EAX |= 0xffff0000;
2259        } else {
2260            M.x86.R_EAX &= 0x0000ffff;
2261        }
2262    } else {
2263        if (M.x86.R_AL & 0x80) {
2264            M.x86.R_AH = 0xff;
2265        } else {
2266            M.x86.R_AH = 0x0;
2267        }
2268    }
2269    DECODE_CLEAR_SEGOVR();
2270    END_OF_INSTR();
2271}
2272
2273/****************************************************************************
2274REMARKS:
2275Handles opcode 0x99
2276****************************************************************************/
2277void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2278{
2279    START_OF_INSTR();
2280    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2281        DECODE_PRINTF("CDQ\n");
2282    } else {
2283        DECODE_PRINTF("CWD\n");
2284    }
2285    DECODE_PRINTF("CWD\n");
2286    TRACE_AND_STEP();
2287    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2288        if (M.x86.R_EAX & 0x80000000) {
2289            M.x86.R_EDX = 0xffffffff;
2290        } else {
2291            M.x86.R_EDX = 0x0;
2292        }
2293    } else {
2294        if (M.x86.R_AX & 0x8000) {
2295            M.x86.R_DX = 0xffff;
2296        } else {
2297            M.x86.R_DX = 0x0;
2298        }
2299    }
2300    DECODE_CLEAR_SEGOVR();
2301    END_OF_INSTR();
2302}
2303
2304/****************************************************************************
2305REMARKS:
2306Handles opcode 0x9a
2307****************************************************************************/
2308void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2309{
2310    u16 farseg, faroff;
2311
2312    START_OF_INSTR();
2313        DECODE_PRINTF("CALL\t");
2314        faroff = fetch_word_imm();
2315        farseg = fetch_word_imm();
2316        DECODE_PRINTF2("%04x:", farseg);
2317        DECODE_PRINTF2("%04x\n", faroff);
2318        CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2319
2320    /* XXX
2321     *
2322     * Hooked interrupt vectors calling into our "BIOS" will cause
2323     * problems unless all intersegment stuff is checked for BIOS
2324     * access.  Check needed here.  For moment, let it alone.
2325     */
2326    TRACE_AND_STEP();
2327    push_word(M.x86.R_CS);
2328    M.x86.R_CS = farseg;
2329    push_word(M.x86.R_IP);
2330    M.x86.R_IP = faroff;
2331    DECODE_CLEAR_SEGOVR();
2332    END_OF_INSTR();
2333}
2334
2335/****************************************************************************
2336REMARKS:
2337Handles opcode 0x9b
2338****************************************************************************/
2339void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2340{
2341    START_OF_INSTR();
2342    DECODE_PRINTF("WAIT");
2343    TRACE_AND_STEP();
2344    /* NADA.  */
2345    DECODE_CLEAR_SEGOVR();
2346    END_OF_INSTR();
2347}
2348
2349/****************************************************************************
2350REMARKS:
2351Handles opcode 0x9c
2352****************************************************************************/
2353void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2354{
2355    u32 flags;
2356
2357    START_OF_INSTR();
2358    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2359        DECODE_PRINTF("PUSHFD\n");
2360    } else {
2361        DECODE_PRINTF("PUSHF\n");
2362    }
2363    TRACE_AND_STEP();
2364
2365    /* clear out *all* bits not representing flags, and turn on real bits */
2366    flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2367    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2368        push_long(flags);
2369    } else {
2370        push_word((u16)flags);
2371    }
2372    DECODE_CLEAR_SEGOVR();
2373    END_OF_INSTR();
2374}
2375
2376/****************************************************************************
2377REMARKS:
2378Handles opcode 0x9d
2379****************************************************************************/
2380void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2381{
2382    START_OF_INSTR();
2383    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2384        DECODE_PRINTF("POPFD\n");
2385    } else {
2386        DECODE_PRINTF("POPF\n");
2387    }
2388    TRACE_AND_STEP();
2389    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2390        M.x86.R_EFLG = pop_long();
2391    } else {
2392        M.x86.R_FLG = pop_word();
2393    }
2394    DECODE_CLEAR_SEGOVR();
2395    END_OF_INSTR();
2396}
2397
2398/****************************************************************************
2399REMARKS:
2400Handles opcode 0x9e
2401****************************************************************************/
2402void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2403{
2404    START_OF_INSTR();
2405    DECODE_PRINTF("SAHF\n");
2406    TRACE_AND_STEP();
2407    /* clear the lower bits of the flag register */
2408    M.x86.R_FLG &= 0xffffff00;
2409    /* or in the AH register into the flags register */
2410    M.x86.R_FLG |= M.x86.R_AH;
2411    DECODE_CLEAR_SEGOVR();
2412    END_OF_INSTR();
2413}
2414
2415/****************************************************************************
2416REMARKS:
2417Handles opcode 0x9f
2418****************************************************************************/
2419void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2420{
2421    START_OF_INSTR();
2422    DECODE_PRINTF("LAHF\n");
2423    TRACE_AND_STEP();
2424        M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2425    /*undocumented TC++ behavior??? Nope.  It's documented, but
2426       you have too look real hard to notice it. */
2427    M.x86.R_AH |= 0x2;
2428    DECODE_CLEAR_SEGOVR();
2429    END_OF_INSTR();
2430}
2431
2432/****************************************************************************
2433REMARKS:
2434Handles opcode 0xa0
2435****************************************************************************/
2436void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2437{
2438    u16 offset;
2439
2440    START_OF_INSTR();
2441    DECODE_PRINTF("MOV\tAL,");
2442    offset = fetch_word_imm();
2443    DECODE_PRINTF2("[%04x]\n", offset);
2444    TRACE_AND_STEP();
2445    M.x86.R_AL = fetch_data_byte(offset);
2446    DECODE_CLEAR_SEGOVR();
2447    END_OF_INSTR();
2448}
2449
2450/****************************************************************************
2451REMARKS:
2452Handles opcode 0xa1
2453****************************************************************************/
2454void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2455{
2456    u16 offset;
2457
2458    START_OF_INSTR();
2459    offset = fetch_word_imm();
2460    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2461        DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2462    } else {
2463        DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2464    }
2465    TRACE_AND_STEP();
2466    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2467        M.x86.R_EAX = fetch_data_long(offset);
2468    } else {
2469        M.x86.R_AX = fetch_data_word(offset);
2470    }
2471    DECODE_CLEAR_SEGOVR();
2472    END_OF_INSTR();
2473}
2474
2475/****************************************************************************
2476REMARKS:
2477Handles opcode 0xa2
2478****************************************************************************/
2479void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2480{
2481    u16 offset;
2482
2483    START_OF_INSTR();
2484    DECODE_PRINTF("MOV\t");
2485    offset = fetch_word_imm();
2486    DECODE_PRINTF2("[%04x],AL\n", offset);
2487    TRACE_AND_STEP();
2488    store_data_byte(offset, M.x86.R_AL);
2489    DECODE_CLEAR_SEGOVR();
2490    END_OF_INSTR();
2491}
2492
2493/****************************************************************************
2494REMARKS:
2495Handles opcode 0xa3
2496****************************************************************************/
2497void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2498{
2499    u16 offset;
2500
2501    START_OF_INSTR();
2502    offset = fetch_word_imm();
2503    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2504        DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2505    } else {
2506        DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2507    }
2508    TRACE_AND_STEP();
2509    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2510        store_data_long(offset, M.x86.R_EAX);
2511    } else {
2512        store_data_word(offset, M.x86.R_AX);
2513    }
2514    DECODE_CLEAR_SEGOVR();
2515    END_OF_INSTR();
2516}
2517
2518/****************************************************************************
2519REMARKS:
2520Handles opcode 0xa4
2521****************************************************************************/
2522void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2523{
2524    u8  val;
2525    u32 count;
2526    int inc;
2527
2528    START_OF_INSTR();
2529    DECODE_PRINTF("MOVS\tBYTE\n");
2530    if (ACCESS_FLAG(F_DF))   /* down */
2531        inc = -1;
2532    else
2533        inc = 1;
2534    TRACE_AND_STEP();
2535    count = 1;
2536    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2537        /* dont care whether REPE or REPNE */
2538        /* move them until CX is ZERO. */
2539        count = M.x86.R_CX;
2540        M.x86.R_CX = 0;
2541        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2542    }
2543    while (count--) {
2544        val = fetch_data_byte(M.x86.R_SI);
2545        store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2546        M.x86.R_SI += inc;
2547        M.x86.R_DI += inc;
2548    }
2549    DECODE_CLEAR_SEGOVR();
2550    END_OF_INSTR();
2551}
2552
2553/****************************************************************************
2554REMARKS:
2555Handles opcode 0xa5
2556****************************************************************************/
2557void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2558{
2559    u32 val;
2560    int inc;
2561    u32 count;
2562
2563    START_OF_INSTR();
2564    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2565        DECODE_PRINTF("MOVS\tDWORD\n");
2566        if (ACCESS_FLAG(F_DF))      /* down */
2567            inc = -4;
2568        else
2569            inc = 4;
2570    } else {
2571        DECODE_PRINTF("MOVS\tWORD\n");
2572        if (ACCESS_FLAG(F_DF))      /* down */
2573            inc = -2;
2574        else
2575            inc = 2;
2576    }
2577    TRACE_AND_STEP();
2578    count = 1;
2579    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2580        /* dont care whether REPE or REPNE */
2581        /* move them until CX is ZERO. */
2582        count = M.x86.R_CX;
2583        M.x86.R_CX = 0;
2584        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2585    }
2586    while (count--) {
2587        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2588            val = fetch_data_long(M.x86.R_SI);
2589            store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2590        } else {
2591            val = fetch_data_word(M.x86.R_SI);
2592            store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2593        }
2594        M.x86.R_SI += inc;
2595        M.x86.R_DI += inc;
2596    }
2597    DECODE_CLEAR_SEGOVR();
2598    END_OF_INSTR();
2599}
2600
2601/****************************************************************************
2602REMARKS:
2603Handles opcode 0xa6
2604****************************************************************************/
2605void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2606{
2607    s8 val1, val2;
2608    int inc;
2609
2610    START_OF_INSTR();
2611    DECODE_PRINTF("CMPS\tBYTE\n");
2612    TRACE_AND_STEP();
2613    if (ACCESS_FLAG(F_DF))   /* down */
2614        inc = -1;
2615    else
2616        inc = 1;
2617
2618    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2619        /* REPE  */
2620        /* move them until CX is ZERO. */
2621        while (M.x86.R_CX != 0) {
2622            val1 = fetch_data_byte(M.x86.R_SI);
2623            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2624                     cmp_byte(val1, val2);
2625            M.x86.R_CX -= 1;
2626            M.x86.R_SI += inc;
2627            M.x86.R_DI += inc;
2628            if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2629            if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2630        }
2631        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2632    } else {
2633        val1 = fetch_data_byte(M.x86.R_SI);
2634        val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2635        cmp_byte(val1, val2);
2636        M.x86.R_SI += inc;
2637        M.x86.R_DI += inc;
2638    }
2639    DECODE_CLEAR_SEGOVR();
2640    END_OF_INSTR();
2641}
2642
2643/****************************************************************************
2644REMARKS:
2645Handles opcode 0xa7
2646****************************************************************************/
2647void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2648{
2649    u32 val1,val2;
2650    int inc;
2651
2652    START_OF_INSTR();
2653    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2654        DECODE_PRINTF("CMPS\tDWORD\n");
2655        inc = 4;
2656    } else {
2657        DECODE_PRINTF("CMPS\tWORD\n");
2658        inc = 2;
2659    }
2660    if (ACCESS_FLAG(F_DF))   /* down */
2661        inc = -inc;
2662
2663    TRACE_AND_STEP();
2664    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2665        /* REPE  */
2666        /* move them until CX is ZERO. */
2667        while (M.x86.R_CX != 0) {
2668            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2669                val1 = fetch_data_long(M.x86.R_SI);
2670                val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2671                cmp_long(val1, val2);
2672            } else {
2673                val1 = fetch_data_word(M.x86.R_SI);
2674                val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2675                cmp_word((u16)val1, (u16)val2);
2676            }
2677            M.x86.R_CX -= 1;
2678            M.x86.R_SI += inc;
2679            M.x86.R_DI += inc;
2680            if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2681            if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2682        }
2683        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2684    } else {
2685        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2686            val1 = fetch_data_long(M.x86.R_SI);
2687            val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2688            cmp_long(val1, val2);
2689        } else {
2690            val1 = fetch_data_word(M.x86.R_SI);
2691            val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2692            cmp_word((u16)val1, (u16)val2);
2693        }
2694        M.x86.R_SI += inc;
2695        M.x86.R_DI += inc;
2696    }
2697    DECODE_CLEAR_SEGOVR();
2698    END_OF_INSTR();
2699}
2700
2701/****************************************************************************
2702REMARKS:
2703Handles opcode 0xa8
2704****************************************************************************/
2705void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2706{
2707    int imm;
2708
2709    START_OF_INSTR();
2710    DECODE_PRINTF("TEST\tAL,");
2711    imm = fetch_byte_imm();
2712    DECODE_PRINTF2("%04x\n", imm);
2713    TRACE_AND_STEP();
2714        test_byte(M.x86.R_AL, (u8)imm);
2715    DECODE_CLEAR_SEGOVR();
2716    END_OF_INSTR();
2717}
2718
2719/****************************************************************************
2720REMARKS:
2721Handles opcode 0xa9
2722****************************************************************************/
2723void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2724{
2725    u32 srcval;
2726
2727    START_OF_INSTR();
2728    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2729        DECODE_PRINTF("TEST\tEAX,");
2730        srcval = fetch_long_imm();
2731    } else {
2732        DECODE_PRINTF("TEST\tAX,");
2733        srcval = fetch_word_imm();
2734    }
2735    DECODE_PRINTF2("%x\n", srcval);
2736    TRACE_AND_STEP();
2737    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2738        test_long(M.x86.R_EAX, srcval);
2739    } else {
2740        test_word(M.x86.R_AX, (u16)srcval);
2741    }
2742    DECODE_CLEAR_SEGOVR();
2743    END_OF_INSTR();
2744}
2745
2746/****************************************************************************
2747REMARKS:
2748Handles opcode 0xaa
2749****************************************************************************/
2750void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2751{
2752    int inc;
2753
2754    START_OF_INSTR();
2755    DECODE_PRINTF("STOS\tBYTE\n");
2756    if (ACCESS_FLAG(F_DF))   /* down */
2757        inc = -1;
2758    else
2759        inc = 1;
2760    TRACE_AND_STEP();
2761    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2762        /* dont care whether REPE or REPNE */
2763        /* move them until CX is ZERO. */
2764        while (M.x86.R_CX != 0) {
2765            store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2766            M.x86.R_CX -= 1;
2767            M.x86.R_DI += inc;
2768        }
2769        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2770    } else {
2771        store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2772        M.x86.R_DI += inc;
2773    }
2774    DECODE_CLEAR_SEGOVR();
2775    END_OF_INSTR();
2776}
2777
2778/****************************************************************************
2779REMARKS:
2780Handles opcode 0xab
2781****************************************************************************/
2782void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2783{
2784    int inc;
2785    u32 count;
2786
2787    START_OF_INSTR();
2788    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2789        DECODE_PRINTF("STOS\tDWORD\n");
2790        if (ACCESS_FLAG(F_DF))   /* down */
2791            inc = -4;
2792        else
2793            inc = 4;
2794    } else {
2795        DECODE_PRINTF("STOS\tWORD\n");
2796        if (ACCESS_FLAG(F_DF))   /* down */
2797            inc = -2;
2798        else
2799            inc = 2;
2800    }
2801    TRACE_AND_STEP();
2802    count = 1;
2803    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2804        /* dont care whether REPE or REPNE */
2805        /* move them until CX is ZERO. */
2806        count = M.x86.R_CX;
2807        M.x86.R_CX = 0;
2808        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2809    }
2810    while (count--) {
2811        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2812            store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2813        } else {
2814            store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2815        }
2816        M.x86.R_DI += inc;
2817    }
2818    DECODE_CLEAR_SEGOVR();
2819    END_OF_INSTR();
2820}
2821
2822/****************************************************************************
2823REMARKS:
2824Handles opcode 0xac
2825****************************************************************************/
2826void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2827{
2828    int inc;
2829
2830    START_OF_INSTR();
2831    DECODE_PRINTF("LODS\tBYTE\n");
2832    TRACE_AND_STEP();
2833    if (ACCESS_FLAG(F_DF))   /* down */
2834        inc = -1;
2835    else
2836        inc = 1;
2837    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2838        /* dont care whether REPE or REPNE */
2839        /* move them until CX is ZERO. */
2840        while (M.x86.R_CX != 0) {
2841            M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2842            M.x86.R_CX -= 1;
2843            M.x86.R_SI += inc;
2844        }
2845        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2846    } else {
2847        M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2848        M.x86.R_SI += inc;
2849    }
2850    DECODE_CLEAR_SEGOVR();
2851    END_OF_INSTR();
2852}
2853
2854/****************************************************************************
2855REMARKS:
2856Handles opcode 0xad
2857****************************************************************************/
2858void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2859{
2860    int inc;
2861    u32 count;
2862
2863    START_OF_INSTR();
2864    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2865        DECODE_PRINTF("LODS\tDWORD\n");
2866        if (ACCESS_FLAG(F_DF))   /* down */
2867            inc = -4;
2868        else
2869            inc = 4;
2870    } else {
2871        DECODE_PRINTF("LODS\tWORD\n");
2872        if (ACCESS_FLAG(F_DF))   /* down */
2873            inc = -2;
2874        else
2875            inc = 2;
2876    }
2877    TRACE_AND_STEP();
2878    count = 1;
2879    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2880        /* dont care whether REPE or REPNE */
2881        /* move them until CX is ZERO. */
2882        count = M.x86.R_CX;
2883        M.x86.R_CX = 0;
2884        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2885    }
2886    while (count--) {
2887        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2888            M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2889        } else {
2890            M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2891        }
2892        M.x86.R_SI += inc;
2893    }
2894    DECODE_CLEAR_SEGOVR();
2895    END_OF_INSTR();
2896}
2897
2898/****************************************************************************
2899REMARKS:
2900Handles opcode 0xae
2901****************************************************************************/
2902void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2903{
2904    s8 val2;
2905    int inc;
2906
2907    START_OF_INSTR();
2908    DECODE_PRINTF("SCAS\tBYTE\n");
2909    TRACE_AND_STEP();
2910    if (ACCESS_FLAG(F_DF))   /* down */
2911        inc = -1;
2912    else
2913        inc = 1;
2914    if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2915        /* REPE  */
2916        /* move them until CX is ZERO. */
2917        while (M.x86.R_CX != 0) {
2918            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2919            cmp_byte(M.x86.R_AL, val2);
2920            M.x86.R_CX -= 1;
2921            M.x86.R_DI += inc;
2922            if (ACCESS_FLAG(F_ZF) == 0)
2923                break;
2924        }
2925        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2926    } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2927        /* REPNE  */
2928        /* move them until CX is ZERO. */
2929        while (M.x86.R_CX != 0) {
2930            val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2931            cmp_byte(M.x86.R_AL, val2);
2932            M.x86.R_CX -= 1;
2933            M.x86.R_DI += inc;
2934            if (ACCESS_FLAG(F_ZF))
2935                break;          /* zero flag set means equal */
2936        }
2937        M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2938    } else {
2939        val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2940        cmp_byte(M.x86.R_AL, val2);
2941        M.x86.R_DI += inc;
2942    }
2943    DECODE_CLEAR_SEGOVR();
2944    END_OF_INSTR();
2945}
2946
2947/****************************************************************************
2948REMARKS:
2949Handles opcode 0xaf
2950****************************************************************************/
2951void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2952{
2953    int inc;
2954    u32 val;
2955
2956    START_OF_INSTR();
2957    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2958        DECODE_PRINTF("SCAS\tDWORD\n");
2959        if (ACCESS_FLAG(F_DF))   /* down */
2960            inc = -4;
2961        else
2962            inc = 4;
2963    } else {
2964        DECODE_PRINTF("SCAS\tWORD\n");
2965        if (ACCESS_FLAG(F_DF))   /* down */
2966            inc = -2;
2967        else
2968            inc = 2;
2969    }
2970    TRACE_AND_STEP();
2971    if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2972        /* REPE  */
2973        /* move them until CX is ZERO. */
2974        while (M.x86.R_CX != 0) {
2975            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2976                val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2977                cmp_long(M.x86.R_EAX, val);
2978            } else {
2979                val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2980                cmp_word(M.x86.R_AX, (u16)val);
2981            }
2982            M.x86.R_CX -= 1;
2983            M.x86.R_DI += inc;
2984            if (ACCESS_FLAG(F_ZF) == 0)
2985                break;
2986        }
2987        M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2988    } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2989        /* REPNE  */
2990        /* move them until CX is ZERO. */
2991        while (M.x86.R_CX != 0) {
2992            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2993                val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2994                cmp_long(M.x86.R_EAX, val);
2995            } else {
2996                val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2997                cmp_word(M.x86.R_AX, (u16)val);
2998            }
2999            M.x86.R_CX -= 1;
3000            M.x86.R_DI += inc;
3001            if (ACCESS_FLAG(F_ZF))
3002                break;          /* zero flag set means equal */
3003        }
3004        M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3005    } else {
3006        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3007            val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3008            cmp_long(M.x86.R_EAX, val);
3009        } else {
3010            val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3011            cmp_word(M.x86.R_AX, (u16)val);
3012        }
3013        M.x86.R_DI += inc;
3014    }
3015    DECODE_CLEAR_SEGOVR();
3016    END_OF_INSTR();
3017}
3018
3019/****************************************************************************
3020REMARKS:
3021Handles opcode 0xb0 - 0xb7
3022****************************************************************************/
3023void x86emuOp_mov_byte_register_IMM(u8 op1)
3024{
3025    u8 imm, *ptr;
3026
3027    START_OF_INSTR();
3028    DECODE_PRINTF("MOV\t");
3029    ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3030    DECODE_PRINTF(",");
3031    imm = fetch_byte_imm();
3032    DECODE_PRINTF2("%x\n", imm);
3033    TRACE_AND_STEP();
3034    *ptr = imm;
3035    DECODE_CLEAR_SEGOVR();
3036    END_OF_INSTR();
3037}
3038
3039/****************************************************************************
3040REMARKS:
3041Handles opcode 0xb8 - 0xbf
3042****************************************************************************/
3043void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3044{
3045    u32 srcval;
3046
3047    op1 &= 0x7;
3048
3049    START_OF_INSTR();
3050    DECODE_PRINTF("MOV\t");
3051    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3052        u32 *reg32;
3053        reg32 = DECODE_RM_LONG_REGISTER(op1);
3054        srcval = fetch_long_imm();
3055        DECODE_PRINTF2(",%x\n", srcval);
3056        TRACE_AND_STEP();
3057        *reg32 = srcval;
3058    } else {
3059        u16 *reg16;
3060        reg16 = DECODE_RM_WORD_REGISTER(op1);
3061        srcval = fetch_word_imm();
3062        DECODE_PRINTF2(",%x\n", srcval);
3063        TRACE_AND_STEP();
3064        *reg16 = (u16)srcval;
3065    }
3066    DECODE_CLEAR_SEGOVR();
3067    END_OF_INSTR();
3068}
3069
3070/****************************************************************************
3071REMARKS:
3072Handles opcode 0xc0
3073****************************************************************************/
3074void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3075{
3076    int mod, rl, rh;
3077    u8 *destreg;
3078    uint destoffset;
3079    u8 destval;
3080    u8 amt;
3081
3082    /*
3083     * Yet another weirdo special case instruction format.  Part of
3084     * the opcode held below in "RH".  Doubly nested case would
3085     * result, except that the decoded instruction
3086     */
3087    START_OF_INSTR();
3088    FETCH_DECODE_MODRM(mod, rh, rl);
3089#ifdef DEBUG
3090    if (DEBUG_DECODE()) {
3091        /* XXX DECODE_PRINTF may be changed to something more
3092           general, so that it is important to leave the strings
3093           in the same format, even though the result is that the
3094           above test is done twice. */
3095
3096        switch (rh) {
3097        case 0:
3098            DECODE_PRINTF("ROL\t");
3099            break;
3100        case 1:
3101            DECODE_PRINTF("ROR\t");
3102            break;
3103        case 2:
3104            DECODE_PRINTF("RCL\t");
3105            break;
3106        case 3:
3107            DECODE_PRINTF("RCR\t");
3108            break;
3109        case 4:
3110            DECODE_PRINTF("SHL\t");
3111            break;
3112        case 5:
3113            DECODE_PRINTF("SHR\t");
3114            break;
3115        case 6:
3116            DECODE_PRINTF("SAL\t");
3117            break;
3118        case 7:
3119            DECODE_PRINTF("SAR\t");
3120            break;
3121        }
3122    }
3123#endif
3124    /* know operation, decode the mod byte to find the addressing
3125       mode. */
3126    if (mod < 3) {
3127        DECODE_PRINTF("BYTE PTR ");
3128        destoffset = decode_rmXX_address(mod, rl);
3129        amt = fetch_byte_imm();
3130        DECODE_PRINTF2(",%x\n", amt);
3131        destval = fetch_data_byte(destoffset);
3132        TRACE_AND_STEP();
3133        destval = (*opcD0_byte_operation[rh]) (destval, amt);
3134        store_data_byte(destoffset, destval);
3135    } else {                     /* register to register */
3136        destreg = DECODE_RM_BYTE_REGISTER(rl);
3137        amt = fetch_byte_imm();
3138        DECODE_PRINTF2(",%x\n", amt);
3139        TRACE_AND_STEP();
3140        destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3141        *destreg = destval;
3142    }
3143    DECODE_CLEAR_SEGOVR();
3144    END_OF_INSTR();
3145}
3146
3147/****************************************************************************
3148REMARKS:
3149Handles opcode 0xc1
3150****************************************************************************/
3151void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3152{
3153    int mod, rl, rh;
3154    uint destoffset;
3155    u8 amt;
3156
3157    /*
3158     * Yet another weirdo special case instruction format.  Part of
3159     * the opcode held below in "RH".  Doubly nested case would
3160     * result, except that the decoded instruction
3161     */
3162    START_OF_INSTR();
3163    FETCH_DECODE_MODRM(mod, rh, rl);
3164#ifdef DEBUG
3165    if (DEBUG_DECODE()) {
3166        /* XXX DECODE_PRINTF may be changed to something more
3167           general, so that it is important to leave the strings
3168           in the same format, even though the result is that the
3169           above test is done twice. */
3170
3171        switch (rh) {
3172        case 0:
3173            DECODE_PRINTF("ROL\t");
3174            break;
3175        case 1:
3176            DECODE_PRINTF("ROR\t");
3177            break;
3178        case 2:
3179            DECODE_PRINTF("RCL\t");
3180            break;
3181        case 3:
3182            DECODE_PRINTF("RCR\t");
3183            break;
3184        case 4:
3185            DECODE_PRINTF("SHL\t");
3186            break;
3187        case 5:
3188            DECODE_PRINTF("SHR\t");
3189            break;
3190        case 6:
3191            DECODE_PRINTF("SAL\t");
3192            break;
3193        case 7:
3194            DECODE_PRINTF("SAR\t");
3195            break;
3196        }
3197    }
3198#endif
3199    /* know operation, decode the mod byte to find the addressing
3200       mode. */
3201    if (mod < 3) {
3202        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3203            u32 destval;
3204
3205            DECODE_PRINTF("DWORD PTR ");
3206            destoffset = decode_rmXX_address(mod, rl);
3207            amt = fetch_byte_imm();
3208            DECODE_PRINTF2(",%x\n", amt);
3209            destval = fetch_data_long(destoffset);
3210            TRACE_AND_STEP();
3211            destval = (*opcD1_long_operation[rh]) (destval, amt);
3212            store_data_long(destoffset, destval);
3213        } else {
3214            u16 destval;
3215
3216            DECODE_PRINTF("WORD PTR ");
3217            destoffset = decode_rmXX_address(mod, rl);
3218            amt = fetch_byte_imm();
3219            DECODE_PRINTF2(",%x\n", amt);
3220            destval = fetch_data_word(destoffset);
3221            TRACE_AND_STEP();
3222            destval = (*opcD1_word_operation[rh]) (destval, amt);
3223            store_data_word(destoffset, destval);
3224        }
3225    } else {                     /* register to register */
3226        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3227            u32 *destreg;
3228
3229            destreg = DECODE_RM_LONG_REGISTER(rl);
3230            amt = fetch_byte_imm();
3231            DECODE_PRINTF2(",%x\n", amt);
3232            TRACE_AND_STEP();
3233            *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3234        } else {
3235            u16 *destreg;
3236
3237            destreg = DECODE_RM_WORD_REGISTER(rl);
3238            amt = fetch_byte_imm();
3239            DECODE_PRINTF2(",%x\n", amt);
3240            TRACE_AND_STEP();
3241            *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3242        }
3243    }
3244    DECODE_CLEAR_SEGOVR();
3245    END_OF_INSTR();
3246}
3247
3248/****************************************************************************
3249REMARKS:
3250Handles opcode 0xc2
3251****************************************************************************/
3252void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3253{
3254    u16 imm;
3255
3256    START_OF_INSTR();
3257    DECODE_PRINTF("RET\t");
3258    imm = fetch_word_imm();
3259    DECODE_PRINTF2("%x\n", imm);
3260        RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3261        TRACE_AND_STEP();
3262    M.x86.R_IP = pop_word();
3263    M.x86.R_SP += imm;
3264    DECODE_CLEAR_SEGOVR();
3265    END_OF_INSTR();
3266}
3267
3268/****************************************************************************
3269REMARKS:
3270Handles opcode 0xc3
3271****************************************************************************/
3272void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3273{
3274    START_OF_INSTR();
3275    DECODE_PRINTF("RET\n");
3276        RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3277        TRACE_AND_STEP();
3278    M.x86.R_IP = pop_word();
3279    DECODE_CLEAR_SEGOVR();
3280    END_OF_INSTR();
3281}
3282
3283/****************************************************************************
3284REMARKS:
3285Handles opcode 0xc4
3286****************************************************************************/
3287void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3288{
3289    int mod, rh, rl;
3290    u16 *dstreg;
3291    uint srcoffset;
3292
3293    START_OF_INSTR();
3294    DECODE_PRINTF("LES\t");
3295    FETCH_DECODE_MODRM(mod, rh, rl);
3296    if (mod < 3) {
3297        dstreg = DECODE_RM_WORD_REGISTER(rh);
3298        DECODE_PRINTF(",");
3299        srcoffset = decode_rmXX_address(mod, rl);
3300        DECODE_PRINTF("\n");
3301        TRACE_AND_STEP();
3302        *dstreg = fetch_data_word(srcoffset);
3303        M.x86.R_ES = fetch_data_word(srcoffset + 2);
3304    }
3305    /* else UNDEFINED!                   register to register */
3306
3307    DECODE_CLEAR_SEGOVR();
3308    END_OF_INSTR();
3309}
3310
3311/****************************************************************************
3312REMARKS:
3313Handles opcode 0xc5
3314****************************************************************************/
3315void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3316{
3317    int mod, rh, rl;
3318    u16 *dstreg;
3319    uint srcoffset;
3320
3321    START_OF_INSTR();
3322    DECODE_PRINTF("LDS\t");
3323    FETCH_DECODE_MODRM(mod, rh, rl);
3324    if (mod < 3) {
3325        dstreg = DECODE_RM_WORD_REGISTER(rh);
3326        DECODE_PRINTF(",");
3327        srcoffset = decode_rmXX_address(mod, rl);
3328        DECODE_PRINTF("\n");
3329        TRACE_AND_STEP();
3330        *dstreg = fetch_data_word(srcoffset);
3331        M.x86.R_DS = fetch_data_word(srcoffset + 2);
3332    }
3333    /* else UNDEFINED! */
3334    DECODE_CLEAR_SEGOVR();
3335    END_OF_INSTR();
3336}
3337
3338/****************************************************************************
3339REMARKS:
3340Handles opcode 0xc6
3341****************************************************************************/
3342void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3343{
3344    int mod, rl, rh;
3345    u8 *destreg;
3346    uint destoffset;
3347    u8 imm;
3348
3349    START_OF_INSTR();
3350    DECODE_PRINTF("MOV\t");
3351    FETCH_DECODE_MODRM(mod, rh, rl);
3352    if (rh != 0) {
3353        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3354        HALT_SYS();
3355    }
3356    if (mod < 3) {
3357        DECODE_PRINTF("BYTE PTR ");
3358        destoffset = decode_rmXX_address(mod, rl);
3359        imm = fetch_byte_imm();
3360        DECODE_PRINTF2(",%2x\n", imm);
3361        TRACE_AND_STEP();
3362        store_data_byte(destoffset, imm);
3363    } else {                     /* register to register */
3364        destreg = DECODE_RM_BYTE_REGISTER(rl);
3365        imm = fetch_byte_imm();
3366        DECODE_PRINTF2(",%2x\n", imm);
3367        TRACE_AND_STEP();
3368        *destreg = imm;
3369    }
3370    DECODE_CLEAR_SEGOVR();
3371    END_OF_INSTR();
3372}
3373
3374/****************************************************************************
3375REMARKS:
3376Handles opcode 0xc7
3377****************************************************************************/
3378void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3379{
3380    int mod, rl, rh;
3381    uint destoffset;
3382
3383    START_OF_INSTR();
3384    DECODE_PRINTF("MOV\t");
3385    FETCH_DECODE_MODRM(mod, rh, rl);
3386    if (rh != 0) {
3387        DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3388        HALT_SYS();
3389    }
3390    if (mod < 3) {
3391        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3392            u32 imm;
3393
3394            DECODE_PRINTF("DWORD PTR ");
3395            destoffset = decode_rmXX_address(mod, rl);
3396            imm = fetch_long_imm();
3397            DECODE_PRINTF2(",%x\n", imm);
3398            TRACE_AND_STEP();
3399            store_data_long(destoffset, imm);
3400        } else {
3401            u16 imm;
3402
3403            DECODE_PRINTF("WORD PTR ");
3404            destoffset = decode_rmXX_address(mod, rl);
3405            imm = fetch_word_imm();
3406            DECODE_PRINTF2(",%x\n", imm);
3407            TRACE_AND_STEP();
3408            store_data_word(destoffset, imm);
3409        }
3410    } else {                     /* register to register */
3411        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3412                        u32 *destreg;
3413                        u32 imm;
3414
3415            destreg = DECODE_RM_LONG_REGISTER(rl);
3416            imm = fetch_long_imm();
3417            DECODE_PRINTF2(",%x\n", imm);
3418            TRACE_AND_STEP();
3419            *destreg = imm;
3420        } else {
3421                        u16 *destreg;
3422                        u16 imm;
3423
3424            destreg = DECODE_RM_WORD_REGISTER(rl);
3425            imm = fetch_word_imm();
3426            DECODE_PRINTF2(",%x\n", imm);
3427            TRACE_AND_STEP();
3428            *destreg = imm;
3429        }
3430    }
3431    DECODE_CLEAR_SEGOVR();
3432    END_OF_INSTR();
3433}
3434
3435/****************************************************************************
3436REMARKS:
3437Handles opcode 0xc8
3438****************************************************************************/
3439void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3440{
3441    u16 local,frame_pointer;
3442    u8  nesting;
3443    int i;
3444
3445    START_OF_INSTR();
3446    local = fetch_word_imm();
3447    nesting = fetch_byte_imm();
3448    DECODE_PRINTF2("ENTER %x\n", local);
3449    DECODE_PRINTF2(",%x\n", nesting);
3450    TRACE_AND_STEP();
3451    push_word(M.x86.R_BP);
3452    frame_pointer = M.x86.R_SP;
3453    if (nesting > 0) {
3454        for (i = 1; i < nesting; i++) {
3455            M.x86.R_BP -= 2;
3456            push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3457            }
3458        push_word(frame_pointer);
3459        }
3460    M.x86.R_BP = frame_pointer;
3461    M.x86.R_SP = (u16)(M.x86.R_SP - local);
3462    DECODE_CLEAR_SEGOVR();
3463    END_OF_INSTR();
3464}
3465
3466/****************************************************************************
3467REMARKS:
3468Handles opcode 0xc9
3469****************************************************************************/
3470void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3471{
3472    START_OF_INSTR();
3473    DECODE_PRINTF("LEAVE\n");
3474    TRACE_AND_STEP();
3475    M.x86.R_SP = M.x86.R_BP;
3476    M.x86.R_BP = pop_word();
3477    DECODE_CLEAR_SEGOVR();
3478    END_OF_INSTR();
3479}
3480
3481/****************************************************************************
3482REMARKS:
3483Handles opcode 0xca
3484****************************************************************************/
3485void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3486{
3487    u16 imm;
3488
3489    START_OF_INSTR();
3490    DECODE_PRINTF("RETF\t");
3491    imm = fetch_word_imm();
3492    DECODE_PRINTF2("%x\n", imm);
3493        RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3494        TRACE_AND_STEP();
3495    M.x86.R_IP = pop_word();
3496    M.x86.R_CS = pop_word();
3497    M.x86.R_SP += imm;
3498    DECODE_CLEAR_SEGOVR();
3499    END_OF_INSTR();
3500}
3501
3502/****************************************************************************
3503REMARKS:
3504Handles opcode 0xcb
3505****************************************************************************/
3506void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3507{
3508    START_OF_INSTR();
3509    DECODE_PRINTF("RETF\n");
3510        RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3511        TRACE_AND_STEP();
3512    M.x86.R_IP = pop_word();
3513    M.x86.R_CS = pop_word();
3514    DECODE_CLEAR_SEGOVR();
3515    END_OF_INSTR();
3516}
3517
3518/****************************************************************************
3519REMARKS:
3520Handles opcode 0xcc
3521****************************************************************************/
3522void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3523{
3524    u16 tmp;
3525
3526    START_OF_INSTR();
3527    DECODE_PRINTF("INT 3\n");
3528    tmp = (u16) mem_access_word(3 * 4 + 2);
3529    /* access the segment register */
3530    TRACE_AND_STEP();
3531        if (_X86EMU_intrTab[3]) {
3532                (*_X86EMU_intrTab[3])(3);
3533    } else {
3534        push_word((u16)M.x86.R_FLG);
3535        CLEAR_FLAG(F_IF);
3536        CLEAR_FLAG(F_TF);
3537        push_word(M.x86.R_CS);
3538        M.x86.R_CS = mem_access_word(3 * 4 + 2);
3539        push_word(M.x86.R_IP);
3540        M.x86.R_IP = mem_access_word(3 * 4);
3541    }
3542    DECODE_CLEAR_SEGOVR();
3543    END_OF_INSTR();
3544}
3545
3546/****************************************************************************
3547REMARKS:
3548Handles opcode 0xcd
3549****************************************************************************/
3550void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3551{
3552    u16 tmp;
3553    u8 intnum;
3554
3555    START_OF_INSTR();
3556    DECODE_PRINTF("INT\t");
3557    intnum = fetch_byte_imm();
3558    DECODE_PRINTF2("%x\n", intnum);
3559    tmp = mem_access_word(intnum * 4 + 2);
3560    TRACE_AND_STEP();
3561        if (_X86EMU_intrTab[intnum]) {
3562                (*_X86EMU_intrTab[intnum])(intnum);
3563    } else {
3564        push_word((u16)M.x86.R_FLG);
3565        CLEAR_FLAG(F_IF);
3566        CLEAR_FLAG(F_TF);
3567        push_word(M.x86.R_CS);
3568        M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3569        push_word(M.x86.R_IP);
3570        M.x86.R_IP = mem_access_word(intnum * 4);
3571    }
3572    DECODE_CLEAR_SEGOVR();
3573    END_OF_INSTR();
3574}
3575
3576/****************************************************************************
3577REMARKS:
3578Handles opcode 0xce
3579****************************************************************************/
3580void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3581{
3582    u16 tmp;
3583
3584    START_OF_INSTR();
3585    DECODE_PRINTF("INTO\n");
3586    TRACE_AND_STEP();
3587    if (ACCESS_FLAG(F_OF)) {
3588        tmp = mem_access_word(4 * 4 + 2);
3589                if (_X86EMU_intrTab[4]) {
3590                        (*_X86EMU_intrTab[4])(4);
3591        } else {
3592            push_word((u16)M.x86.R_FLG);
3593            CLEAR_FLAG(F_IF);
3594            CLEAR_FLAG(F_TF);
3595            push_word(M.x86.R_CS);
3596            M.x86.R_CS = mem_access_word(4 * 4 + 2);
3597            push_word(M.x86.R_IP);
3598            M.x86.R_IP = mem_access_word(4 * 4);
3599        }
3600    }
3601    DECODE_CLEAR_SEGOVR();
3602    END_OF_INSTR();
3603}
3604
3605/****************************************************************************
3606REMARKS:
3607Handles opcode 0xcf
3608****************************************************************************/
3609void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3610{
3611    START_OF_INSTR();
3612    DECODE_PRINTF("IRET\n");
3613
3614    TRACE_AND_STEP();
3615
3616    M.x86.R_IP = pop_word();
3617    M.x86.R_CS = pop_word();
3618    M.x86.R_FLG = pop_word();
3619    DECODE_CLEAR_SEGOVR();
3620    END_OF_INSTR();
3621}
3622
3623/****************************************************************************
3624REMARKS:
3625Handles opcode 0xd0
3626****************************************************************************/
3627void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3628{
3629    int mod, rl, rh;
3630    u8 *destreg;
3631    uint destoffset;
3632    u8 destval;
3633
3634    /*
3635     * Yet another weirdo special case instruction format.  Part of
3636     * the opcode held below in "RH".  Doubly nested case would
3637     * result, except that the decoded instruction
3638     */
3639    START_OF_INSTR();
3640    FETCH_DECODE_MODRM(mod, rh, rl);
3641#ifdef DEBUG
3642    if (DEBUG_DECODE()) {
3643        /* XXX DECODE_PRINTF may be changed to something more
3644           general, so that it is important to leave the strings
3645           in the same format, even though the result is that the
3646           above test is done twice. */
3647        switch (rh) {
3648        case 0:
3649            DECODE_PRINTF("ROL\t");
3650            break;
3651        case 1:
3652            DECODE_PRINTF("ROR\t");
3653            break;
3654        case 2:
3655            DECODE_PRINTF("RCL\t");
3656            break;
3657        case 3:
3658            DECODE_PRINTF("RCR\t");
3659            break;
3660        case 4:
3661            DECODE_PRINTF("SHL\t");
3662            break;
3663        case 5:
3664            DECODE_PRINTF("SHR\t");
3665            break;
3666        case 6:
3667            DECODE_PRINTF("SAL\t");
3668            break;
3669        case 7:
3670            DECODE_PRINTF("SAR\t");
3671            break;
3672        }
3673    }
3674#endif
3675    /* know operation, decode the mod byte to find the addressing
3676       mode. */
3677    if (mod < 3) {
3678        DECODE_PRINTF("BYTE PTR ");
3679        destoffset = decode_rmXX_address(mod, rl);
3680        DECODE_PRINTF(",1\n");
3681        destval = fetch_data_byte(destoffset);
3682        TRACE_AND_STEP();
3683        destval = (*opcD0_byte_operation[rh]) (destval, 1);
3684        store_data_byte(destoffset, destval);
3685    } else {                     /* register to register */
3686        destreg = DECODE_RM_BYTE_REGISTER(rl);
3687        DECODE_PRINTF(",1\n");
3688        TRACE_AND_STEP();
3689        destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3690        *destreg = destval;
3691    }
3692    DECODE_CLEAR_SEGOVR();
3693    END_OF_INSTR();
3694}
3695
3696/****************************************************************************
3697REMARKS:
3698Handles opcode 0xd1
3699****************************************************************************/
3700void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3701{
3702    int mod, rl, rh;
3703    uint destoffset;
3704
3705    /*
3706     * Yet another weirdo special case instruction format.  Part of
3707     * the opcode held below in "RH".  Doubly nested case would
3708     * result, except that the decoded instruction
3709     */
3710    START_OF_INSTR();
3711    FETCH_DECODE_MODRM(mod, rh, rl);
3712#ifdef DEBUG
3713    if (DEBUG_DECODE()) {
3714        /* XXX DECODE_PRINTF may be changed to something more
3715           general, so that it is important to leave the strings
3716           in the same format, even though the result is that the
3717           above test is done twice. */
3718        switch (rh) {
3719        case 0:
3720            DECODE_PRINTF("ROL\t");
3721            break;
3722        case 1:
3723            DECODE_PRINTF("ROR\t");
3724            break;
3725        case 2:
3726            DECODE_PRINTF("RCL\t");
3727            break;
3728        case 3:
3729            DECODE_PRINTF("RCR\t");
3730            break;
3731        case 4:
3732            DECODE_PRINTF("SHL\t");
3733            break;
3734        case 5:
3735            DECODE_PRINTF("SHR\t");
3736            break;
3737        case 6:
3738            DECODE_PRINTF("SAL\t");
3739            break;
3740        case 7:
3741            DECODE_PRINTF("SAR\t");
3742            break;
3743        }
3744    }
3745#endif
3746    /* know operation, decode the mod byte to find the addressing
3747       mode. */
3748    if (mod < 3) {
3749        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3750            u32 destval;
3751
3752            DECODE_PRINTF("DWORD PTR ");
3753            destoffset = decode_rmXX_address(mod, rl);
3754            DECODE_PRINTF(",1\n");
3755            destval = fetch_data_long(destoffset);
3756            TRACE_AND_STEP();
3757            destval = (*opcD1_long_operation[rh]) (destval, 1);
3758            store_data_long(destoffset, destval);
3759        } else {
3760            u16 destval;
3761
3762            DECODE_PRINTF("WORD PTR ");
3763            destoffset = decode_rmXX_address(mod, rl);
3764            DECODE_PRINTF(",1\n");
3765            destval = fetch_data_word(destoffset);
3766            TRACE_AND_STEP();
3767            destval = (*opcD1_word_operation[rh]) (destval, 1);
3768            store_data_word(destoffset, destval);
3769        }
3770    } else {                     /* register to register */
3771        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3772                        u32 destval;
3773                        u32 *destreg;
3774
3775            destreg = DECODE_RM_LONG_REGISTER(rl);
3776            DECODE_PRINTF(",1\n");
3777            TRACE_AND_STEP();
3778            destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3779            *destreg = destval;
3780        } else {
3781                        u16 destval;
3782                        u16 *destreg;
3783
3784            destreg = DECODE_RM_WORD_REGISTER(rl);
3785            DECODE_PRINTF(",1\n");
3786            TRACE_AND_STEP();
3787            destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3788            *destreg = destval;
3789        }
3790    }
3791    DECODE_CLEAR_SEGOVR();
3792    END_OF_INSTR();
3793}
3794
3795/****************************************************************************
3796REMARKS:
3797Handles opcode 0xd2
3798****************************************************************************/
3799void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3800{
3801    int mod, rl, rh;
3802    u8 *destreg;
3803    uint destoffset;
3804    u8 destval;
3805    u8 amt;
3806
3807    /*
3808     * Yet another weirdo special case instruction format.  Part of
3809     * the opcode held below in "RH".  Doubly nested case would
3810     * result, except that the decoded instruction
3811     */
3812    START_OF_INSTR();
3813    FETCH_DECODE_MODRM(mod, rh, rl);
3814#ifdef DEBUG
3815    if (DEBUG_DECODE()) {
3816        /* XXX DECODE_PRINTF may be changed to something more
3817           general, so that it is important to leave the strings
3818           in the same format, even though the result is that the
3819           above test is done twice. */
3820        switch (rh) {
3821        case 0:
3822            DECODE_PRINTF("ROL\t");
3823            break;
3824        case 1:
3825            DECODE_PRINTF("ROR\t");
3826            break;
3827        case 2:
3828            DECODE_PRINTF("RCL\t");
3829            break;
3830        case 3:
3831            DECODE_PRINTF("RCR\t");
3832            break;
3833        case 4:
3834            DECODE_PRINTF("SHL\t");
3835            break;
3836        case 5:
3837            DECODE_PRINTF("SHR\t");
3838            break;
3839        case 6:
3840            DECODE_PRINTF("SAL\t");
3841            break;
3842        case 7:
3843            DECODE_PRINTF("SAR\t");
3844            break;
3845        }
3846    }
3847#endif
3848    /* know operation, decode the mod byte to find the addressing
3849       mode. */
3850    amt = M.x86.R_CL;
3851    if (mod < 3) {
3852        DECODE_PRINTF("BYTE PTR ");
3853        destoffset = decode_rmXX_address(mod, rl);
3854        DECODE_PRINTF(",CL\n");
3855        destval = fetch_data_byte(destoffset);
3856        TRACE_AND_STEP();
3857        destval = (*opcD0_byte_operation[rh]) (destval, amt);
3858        store_data_byte(destoffset, destval);
3859    } else {                     /* register to register */
3860        destreg = DECODE_RM_BYTE_REGISTER(rl);
3861        DECODE_PRINTF(",CL\n");
3862        TRACE_AND_STEP();
3863        destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3864        *destreg = destval;
3865    }
3866    DECODE_CLEAR_SEGOVR();
3867    END_OF_INSTR();
3868}
3869
3870/****************************************************************************
3871REMARKS:
3872Handles opcode 0xd3
3873****************************************************************************/
3874void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3875{
3876    int mod, rl, rh;
3877    uint destoffset;
3878    u8 amt;
3879
3880    /*
3881     * Yet another weirdo special case instruction format.  Part of
3882     * the opcode held below in "RH".  Doubly nested case would
3883     * result, except that the decoded instruction
3884     */
3885    START_OF_INSTR();
3886    FETCH_DECODE_MODRM(mod, rh, rl);
3887#ifdef DEBUG
3888    if (DEBUG_DECODE()) {
3889        /* XXX DECODE_PRINTF may be changed to something more
3890           general, so that it is important to leave the strings
3891           in the same format, even though the result is that the
3892           above test is done twice. */
3893        switch (rh) {
3894        case 0:
3895            DECODE_PRINTF("ROL\t");
3896            break;
3897        case 1:
3898            DECODE_PRINTF("ROR\t");
3899            break;
3900        case 2:
3901            DECODE_PRINTF("RCL\t");
3902            break;
3903        case 3:
3904            DECODE_PRINTF("RCR\t");
3905            break;
3906        case 4:
3907            DECODE_PRINTF("SHL\t");
3908            break;
3909        case 5:
3910            DECODE_PRINTF("SHR\t");
3911            break;
3912        case 6:
3913            DECODE_PRINTF("SAL\t");
3914            break;
3915        case 7:
3916            DECODE_PRINTF("SAR\t");
3917            break;
3918        }
3919    }
3920#endif
3921    /* know operation, decode the mod byte to find the addressing
3922       mode. */
3923    amt = M.x86.R_CL;
3924    if (mod < 3) {
3925        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3926            u32 destval;
3927
3928            DECODE_PRINTF("DWORD PTR ");
3929            destoffset = decode_rmXX_address(mod, rl);
3930            DECODE_PRINTF(",CL\n");
3931            destval = fetch_data_long(destoffset);
3932            TRACE_AND_STEP();
3933            destval = (*opcD1_long_operation[rh]) (destval, amt);
3934            store_data_long(destoffset, destval);
3935        } else {
3936            u16 destval;
3937
3938            DECODE_PRINTF("WORD PTR ");
3939            destoffset = decode_rmXX_address(mod, rl);
3940            DECODE_PRINTF(",CL\n");
3941            destval = fetch_data_word(destoffset);
3942            TRACE_AND_STEP();
3943            destval = (*opcD1_word_operation[rh]) (destval, amt);
3944            store_data_word(destoffset, destval);
3945        }
3946    } else {                     /* register to register */
3947        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3948            u32 *destreg;
3949
3950            destreg = DECODE_RM_LONG_REGISTER(rl);
3951            DECODE_PRINTF(",CL\n");
3952            TRACE_AND_STEP();
3953            *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3954        } else {
3955            u16 *destreg;
3956
3957            destreg = DECODE_RM_WORD_REGISTER(rl);
3958            DECODE_PRINTF(",CL\n");
3959            TRACE_AND_STEP();
3960            *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3961        }
3962    }
3963    DECODE_CLEAR_SEGOVR();
3964    END_OF_INSTR();
3965}
3966
3967/****************************************************************************
3968REMARKS:
3969Handles opcode 0xd4
3970****************************************************************************/
3971void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3972{
3973    u8 a;
3974
3975    START_OF_INSTR();
3976    DECODE_PRINTF("AAM\n");
3977    a = fetch_byte_imm();      /* this is a stupid encoding. */
3978    if (a != 10) {
3979        DECODE_PRINTF("ERROR DECODING AAM\n");
3980        TRACE_REGS();
3981        HALT_SYS();
3982    }
3983    TRACE_AND_STEP();
3984    /* note the type change here --- returning AL and AH in AX. */
3985    M.x86.R_AX = aam_word(M.x86.R_AL);
3986    DECODE_CLEAR_SEGOVR();
3987    END_OF_INSTR();
3988}
3989
3990/****************************************************************************
3991REMARKS:
3992Handles opcode 0xd5
3993****************************************************************************/
3994void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3995{
3996    u8 a;
3997
3998    START_OF_INSTR();
3999    DECODE_PRINTF("AAD\n");
4000    a = fetch_byte_imm();
4001    TRACE_AND_STEP();
4002    M.x86.R_AX = aad_word(M.x86.R_AX);
4003    DECODE_CLEAR_SEGOVR();
4004    END_OF_INSTR();
4005}
4006
4007/* opcode 0xd6 ILLEGAL OPCODE */
4008
4009/****************************************************************************
4010REMARKS:
4011Handles opcode 0xd7
4012****************************************************************************/
4013void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4014{
4015    u16 addr;
4016
4017    START_OF_INSTR();
4018    DECODE_PRINTF("XLAT\n");
4019    TRACE_AND_STEP();
4020        addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4021    M.x86.R_AL = fetch_data_byte(addr);
4022    DECODE_CLEAR_SEGOVR();
4023    END_OF_INSTR();
4024}
4025
4026/* instuctions  D8 .. DF are in i87_ops.c */
4027
4028/****************************************************************************
4029REMARKS:
4030Handles opcode 0xe0
4031****************************************************************************/
4032void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4033{
4034    s16 ip;
4035
4036    START_OF_INSTR();
4037    DECODE_PRINTF("LOOPNE\t");
4038    ip = (s8) fetch_byte_imm();
4039    ip += (s16) M.x86.R_IP;
4040    DECODE_PRINTF2("%04x\n", ip);
4041    TRACE_AND_STEP();
4042    M.x86.R_CX -= 1;
4043    if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))      /* CX != 0 and !ZF */
4044        M.x86.R_IP = ip;
4045    DECODE_CLEAR_SEGOVR();
4046    END_OF_INSTR();
4047}
4048
4049/****************************************************************************
4050REMARKS:
4051Handles opcode 0xe1
4052****************************************************************************/
4053void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4054{
4055    s16 ip;
4056
4057    START_OF_INSTR();
4058    DECODE_PRINTF("LOOPE\t");
4059    ip = (s8) fetch_byte_imm();
4060    ip += (s16) M.x86.R_IP;
4061    DECODE_PRINTF2("%04x\n", ip);
4062    TRACE_AND_STEP();
4063    M.x86.R_CX -= 1;
4064    if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF))       /* CX != 0 and ZF */
4065        M.x86.R_IP = ip;
4066    DECODE_CLEAR_SEGOVR();
4067    END_OF_INSTR();
4068}
4069
4070/****************************************************************************
4071REMARKS:
4072Handles opcode 0xe2
4073****************************************************************************/
4074void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4075{
4076    s16 ip;
4077
4078    START_OF_INSTR();
4079    DECODE_PRINTF("LOOP\t");
4080    ip = (s8) fetch_byte_imm();
4081    ip += (s16) M.x86.R_IP;
4082    DECODE_PRINTF2("%04x\n", ip);
4083    TRACE_AND_STEP();
4084    M.x86.R_CX -= 1;
4085    if (M.x86.R_CX != 0)
4086        M.x86.R_IP = ip;
4087    DECODE_CLEAR_SEGOVR();
4088    END_OF_INSTR();
4089}
4090
4091/****************************************************************************
4092REMARKS:
4093Handles opcode 0xe3
4094****************************************************************************/
4095void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4096{
4097    u16 target;
4098    s8  offset;
4099
4100    /* jump to byte offset if overflow flag is set */
4101    START_OF_INSTR();
4102    DECODE_PRINTF("JCXZ\t");
4103    offset = (s8)fetch_byte_imm();
4104    target = (u16)(M.x86.R_IP + offset);
4105    DECODE_PRINTF2("%x\n", target);
4106    TRACE_AND_STEP();
4107    if (M.x86.R_CX == 0)
4108        M.x86.R_IP = target;
4109    DECODE_CLEAR_SEGOVR();
4110    END_OF_INSTR();
4111}
4112
4113/****************************************************************************
4114REMARKS:
4115Handles opcode 0xe4
4116****************************************************************************/
4117void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4118{
4119    u8 port;
4120
4121    START_OF_INSTR();
4122    DECODE_PRINTF("IN\t");
4123        port = (u8) fetch_byte_imm();
4124    DECODE_PRINTF2("%x,AL\n", port);
4125    TRACE_AND_STEP();
4126    M.x86.R_AL = (*sys_inb)(port);
4127    DECODE_CLEAR_SEGOVR();
4128    END_OF_INSTR();
4129}
4130
4131/****************************************************************************
4132REMARKS:
4133Handles opcode 0xe5
4134****************************************************************************/
4135void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4136{
4137    u8 port;
4138
4139    START_OF_INSTR();
4140    DECODE_PRINTF("IN\t");
4141        port = (u8) fetch_byte_imm();
4142    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4143        DECODE_PRINTF2("EAX,%x\n", port);
4144    } else {
4145        DECODE_PRINTF2("AX,%x\n", port);
4146    }
4147    TRACE_AND_STEP();
4148    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4149        M.x86.R_EAX = (*sys_inl)(port);
4150    } else {
4151        M.x86.R_AX = (*sys_inw)(port);
4152    }
4153    DECODE_CLEAR_SEGOVR();
4154    END_OF_INSTR();
4155}
4156
4157/****************************************************************************
4158REMARKS:
4159Handles opcode 0xe6
4160****************************************************************************/
4161void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4162{
4163    u8 port;
4164
4165    START_OF_INSTR();
4166    DECODE_PRINTF("OUT\t");
4167        port = (u8) fetch_byte_imm();
4168    DECODE_PRINTF2("%x,AL\n", port);
4169    TRACE_AND_STEP();
4170    (*sys_outb)(port, M.x86.R_AL);
4171    DECODE_CLEAR_SEGOVR();
4172    END_OF_INSTR();
4173}
4174
4175/****************************************************************************
4176REMARKS:
4177Handles opcode 0xe7
4178****************************************************************************/
4179void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4180{
4181    u8 port;
4182
4183    START_OF_INSTR();
4184    DECODE_PRINTF("OUT\t");
4185        port = (u8) fetch_byte_imm();
4186    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4187        DECODE_PRINTF2("%x,EAX\n", port);
4188    } else {
4189        DECODE_PRINTF2("%x,AX\n", port);
4190    }
4191    TRACE_AND_STEP();
4192    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4193        (*sys_outl)(port, M.x86.R_EAX);
4194    } else {
4195        (*sys_outw)(port, M.x86.R_AX);
4196    }
4197    DECODE_CLEAR_SEGOVR();
4198    END_OF_INSTR();
4199}
4200
4201/****************************************************************************
4202REMARKS:
4203Handles opcode 0xe8
4204****************************************************************************/
4205void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4206{
4207    s16 ip;
4208
4209    START_OF_INSTR();
4210        DECODE_PRINTF("CALL\t");
4211        ip = (s16) fetch_word_imm();
4212        ip += (s16) M.x86.R_IP;    /* CHECK SIGN */
4213        DECODE_PRINTF2("%04x\n", ip);
4214        CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4215    TRACE_AND_STEP();
4216    push_word(M.x86.R_IP);
4217    M.x86.R_IP = ip;
4218    DECODE_CLEAR_SEGOVR();
4219    END_OF_INSTR();
4220}
4221
4222/****************************************************************************
4223REMARKS:
4224Handles opcode 0xe9
4225****************************************************************************/
4226void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4227{
4228    int ip;
4229
4230    START_OF_INSTR();
4231    DECODE_PRINTF("JMP\t");
4232    ip = (s16)fetch_word_imm();
4233    ip += (s16)M.x86.R_IP;
4234    DECODE_PRINTF2("%04x\n", ip);
4235    TRACE_AND_STEP();
4236    M.x86.R_IP = (u16)ip;
4237    DECODE_CLEAR_SEGOVR();
4238    END_OF_INSTR();
4239}
4240
4241/****************************************************************************
4242REMARKS:
4243Handles opcode 0xea
4244****************************************************************************/
4245void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4246{
4247    u16 cs, ip;
4248
4249    START_OF_INSTR();
4250    DECODE_PRINTF("JMP\tFAR ");
4251    ip = fetch_word_imm();
4252    cs = fetch_word_imm();
4253    DECODE_PRINTF2("%04x:", cs);
4254    DECODE_PRINTF2("%04x\n", ip);
4255    TRACE_AND_STEP();
4256    M.x86.R_IP = ip;
4257    M.x86.R_CS = cs;
4258    DECODE_CLEAR_SEGOVR();
4259    END_OF_INSTR();
4260}
4261
4262/****************************************************************************
4263REMARKS:
4264Handles opcode 0xeb
4265****************************************************************************/
4266void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4267{
4268    u16 target;
4269    s8 offset;
4270
4271    START_OF_INSTR();
4272    DECODE_PRINTF("JMP\t");
4273    offset = (s8)fetch_byte_imm();
4274    target = (u16)(M.x86.R_IP + offset);
4275    DECODE_PRINTF2("%x\n", target);
4276    TRACE_AND_STEP();
4277    M.x86.R_IP = target;
4278    DECODE_CLEAR_SEGOVR();
4279    END_OF_INSTR();
4280}
4281
4282/****************************************************************************
4283REMARKS:
4284Handles opcode 0xec
4285****************************************************************************/
4286void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4287{
4288    START_OF_INSTR();
4289    DECODE_PRINTF("IN\tAL,DX\n");
4290    TRACE_AND_STEP();
4291    M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4292    DECODE_CLEAR_SEGOVR();
4293    END_OF_INSTR();
4294}
4295
4296/****************************************************************************
4297REMARKS:
4298Handles opcode 0xed
4299****************************************************************************/
4300void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4301{
4302    START_OF_INSTR();
4303    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4304        DECODE_PRINTF("IN\tEAX,DX\n");
4305    } else {
4306        DECODE_PRINTF("IN\tAX,DX\n");
4307    }
4308    TRACE_AND_STEP();
4309    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4310        M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4311    } else {
4312        M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4313    }
4314    DECODE_CLEAR_SEGOVR();
4315    END_OF_INSTR();
4316}
4317
4318/****************************************************************************
4319REMARKS:
4320Handles opcode 0xee
4321****************************************************************************/
4322void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4323{
4324    START_OF_INSTR();
4325    DECODE_PRINTF("OUT\tDX,AL\n");
4326    TRACE_AND_STEP();
4327    (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4328    DECODE_CLEAR_SEGOVR();
4329    END_OF_INSTR();
4330}
4331
4332/****************************************************************************
4333REMARKS:
4334Handles opcode 0xef
4335****************************************************************************/
4336void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4337{
4338    START_OF_INSTR();
4339    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4340        DECODE_PRINTF("OUT\tDX,EAX\n");
4341    } else {
4342        DECODE_PRINTF("OUT\tDX,AX\n");
4343    }
4344    TRACE_AND_STEP();
4345    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4346        (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4347    } else {
4348        (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4349    }
4350    DECODE_CLEAR_SEGOVR();
4351    END_OF_INSTR();
4352}
4353
4354/****************************************************************************
4355REMARKS:
4356Handles opcode 0xf0
4357****************************************************************************/
4358void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4359{
4360    START_OF_INSTR();
4361    DECODE_PRINTF("LOCK:\n");
4362    TRACE_AND_STEP();
4363    DECODE_CLEAR_SEGOVR();
4364    END_OF_INSTR();
4365}
4366
4367/*opcode 0xf1 ILLEGAL OPERATION */
4368
4369/****************************************************************************
4370REMARKS:
4371Handles opcode 0xf2
4372****************************************************************************/
4373void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4374{
4375    START_OF_INSTR();
4376    DECODE_PRINTF("REPNE\n");
4377    TRACE_AND_STEP();
4378    M.x86.mode |= SYSMODE_PREFIX_REPNE;
4379    DECODE_CLEAR_SEGOVR();
4380    END_OF_INSTR();
4381}
4382
4383/****************************************************************************
4384REMARKS:
4385Handles opcode 0xf3
4386****************************************************************************/
4387void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4388{
4389    START_OF_INSTR();
4390    DECODE_PRINTF("REPE\n");
4391    TRACE_AND_STEP();
4392    M.x86.mode |= SYSMODE_PREFIX_REPE;
4393    DECODE_CLEAR_SEGOVR();
4394    END_OF_INSTR();
4395}
4396
4397/****************************************************************************
4398REMARKS:
4399Handles opcode 0xf4
4400****************************************************************************/
4401void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4402{
4403    START_OF_INSTR();
4404    DECODE_PRINTF("HALT\n");
4405    TRACE_AND_STEP();
4406    HALT_SYS();
4407    DECODE_CLEAR_SEGOVR();
4408    END_OF_INSTR();
4409}
4410
4411/****************************************************************************
4412REMARKS:
4413Handles opcode 0xf5
4414****************************************************************************/
4415void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4416{
4417    /* complement the carry flag. */
4418    START_OF_INSTR();
4419    DECODE_PRINTF("CMC\n");
4420    TRACE_AND_STEP();
4421    TOGGLE_FLAG(F_CF);
4422    DECODE_CLEAR_SEGOVR();
4423    END_OF_INSTR();
4424}
4425
4426/****************************************************************************
4427REMARKS:
4428Handles opcode 0xf6
4429****************************************************************************/
4430void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4431{
4432    int mod, rl, rh;
4433    u8 *destreg;
4434    uint destoffset;
4435    u8 destval, srcval;
4436
4437    /* long, drawn out code follows.  Double switch for a total
4438       of 32 cases.  */
4439    START_OF_INSTR();
4440    FETCH_DECODE_MODRM(mod, rh, rl);
4441    DECODE_PRINTF(opF6_names[rh]);
4442    if (mod < 3) {
4443        DECODE_PRINTF("BYTE PTR ");
4444        destoffset = decode_rmXX_address(mod, rl);
4445        destval = fetch_data_byte(destoffset);
4446
4447        switch (rh) {
4448        case 0:         /* test byte imm */
4449            DECODE_PRINTF(",");
4450            srcval = fetch_byte_imm();
4451            DECODE_PRINTF2("%02x\n", srcval);
4452            TRACE_AND_STEP();
4453            test_byte(destval, srcval);
4454            break;
4455        case 1:
4456            DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4457            HALT_SYS();
4458            break;
4459        case 2:
4460            DECODE_PRINTF("\n");
4461            TRACE_AND_STEP();
4462            destval = not_byte(destval);
4463            store_data_byte(destoffset, destval);
4464            break;
4465        case 3:
4466            DECODE_PRINTF("\n");
4467            TRACE_AND_STEP();
4468            destval = neg_byte(destval);
4469            store_data_byte(destoffset, destval);
4470            break;
4471        case 4:
4472            DECODE_PRINTF("\n");
4473            TRACE_AND_STEP();
4474            mul_byte(destval);
4475            break;
4476        case 5:
4477            DECODE_PRINTF("\n");
4478            TRACE_AND_STEP();
4479            imul_byte(destval);
4480            break;
4481        case 6:
4482            DECODE_PRINTF("\n");
4483            TRACE_AND_STEP();
4484            div_byte(destval);
4485            break;
4486        default:
4487            DECODE_PRINTF("\n");
4488            TRACE_AND_STEP();
4489            idiv_byte(destval);
4490            break;
4491        }
4492    } else {                     /* mod=11 */
4493        destreg = DECODE_RM_BYTE_REGISTER(rl);
4494        switch (rh) {
4495        case 0:         /* test byte imm */
4496            DECODE_PRINTF(",");
4497            srcval = fetch_byte_imm();
4498            DECODE_PRINTF2("%02x\n", srcval);
4499            TRACE_AND_STEP();
4500            test_byte(*destreg, srcval);
4501            break;
4502        case 1:
4503            DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4504            HALT_SYS();
4505            break;
4506        case 2:
4507            DECODE_PRINTF("\n");
4508            TRACE_AND_STEP();
4509            *destreg = not_byte(*destreg);
4510            break;
4511        case 3:
4512            DECODE_PRINTF("\n");
4513            TRACE_AND_STEP();
4514            *destreg = neg_byte(*destreg);
4515            break;
4516        case 4:
4517            DECODE_PRINTF("\n");
4518            TRACE_AND_STEP();
4519            mul_byte(*destreg);      /*!!!  */
4520            break;
4521        case 5:
4522            DECODE_PRINTF("\n");
4523            TRACE_AND_STEP();
4524            imul_byte(*destreg);
4525            break;
4526        case 6:
4527            DECODE_PRINTF("\n");
4528            TRACE_AND_STEP();
4529            div_byte(*destreg);
4530            break;
4531        default:
4532            DECODE_PRINTF("\n");
4533            TRACE_AND_STEP();
4534            idiv_byte(*destreg);
4535            break;
4536        }
4537    }
4538    DECODE_CLEAR_SEGOVR();
4539    END_OF_INSTR();
4540}
4541
4542/****************************************************************************
4543REMARKS:
4544Handles opcode 0xf7
4545****************************************************************************/
4546void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4547{
4548    int mod, rl, rh;
4549    uint destoffset;
4550
4551    START_OF_INSTR();
4552    FETCH_DECODE_MODRM(mod, rh, rl);
4553    DECODE_PRINTF(opF6_names[rh]);
4554    if (mod < 3) {
4555
4556        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4557            u32 destval, srcval;
4558
4559            DECODE_PRINTF("DWORD PTR ");
4560            destoffset = decode_rmXX_address(mod, rl);
4561            destval = fetch_data_long(destoffset);
4562
4563            switch (rh) {
4564            case 0:
4565                DECODE_PRINTF(",");
4566                srcval = fetch_long_imm();
4567                DECODE_PRINTF2("%x\n", srcval);
4568                TRACE_AND_STEP();
4569                test_long(destval, srcval);
4570                break;
4571            case 1:
4572                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4573                HALT_SYS();
4574                break;
4575            case 2:
4576                DECODE_PRINTF("\n");
4577                TRACE_AND_STEP();
4578                destval = not_long(destval);
4579                store_data_long(destoffset, destval);
4580                break;
4581            case 3:
4582                DECODE_PRINTF("\n");
4583                TRACE_AND_STEP();
4584                destval = neg_long(destval);
4585                store_data_long(destoffset, destval);
4586                break;
4587            case 4:
4588                DECODE_PRINTF("\n");
4589                TRACE_AND_STEP();
4590                mul_long(destval);
4591                break;
4592            case 5:
4593                DECODE_PRINTF("\n");
4594                TRACE_AND_STEP();
4595                imul_long(destval);
4596                break;
4597            case 6:
4598                DECODE_PRINTF("\n");
4599                TRACE_AND_STEP();
4600                div_long(destval);
4601                break;
4602            case 7:
4603                DECODE_PRINTF("\n");
4604                TRACE_AND_STEP();
4605                idiv_long(destval);
4606                break;
4607            }
4608        } else {
4609            u16 destval, srcval;
4610
4611            DECODE_PRINTF("WORD PTR ");
4612            destoffset = decode_rmXX_address(mod, rl);
4613            destval = fetch_data_word(destoffset);
4614
4615            switch (rh) {
4616            case 0:         /* test word imm */
4617                DECODE_PRINTF(",");
4618                srcval = fetch_word_imm();
4619                DECODE_PRINTF2("%x\n", srcval);
4620                TRACE_AND_STEP();
4621                test_word(destval, srcval);
4622                break;
4623            case 1:
4624                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4625                HALT_SYS();
4626                break;
4627            case 2:
4628                DECODE_PRINTF("\n");
4629                TRACE_AND_STEP();
4630                destval = not_word(destval);
4631                store_data_word(destoffset, destval);
4632                break;
4633            case 3:
4634                DECODE_PRINTF("\n");
4635                TRACE_AND_STEP();
4636                destval = neg_word(destval);
4637                store_data_word(destoffset, destval);
4638                break;
4639            case 4:
4640                DECODE_PRINTF("\n");
4641                TRACE_AND_STEP();
4642                mul_word(destval);
4643                break;
4644            case 5:
4645                DECODE_PRINTF("\n");
4646                TRACE_AND_STEP();
4647                imul_word(destval);
4648                break;
4649            case 6:
4650                DECODE_PRINTF("\n");
4651                TRACE_AND_STEP();
4652                div_word(destval);
4653                break;
4654            case 7:
4655                DECODE_PRINTF("\n");
4656                TRACE_AND_STEP();
4657                idiv_word(destval);
4658                break;
4659            }
4660        }
4661
4662    } else {                     /* mod=11 */
4663
4664        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4665            u32 *destreg;
4666            u32 srcval;
4667
4668            destreg = DECODE_RM_LONG_REGISTER(rl);
4669
4670            switch (rh) {
4671            case 0:         /* test word imm */
4672                DECODE_PRINTF(",");
4673                srcval = fetch_long_imm();
4674                DECODE_PRINTF2("%x\n", srcval);
4675                TRACE_AND_STEP();
4676                test_long(*destreg, srcval);
4677                break;
4678            case 1:
4679                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4680                HALT_SYS();
4681                break;
4682            case 2:
4683                DECODE_PRINTF("\n");
4684                TRACE_AND_STEP();
4685                *destreg = not_long(*destreg);
4686                break;
4687            case 3:
4688                DECODE_PRINTF("\n");
4689                TRACE_AND_STEP();
4690                *destreg = neg_long(*destreg);
4691                break;
4692            case 4:
4693                DECODE_PRINTF("\n");
4694                TRACE_AND_STEP();
4695                mul_long(*destreg);      /*!!!  */
4696                break;
4697            case 5:
4698                DECODE_PRINTF("\n");
4699                TRACE_AND_STEP();
4700                imul_long(*destreg);
4701                break;
4702            case 6:
4703                DECODE_PRINTF("\n");
4704                TRACE_AND_STEP();
4705                div_long(*destreg);
4706                break;
4707            case 7:
4708                DECODE_PRINTF("\n");
4709                TRACE_AND_STEP();
4710                idiv_long(*destreg);
4711                break;
4712            }
4713        } else {
4714            u16 *destreg;
4715            u16 srcval;
4716
4717            destreg = DECODE_RM_WORD_REGISTER(rl);
4718
4719            switch (rh) {
4720            case 0:         /* test word imm */
4721                DECODE_PRINTF(",");
4722                srcval = fetch_word_imm();
4723                DECODE_PRINTF2("%x\n", srcval);
4724                TRACE_AND_STEP();
4725                test_word(*destreg, srcval);
4726                break;
4727            case 1:
4728                DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4729                HALT_SYS();
4730                break;
4731            case 2:
4732                DECODE_PRINTF("\n");
4733                TRACE_AND_STEP();
4734                *destreg = not_word(*destreg);
4735                break;
4736            case 3:
4737                DECODE_PRINTF("\n");
4738                TRACE_AND_STEP();
4739                *destreg = neg_word(*destreg);
4740                break;
4741            case 4:
4742                DECODE_PRINTF("\n");
4743                TRACE_AND_STEP();
4744                mul_word(*destreg);      /*!!!  */
4745                break;
4746            case 5:
4747                DECODE_PRINTF("\n");
4748                TRACE_AND_STEP();
4749                imul_word(*destreg);
4750                break;
4751            case 6:
4752                DECODE_PRINTF("\n");
4753                TRACE_AND_STEP();
4754                div_word(*destreg);
4755                break;
4756            case 7:
4757                DECODE_PRINTF("\n");
4758                TRACE_AND_STEP();
4759                idiv_word(*destreg);
4760                break;
4761            }
4762        }
4763    }
4764    DECODE_CLEAR_SEGOVR();
4765    END_OF_INSTR();
4766}
4767
4768/****************************************************************************
4769REMARKS:
4770Handles opcode 0xf8
4771****************************************************************************/
4772void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4773{
4774    /* clear the carry flag. */
4775    START_OF_INSTR();
4776    DECODE_PRINTF("CLC\n");
4777    TRACE_AND_STEP();
4778    CLEAR_FLAG(F_CF);
4779    DECODE_CLEAR_SEGOVR();
4780    END_OF_INSTR();
4781}
4782
4783/****************************************************************************
4784REMARKS:
4785Handles opcode 0xf9
4786****************************************************************************/
4787void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4788{
4789    /* set the carry flag. */
4790    START_OF_INSTR();
4791    DECODE_PRINTF("STC\n");
4792    TRACE_AND_STEP();
4793    SET_FLAG(F_CF);
4794    DECODE_CLEAR_SEGOVR();
4795    END_OF_INSTR();
4796}
4797
4798/****************************************************************************
4799REMARKS:
4800Handles opcode 0xfa
4801****************************************************************************/
4802void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4803{
4804    /* clear interrupts. */
4805    START_OF_INSTR();
4806    DECODE_PRINTF("CLI\n");
4807    TRACE_AND_STEP();
4808    CLEAR_FLAG(F_IF);
4809    DECODE_CLEAR_SEGOVR();
4810    END_OF_INSTR();
4811}
4812
4813/****************************************************************************
4814REMARKS:
4815Handles opcode 0xfb
4816****************************************************************************/
4817void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4818{
4819    /* enable  interrupts. */
4820    START_OF_INSTR();
4821    DECODE_PRINTF("STI\n");
4822    TRACE_AND_STEP();
4823    SET_FLAG(F_IF);
4824    DECODE_CLEAR_SEGOVR();
4825    END_OF_INSTR();
4826}
4827
4828/****************************************************************************
4829REMARKS:
4830Handles opcode 0xfc
4831****************************************************************************/
4832void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4833{
4834    /* clear interrupts. */
4835    START_OF_INSTR();
4836    DECODE_PRINTF("CLD\n");
4837    TRACE_AND_STEP();
4838    CLEAR_FLAG(F_DF);
4839    DECODE_CLEAR_SEGOVR();
4840    END_OF_INSTR();
4841}
4842
4843/****************************************************************************
4844REMARKS:
4845Handles opcode 0xfd
4846****************************************************************************/
4847void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4848{
4849    /* clear interrupts. */
4850    START_OF_INSTR();
4851    DECODE_PRINTF("STD\n");
4852    TRACE_AND_STEP();
4853    SET_FLAG(F_DF);
4854    DECODE_CLEAR_SEGOVR();
4855    END_OF_INSTR();
4856}
4857
4858/****************************************************************************
4859REMARKS:
4860Handles opcode 0xfe
4861****************************************************************************/
4862void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4863{
4864    int mod, rh, rl;
4865    u8 destval;
4866    uint destoffset;
4867    u8 *destreg;
4868
4869    /* Yet another special case instruction. */
4870    START_OF_INSTR();
4871    FETCH_DECODE_MODRM(mod, rh, rl);
4872#ifdef DEBUG
4873    if (DEBUG_DECODE()) {
4874        /* XXX DECODE_PRINTF may be changed to something more
4875           general, so that it is important to leave the strings
4876           in the same format, even though the result is that the
4877           above test is done twice. */
4878
4879        switch (rh) {
4880        case 0:
4881            DECODE_PRINTF("INC\t");
4882            break;
4883        case 1:
4884            DECODE_PRINTF("DEC\t");
4885            break;
4886        case 2:
4887        case 3:
4888        case 4:
4889        case 5:
4890        case 6:
4891        case 7:
4892            DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4893            HALT_SYS();
4894            break;
4895        }
4896    }
4897#endif
4898    if (mod < 3) {
4899        DECODE_PRINTF("BYTE PTR ");
4900        destoffset = decode_rmXX_address(mod, rl);
4901        DECODE_PRINTF("\n");
4902        destval = fetch_data_byte(destoffset);
4903        TRACE_AND_STEP();
4904        if (rh == 0)
4905          destval = inc_byte(destval);
4906        else
4907          destval = dec_byte(destval);
4908        store_data_byte(destoffset, destval);
4909    } else {
4910        destreg = DECODE_RM_BYTE_REGISTER(rl);
4911        DECODE_PRINTF("\n");
4912        TRACE_AND_STEP();
4913        if (rh == 0)
4914          *destreg = inc_byte(*destreg);
4915        else
4916          *destreg = dec_byte(*destreg);
4917    }
4918    DECODE_CLEAR_SEGOVR();
4919    END_OF_INSTR();
4920}
4921
4922/****************************************************************************
4923REMARKS:
4924Handles opcode 0xff
4925****************************************************************************/
4926void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4927{
4928    int mod, rh, rl;
4929    uint destoffset = 0;
4930        u16 *destreg;
4931        u16 destval,destval2;
4932
4933    /* Yet another special case instruction. */
4934    START_OF_INSTR();
4935    FETCH_DECODE_MODRM(mod, rh, rl);
4936#ifdef DEBUG
4937    if (DEBUG_DECODE()) {
4938        /* XXX DECODE_PRINTF may be changed to something more
4939           general, so that it is important to leave the strings
4940           in the same format, even though the result is that the
4941           above test is done twice. */
4942
4943        switch (rh) {
4944        case 0:
4945            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4946                DECODE_PRINTF("INC\tDWORD PTR ");
4947            } else {
4948                DECODE_PRINTF("INC\tWORD PTR ");
4949            }
4950            break;
4951        case 1:
4952            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4953                DECODE_PRINTF("DEC\tDWORD PTR ");
4954            } else {
4955                DECODE_PRINTF("DEC\tWORD PTR ");
4956            }
4957            break;
4958        case 2:
4959            DECODE_PRINTF("CALL\t ");
4960            break;
4961        case 3:
4962            DECODE_PRINTF("CALL\tFAR ");
4963            break;
4964        case 4:
4965            DECODE_PRINTF("JMP\t");
4966            break;
4967        case 5:
4968            DECODE_PRINTF("JMP\tFAR ");
4969            break;
4970        case 6:
4971            DECODE_PRINTF("PUSH\t");
4972            break;
4973        case 7:
4974            DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4975            HALT_SYS();
4976            break;
4977        }
4978    }
4979#endif
4980    if (mod < 3) {
4981        destoffset = decode_rmXX_address(mod, rl);
4982        DECODE_PRINTF("\n");
4983        switch (rh) {
4984        case 0:         /* inc word ptr ... */
4985            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4986                u32 destval;
4987
4988                destval = fetch_data_long(destoffset);
4989                TRACE_AND_STEP();
4990                destval = inc_long(destval);
4991                store_data_long(destoffset, destval);
4992            } else {
4993                u16 destval;
4994
4995                destval = fetch_data_word(destoffset);
4996                TRACE_AND_STEP();
4997                destval = inc_word(destval);
4998                store_data_word(destoffset, destval);
4999            }
5000            break;
5001        case 1:         /* dec word ptr ... */
5002            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5003                u32 destval;
5004
5005                destval = fetch_data_long(destoffset);
5006                TRACE_AND_STEP();
5007                destval = dec_long(destval);
5008                store_data_long(destoffset, destval);
5009            } else {
5010                u16 destval;
5011
5012                destval = fetch_data_word(destoffset);
5013                TRACE_AND_STEP();
5014                destval = dec_word(destval);
5015                store_data_word(destoffset, destval);
5016            }
5017            break;
5018        case 2:         /* call word ptr ... */
5019            destval = fetch_data_word(destoffset);
5020            TRACE_AND_STEP();
5021            push_word(M.x86.R_IP);
5022            M.x86.R_IP = destval;
5023            break;
5024        case 3:         /* call far ptr ... */
5025            destval = fetch_data_word(destoffset);
5026            destval2 = fetch_data_word(destoffset + 2);
5027            TRACE_AND_STEP();
5028            push_word(M.x86.R_CS);
5029            M.x86.R_CS = destval2;
5030            push_word(M.x86.R_IP);
5031            M.x86.R_IP = destval;
5032            break;
5033        case 4:         /* jmp word ptr ... */
5034            destval = fetch_data_word(destoffset);
5035            TRACE_AND_STEP();
5036            M.x86.R_IP = destval;
5037            break;
5038        case 5:         /* jmp far ptr ... */
5039            destval = fetch_data_word(destoffset);
5040            destval2 = fetch_data_word(destoffset + 2);
5041            TRACE_AND_STEP();
5042            M.x86.R_IP = destval;
5043            M.x86.R_CS = destval2;
5044            break;
5045        case 6:         /*  push word ptr ... */
5046            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5047                u32 destval;
5048
5049                destval = fetch_data_long(destoffset);
5050                TRACE_AND_STEP();
5051                push_long(destval);
5052            } else {
5053                u16 destval;
5054
5055                destval = fetch_data_word(destoffset);
5056                TRACE_AND_STEP();
5057                push_word(destval);
5058            }
5059            break;
5060        }
5061    } else {
5062        switch (rh) {
5063        case 0:
5064            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5065                u32 *destreg;
5066
5067                destreg = DECODE_RM_LONG_REGISTER(rl);
5068                DECODE_PRINTF("\n");
5069                TRACE_AND_STEP();
5070                *destreg = inc_long(*destreg);
5071            } else {
5072                u16 *destreg;
5073
5074                destreg = DECODE_RM_WORD_REGISTER(rl);
5075                DECODE_PRINTF("\n");
5076                TRACE_AND_STEP();
5077                *destreg = inc_word(*destreg);
5078            }
5079            break;
5080        case 1:
5081            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5082                u32 *destreg;
5083
5084                destreg = DECODE_RM_LONG_REGISTER(rl);
5085                DECODE_PRINTF("\n");
5086                TRACE_AND_STEP();
5087                *destreg = dec_long(*destreg);
5088            } else {
5089                u16 *destreg;
5090
5091                destreg = DECODE_RM_WORD_REGISTER(rl);
5092                DECODE_PRINTF("\n");
5093                TRACE_AND_STEP();
5094                *destreg = dec_word(*destreg);
5095            }
5096            break;
5097        case 2:         /* call word ptr ... */
5098            destreg = DECODE_RM_WORD_REGISTER(rl);
5099            DECODE_PRINTF("\n");
5100            TRACE_AND_STEP();
5101            push_word(M.x86.R_IP);
5102            M.x86.R_IP = *destreg;
5103            break;
5104        case 3:         /* jmp far ptr ... */
5105            DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5106            TRACE_AND_STEP();
5107            HALT_SYS();
5108            break;
5109
5110        case 4:         /* jmp  ... */
5111            destreg = DECODE_RM_WORD_REGISTER(rl);
5112            DECODE_PRINTF("\n");
5113            TRACE_AND_STEP();
5114            M.x86.R_IP = (u16) (*destreg);
5115            break;
5116        case 5:         /* jmp far ptr ... */
5117            DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5118            TRACE_AND_STEP();
5119            HALT_SYS();
5120            break;
5121        case 6:
5122            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5123                u32 *destreg;
5124
5125                destreg = DECODE_RM_LONG_REGISTER(rl);
5126                DECODE_PRINTF("\n");
5127                TRACE_AND_STEP();
5128                push_long(*destreg);
5129            } else {
5130                u16 *destreg;
5131
5132                destreg = DECODE_RM_WORD_REGISTER(rl);
5133                DECODE_PRINTF("\n");
5134                TRACE_AND_STEP();
5135                push_word(*destreg);
5136            }
5137            break;
5138        }
5139    }
5140    DECODE_CLEAR_SEGOVR();
5141    END_OF_INSTR();
5142}
5143
5144/***************************************************************************
5145 * Single byte operation code table:
5146 **************************************************************************/
5147void (*x86emu_optab[256])(u8) __attribute__ ((section(GOT2_TYPE))) =
5148{
5149/*  0x00 */ x86emuOp_genop_byte_RM_R,
5150/*  0x01 */ x86emuOp_genop_word_RM_R,
5151/*  0x02 */ x86emuOp_genop_byte_R_RM,
5152/*  0x03 */ x86emuOp_genop_word_R_RM,
5153/*  0x04 */ x86emuOp_genop_byte_AL_IMM,
5154/*  0x05 */ x86emuOp_genop_word_AX_IMM,
5155/*  0x06 */ x86emuOp_push_ES,
5156/*  0x07 */ x86emuOp_pop_ES,
5157
5158/*  0x08 */ x86emuOp_genop_byte_RM_R,
5159/*  0x09 */ x86emuOp_genop_word_RM_R,
5160/*  0x0a */ x86emuOp_genop_byte_R_RM,
5161/*  0x0b */ x86emuOp_genop_word_R_RM,
5162/*  0x0c */ x86emuOp_genop_byte_AL_IMM,
5163/*  0x0d */ x86emuOp_genop_word_AX_IMM,
5164/*  0x0e */ x86emuOp_push_CS,
5165/*  0x0f */ x86emuOp_two_byte,
5166
5167/*  0x10 */ x86emuOp_genop_byte_RM_R,
5168/*  0x11 */ x86emuOp_genop_word_RM_R,
5169/*  0x12 */ x86emuOp_genop_byte_R_RM,
5170/*  0x13 */ x86emuOp_genop_word_R_RM,
5171/*  0x14 */ x86emuOp_genop_byte_AL_IMM,
5172/*  0x15 */ x86emuOp_genop_word_AX_IMM,
5173/*  0x16 */ x86emuOp_push_SS,
5174/*  0x17 */ x86emuOp_pop_SS,
5175
5176/*  0x18 */ x86emuOp_genop_byte_RM_R,
5177/*  0x19 */ x86emuOp_genop_word_RM_R,
5178/*  0x1a */ x86emuOp_genop_byte_R_RM,
5179/*  0x1b */ x86emuOp_genop_word_R_RM,
5180/*  0x1c */ x86emuOp_genop_byte_AL_IMM,
5181/*  0x1d */ x86emuOp_genop_word_AX_IMM,
5182/*  0x1e */ x86emuOp_push_DS,
5183/*  0x1f */ x86emuOp_pop_DS,
5184
5185/*  0x20 */ x86emuOp_genop_byte_RM_R,
5186/*  0x21 */ x86emuOp_genop_word_RM_R,
5187/*  0x22 */ x86emuOp_genop_byte_R_RM,
5188/*  0x23 */ x86emuOp_genop_word_R_RM,
5189/*  0x24 */ x86emuOp_genop_byte_AL_IMM,
5190/*  0x25 */ x86emuOp_genop_word_AX_IMM,
5191/*  0x26 */ x86emuOp_segovr_ES,
5192/*  0x27 */ x86emuOp_daa,
5193
5194/*  0x28 */ x86emuOp_genop_byte_RM_R,
5195/*  0x29 */ x86emuOp_genop_word_RM_R,
5196/*  0x2a */ x86emuOp_genop_byte_R_RM,
5197/*  0x2b */ x86emuOp_genop_word_R_RM,
5198/*  0x2c */ x86emuOp_genop_byte_AL_IMM,
5199/*  0x2d */ x86emuOp_genop_word_AX_IMM,
5200/*  0x2e */ x86emuOp_segovr_CS,
5201/*  0x2f */ x86emuOp_das,
5202
5203/*  0x30 */ x86emuOp_genop_byte_RM_R,
5204/*  0x31 */ x86emuOp_genop_word_RM_R,
5205/*  0x32 */ x86emuOp_genop_byte_R_RM,
5206/*  0x33 */ x86emuOp_genop_word_R_RM,
5207/*  0x34 */ x86emuOp_genop_byte_AL_IMM,
5208/*  0x35 */ x86emuOp_genop_word_AX_IMM,
5209/*  0x36 */ x86emuOp_segovr_SS,
5210/*  0x37 */ x86emuOp_aaa,
5211
5212/*  0x38 */ x86emuOp_genop_byte_RM_R,
5213/*  0x39 */ x86emuOp_genop_word_RM_R,
5214/*  0x3a */ x86emuOp_genop_byte_R_RM,
5215/*  0x3b */ x86emuOp_genop_word_R_RM,
5216/*  0x3c */ x86emuOp_genop_byte_AL_IMM,
5217/*  0x3d */ x86emuOp_genop_word_AX_IMM,
5218/*  0x3e */ x86emuOp_segovr_DS,
5219/*  0x3f */ x86emuOp_aas,
5220
5221/*  0x40 */ x86emuOp_inc_register,
5222/*  0x41 */ x86emuOp_inc_register,
5223/*  0x42 */ x86emuOp_inc_register,
5224/*  0x43 */ x86emuOp_inc_register,
5225/*  0x44 */ x86emuOp_inc_register,
5226/*  0x45 */ x86emuOp_inc_register,
5227/*  0x46 */ x86emuOp_inc_register,
5228/*  0x47 */ x86emuOp_inc_register,
5229
5230/*  0x48 */ x86emuOp_dec_register,
5231/*  0x49 */ x86emuOp_dec_register,
5232/*  0x4a */ x86emuOp_dec_register,
5233/*  0x4b */ x86emuOp_dec_register,
5234/*  0x4c */ x86emuOp_dec_register,
5235/*  0x4d */ x86emuOp_dec_register,
5236/*  0x4e */ x86emuOp_dec_register,
5237/*  0x4f */ x86emuOp_dec_register,
5238
5239/*  0x50 */ x86emuOp_push_register,
5240/*  0x51 */ x86emuOp_push_register,
5241/*  0x52 */ x86emuOp_push_register,
5242/*  0x53 */ x86emuOp_push_register,
5243/*  0x54 */ x86emuOp_push_register,
5244/*  0x55 */ x86emuOp_push_register,
5245/*  0x56 */ x86emuOp_push_register,
5246/*  0x57 */ x86emuOp_push_register,
5247
5248/*  0x58 */ x86emuOp_pop_register,
5249/*  0x59 */ x86emuOp_pop_register,
5250/*  0x5a */ x86emuOp_pop_register,
5251/*  0x5b */ x86emuOp_pop_register,
5252/*  0x5c */ x86emuOp_pop_register,
5253/*  0x5d */ x86emuOp_pop_register,
5254/*  0x5e */ x86emuOp_pop_register,
5255/*  0x5f */ x86emuOp_pop_register,
5256
5257/*  0x60 */ x86emuOp_push_all,
5258/*  0x61 */ x86emuOp_pop_all,
5259/*  0x62 */ x86emuOp_illegal_op,   /* bound */
5260/*  0x63 */ x86emuOp_illegal_op,   /* arpl */
5261/*  0x64 */ x86emuOp_segovr_FS,
5262/*  0x65 */ x86emuOp_segovr_GS,
5263/*  0x66 */ x86emuOp_prefix_data,
5264/*  0x67 */ x86emuOp_prefix_addr,
5265
5266/*  0x68 */ x86emuOp_push_word_IMM,
5267/*  0x69 */ x86emuOp_imul_word_IMM,
5268/*  0x6a */ x86emuOp_push_byte_IMM,
5269/*  0x6b */ x86emuOp_imul_byte_IMM,
5270/*  0x6c */ x86emuOp_ins_byte,
5271/*  0x6d */ x86emuOp_ins_word,
5272/*  0x6e */ x86emuOp_outs_byte,
5273/*  0x6f */ x86emuOp_outs_word,
5274
5275/*  0x70 */ x86emuOp_jump_near_cond,
5276/*  0x71 */ x86emuOp_jump_near_cond,
5277/*  0x72 */ x86emuOp_jump_near_cond,
5278/*  0x73 */ x86emuOp_jump_near_cond,
5279/*  0x74 */ x86emuOp_jump_near_cond,
5280/*  0x75 */ x86emuOp_jump_near_cond,
5281/*  0x76 */ x86emuOp_jump_near_cond,
5282/*  0x77 */ x86emuOp_jump_near_cond,
5283
5284/*  0x78 */ x86emuOp_jump_near_cond,
5285/*  0x79 */ x86emuOp_jump_near_cond,
5286/*  0x7a */ x86emuOp_jump_near_cond,
5287/*  0x7b */ x86emuOp_jump_near_cond,
5288/*  0x7c */ x86emuOp_jump_near_cond,
5289/*  0x7d */ x86emuOp_jump_near_cond,
5290/*  0x7e */ x86emuOp_jump_near_cond,
5291/*  0x7f */ x86emuOp_jump_near_cond,
5292
5293/*  0x80 */ x86emuOp_opc80_byte_RM_IMM,
5294/*  0x81 */ x86emuOp_opc81_word_RM_IMM,
5295/*  0x82 */ x86emuOp_opc82_byte_RM_IMM,
5296/*  0x83 */ x86emuOp_opc83_word_RM_IMM,
5297/*  0x84 */ x86emuOp_test_byte_RM_R,
5298/*  0x85 */ x86emuOp_test_word_RM_R,
5299/*  0x86 */ x86emuOp_xchg_byte_RM_R,
5300/*  0x87 */ x86emuOp_xchg_word_RM_R,
5301
5302/*  0x88 */ x86emuOp_mov_byte_RM_R,
5303/*  0x89 */ x86emuOp_mov_word_RM_R,
5304/*  0x8a */ x86emuOp_mov_byte_R_RM,
5305/*  0x8b */ x86emuOp_mov_word_R_RM,
5306/*  0x8c */ x86emuOp_mov_word_RM_SR,
5307/*  0x8d */ x86emuOp_lea_word_R_M,
5308/*  0x8e */ x86emuOp_mov_word_SR_RM,
5309/*  0x8f */ x86emuOp_pop_RM,
5310
5311/*  0x90 */ x86emuOp_nop,
5312/*  0x91 */ x86emuOp_xchg_word_AX_register,
5313/*  0x92 */ x86emuOp_xchg_word_AX_register,
5314/*  0x93 */ x86emuOp_xchg_word_AX_register,
5315/*  0x94 */ x86emuOp_xchg_word_AX_register,
5316/*  0x95 */ x86emuOp_xchg_word_AX_register,
5317/*  0x96 */ x86emuOp_xchg_word_AX_register,
5318/*  0x97 */ x86emuOp_xchg_word_AX_register,
5319
5320/*  0x98 */ x86emuOp_cbw,
5321/*  0x99 */ x86emuOp_cwd,
5322/*  0x9a */ x86emuOp_call_far_IMM,
5323/*  0x9b */ x86emuOp_wait,
5324/*  0x9c */ x86emuOp_pushf_word,
5325/*  0x9d */ x86emuOp_popf_word,
5326/*  0x9e */ x86emuOp_sahf,
5327/*  0x9f */ x86emuOp_lahf,
5328
5329/*  0xa0 */ x86emuOp_mov_AL_M_IMM,
5330/*  0xa1 */ x86emuOp_mov_AX_M_IMM,
5331/*  0xa2 */ x86emuOp_mov_M_AL_IMM,
5332/*  0xa3 */ x86emuOp_mov_M_AX_IMM,
5333/*  0xa4 */ x86emuOp_movs_byte,
5334/*  0xa5 */ x86emuOp_movs_word,
5335/*  0xa6 */ x86emuOp_cmps_byte,
5336/*  0xa7 */ x86emuOp_cmps_word,
5337/*  0xa8 */ x86emuOp_test_AL_IMM,
5338/*  0xa9 */ x86emuOp_test_AX_IMM,
5339/*  0xaa */ x86emuOp_stos_byte,
5340/*  0xab */ x86emuOp_stos_word,
5341/*  0xac */ x86emuOp_lods_byte,
5342/*  0xad */ x86emuOp_lods_word,
5343/*  0xac */ x86emuOp_scas_byte,
5344/*  0xad */ x86emuOp_scas_word,
5345
5346/*  0xb0 */ x86emuOp_mov_byte_register_IMM,
5347/*  0xb1 */ x86emuOp_mov_byte_register_IMM,
5348/*  0xb2 */ x86emuOp_mov_byte_register_IMM,
5349/*  0xb3 */ x86emuOp_mov_byte_register_IMM,
5350/*  0xb4 */ x86emuOp_mov_byte_register_IMM,
5351/*  0xb5 */ x86emuOp_mov_byte_register_IMM,
5352/*  0xb6 */ x86emuOp_mov_byte_register_IMM,
5353/*  0xb7 */ x86emuOp_mov_byte_register_IMM,
5354
5355/*  0xb8 */ x86emuOp_mov_word_register_IMM,
5356/*  0xb9 */ x86emuOp_mov_word_register_IMM,
5357/*  0xba */ x86emuOp_mov_word_register_IMM,
5358/*  0xbb */ x86emuOp_mov_word_register_IMM,
5359/*  0xbc */ x86emuOp_mov_word_register_IMM,
5360/*  0xbd */ x86emuOp_mov_word_register_IMM,
5361/*  0xbe */ x86emuOp_mov_word_register_IMM,
5362/*  0xbf */ x86emuOp_mov_word_register_IMM,
5363
5364/*  0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5365/*  0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5366/*  0xc2 */ x86emuOp_ret_near_IMM,
5367/*  0xc3 */ x86emuOp_ret_near,
5368/*  0xc4 */ x86emuOp_les_R_IMM,
5369/*  0xc5 */ x86emuOp_lds_R_IMM,
5370/*  0xc6 */ x86emuOp_mov_byte_RM_IMM,
5371/*  0xc7 */ x86emuOp_mov_word_RM_IMM,
5372/*  0xc8 */ x86emuOp_enter,
5373/*  0xc9 */ x86emuOp_leave,
5374/*  0xca */ x86emuOp_ret_far_IMM,
5375/*  0xcb */ x86emuOp_ret_far,
5376/*  0xcc */ x86emuOp_int3,
5377/*  0xcd */ x86emuOp_int_IMM,
5378/*  0xce */ x86emuOp_into,
5379/*  0xcf */ x86emuOp_iret,
5380
5381/*  0xd0 */ x86emuOp_opcD0_byte_RM_1,
5382/*  0xd1 */ x86emuOp_opcD1_word_RM_1,
5383/*  0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5384/*  0xd3 */ x86emuOp_opcD3_word_RM_CL,
5385/*  0xd4 */ x86emuOp_aam,
5386/*  0xd5 */ x86emuOp_aad,
5387/*  0xd6 */ x86emuOp_illegal_op,   /* Undocumented SETALC instruction */
5388/*  0xd7 */ x86emuOp_xlat,
5389/*  0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5390/*  0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5391/*  0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5392/*  0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5393/*  0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5394/*  0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5395/*  0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5396/*  0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5397
5398/*  0xe0 */ x86emuOp_loopne,
5399/*  0xe1 */ x86emuOp_loope,
5400/*  0xe2 */ x86emuOp_loop,
5401/*  0xe3 */ x86emuOp_jcxz,
5402/*  0xe4 */ x86emuOp_in_byte_AL_IMM,
5403/*  0xe5 */ x86emuOp_in_word_AX_IMM,
5404/*  0xe6 */ x86emuOp_out_byte_IMM_AL,
5405/*  0xe7 */ x86emuOp_out_word_IMM_AX,
5406
5407/*  0xe8 */ x86emuOp_call_near_IMM,
5408/*  0xe9 */ x86emuOp_jump_near_IMM,
5409/*  0xea */ x86emuOp_jump_far_IMM,
5410/*  0xeb */ x86emuOp_jump_byte_IMM,
5411/*  0xec */ x86emuOp_in_byte_AL_DX,
5412/*  0xed */ x86emuOp_in_word_AX_DX,
5413/*  0xee */ x86emuOp_out_byte_DX_AL,
5414/*  0xef */ x86emuOp_out_word_DX_AX,
5415
5416/*  0xf0 */ x86emuOp_lock,
5417/*  0xf1 */ x86emuOp_illegal_op,
5418/*  0xf2 */ x86emuOp_repne,
5419/*  0xf3 */ x86emuOp_repe,
5420/*  0xf4 */ x86emuOp_halt,
5421/*  0xf5 */ x86emuOp_cmc,
5422/*  0xf6 */ x86emuOp_opcF6_byte_RM,
5423/*  0xf7 */ x86emuOp_opcF7_word_RM,
5424
5425/*  0xf8 */ x86emuOp_clc,
5426/*  0xf9 */ x86emuOp_stc,
5427/*  0xfa */ x86emuOp_cli,
5428/*  0xfb */ x86emuOp_sti,
5429/*  0xfc */ x86emuOp_cld,
5430/*  0xfd */ x86emuOp_std,
5431/*  0xfe */ x86emuOp_opcFE_byte_RM,
5432/*  0xff */ x86emuOp_opcFF_word_RM,
5433};
5434