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