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 preceding 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 CONFIG_X86EMU_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 CONFIG_X86EMU_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        DB(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 CONFIG_X86EMU_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 CONFIG_X86EMU_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 CONFIG_X86EMU_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 CONFIG_X86EMU_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        ERR_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 CONFIG_X86EMU_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 CONFIG_X86EMU_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        ERR_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        ERR_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    START_OF_INSTR();
3522    DECODE_PRINTF("INT 3\n");
3523    (void)mem_access_word(3 * 4 + 2);
3524    /* access the segment register */
3525    TRACE_AND_STEP();
3526        if (_X86EMU_intrTab[3]) {
3527                (*_X86EMU_intrTab[3])(3);
3528    } else {
3529        push_word((u16)M.x86.R_FLG);
3530        CLEAR_FLAG(F_IF);
3531        CLEAR_FLAG(F_TF);
3532        push_word(M.x86.R_CS);
3533        M.x86.R_CS = mem_access_word(3 * 4 + 2);
3534        push_word(M.x86.R_IP);
3535        M.x86.R_IP = mem_access_word(3 * 4);
3536    }
3537    DECODE_CLEAR_SEGOVR();
3538    END_OF_INSTR();
3539}
3540
3541/****************************************************************************
3542REMARKS:
3543Handles opcode 0xcd
3544****************************************************************************/
3545void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3546{
3547    u8 intnum;
3548
3549    START_OF_INSTR();
3550    DECODE_PRINTF("INT\t");
3551    intnum = fetch_byte_imm();
3552    DECODE_PRINTF2("%x\n", intnum);
3553    (void)mem_access_word(intnum * 4 + 2);
3554    TRACE_AND_STEP();
3555        if (_X86EMU_intrTab[intnum]) {
3556                (*_X86EMU_intrTab[intnum])(intnum);
3557    } else {
3558        push_word((u16)M.x86.R_FLG);
3559        CLEAR_FLAG(F_IF);
3560        CLEAR_FLAG(F_TF);
3561        push_word(M.x86.R_CS);
3562        M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3563        push_word(M.x86.R_IP);
3564        M.x86.R_IP = mem_access_word(intnum * 4);
3565    }
3566    DECODE_CLEAR_SEGOVR();
3567    END_OF_INSTR();
3568}
3569
3570/****************************************************************************
3571REMARKS:
3572Handles opcode 0xce
3573****************************************************************************/
3574void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3575{
3576    START_OF_INSTR();
3577    DECODE_PRINTF("INTO\n");
3578    TRACE_AND_STEP();
3579    if (ACCESS_FLAG(F_OF)) {
3580        (void)mem_access_word(4 * 4 + 2);
3581                if (_X86EMU_intrTab[4]) {
3582                        (*_X86EMU_intrTab[4])(4);
3583        } else {
3584            push_word((u16)M.x86.R_FLG);
3585            CLEAR_FLAG(F_IF);
3586            CLEAR_FLAG(F_TF);
3587            push_word(M.x86.R_CS);
3588            M.x86.R_CS = mem_access_word(4 * 4 + 2);
3589            push_word(M.x86.R_IP);
3590            M.x86.R_IP = mem_access_word(4 * 4);
3591        }
3592    }
3593    DECODE_CLEAR_SEGOVR();
3594    END_OF_INSTR();
3595}
3596
3597/****************************************************************************
3598REMARKS:
3599Handles opcode 0xcf
3600****************************************************************************/
3601void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3602{
3603    START_OF_INSTR();
3604    DECODE_PRINTF("IRET\n");
3605
3606    TRACE_AND_STEP();
3607
3608    M.x86.R_IP = pop_word();
3609    M.x86.R_CS = pop_word();
3610    M.x86.R_FLG = pop_word();
3611    DECODE_CLEAR_SEGOVR();
3612    END_OF_INSTR();
3613}
3614
3615/****************************************************************************
3616REMARKS:
3617Handles opcode 0xd0
3618****************************************************************************/
3619void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3620{
3621    int mod, rl, rh;
3622    u8 *destreg;
3623    uint destoffset;
3624    u8 destval;
3625
3626    /*
3627     * Yet another weirdo special case instruction format.  Part of
3628     * the opcode held below in "RH".  Doubly nested case would
3629     * result, except that the decoded instruction
3630     */
3631    START_OF_INSTR();
3632    FETCH_DECODE_MODRM(mod, rh, rl);
3633#ifdef CONFIG_X86EMU_DEBUG
3634    if (DEBUG_DECODE()) {
3635        /* XXX DECODE_PRINTF may be changed to something more
3636           general, so that it is important to leave the strings
3637           in the same format, even though the result is that the
3638           above test is done twice. */
3639        switch (rh) {
3640        case 0:
3641            DECODE_PRINTF("ROL\t");
3642            break;
3643        case 1:
3644            DECODE_PRINTF("ROR\t");
3645            break;
3646        case 2:
3647            DECODE_PRINTF("RCL\t");
3648            break;
3649        case 3:
3650            DECODE_PRINTF("RCR\t");
3651            break;
3652        case 4:
3653            DECODE_PRINTF("SHL\t");
3654            break;
3655        case 5:
3656            DECODE_PRINTF("SHR\t");
3657            break;
3658        case 6:
3659            DECODE_PRINTF("SAL\t");
3660            break;
3661        case 7:
3662            DECODE_PRINTF("SAR\t");
3663            break;
3664        }
3665    }
3666#endif
3667    /* know operation, decode the mod byte to find the addressing
3668       mode. */
3669    if (mod < 3) {
3670        DECODE_PRINTF("BYTE PTR ");
3671        destoffset = decode_rmXX_address(mod, rl);
3672        DECODE_PRINTF(",1\n");
3673        destval = fetch_data_byte(destoffset);
3674        TRACE_AND_STEP();
3675        destval = (*opcD0_byte_operation[rh]) (destval, 1);
3676        store_data_byte(destoffset, destval);
3677    } else {                     /* register to register */
3678        destreg = DECODE_RM_BYTE_REGISTER(rl);
3679        DECODE_PRINTF(",1\n");
3680        TRACE_AND_STEP();
3681        destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3682        *destreg = destval;
3683    }
3684    DECODE_CLEAR_SEGOVR();
3685    END_OF_INSTR();
3686}
3687
3688/****************************************************************************
3689REMARKS:
3690Handles opcode 0xd1
3691****************************************************************************/
3692void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3693{
3694    int mod, rl, rh;
3695    uint destoffset;
3696
3697    /*
3698     * Yet another weirdo special case instruction format.  Part of
3699     * the opcode held below in "RH".  Doubly nested case would
3700     * result, except that the decoded instruction
3701     */
3702    START_OF_INSTR();
3703    FETCH_DECODE_MODRM(mod, rh, rl);
3704#ifdef CONFIG_X86EMU_DEBUG
3705    if (DEBUG_DECODE()) {
3706        /* XXX DECODE_PRINTF may be changed to something more
3707           general, so that it is important to leave the strings
3708           in the same format, even though the result is that the
3709           above test is done twice. */
3710        switch (rh) {
3711        case 0:
3712            DECODE_PRINTF("ROL\t");
3713            break;
3714        case 1:
3715            DECODE_PRINTF("ROR\t");
3716            break;
3717        case 2:
3718            DECODE_PRINTF("RCL\t");
3719            break;
3720        case 3:
3721            DECODE_PRINTF("RCR\t");
3722            break;
3723        case 4:
3724            DECODE_PRINTF("SHL\t");
3725            break;
3726        case 5:
3727            DECODE_PRINTF("SHR\t");
3728            break;
3729        case 6:
3730            DECODE_PRINTF("SAL\t");
3731            break;
3732        case 7:
3733            DECODE_PRINTF("SAR\t");
3734            break;
3735        }
3736    }
3737#endif
3738    /* know operation, decode the mod byte to find the addressing
3739       mode. */
3740    if (mod < 3) {
3741        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3742            u32 destval;
3743
3744            DECODE_PRINTF("DWORD PTR ");
3745            destoffset = decode_rmXX_address(mod, rl);
3746            DECODE_PRINTF(",1\n");
3747            destval = fetch_data_long(destoffset);
3748            TRACE_AND_STEP();
3749            destval = (*opcD1_long_operation[rh]) (destval, 1);
3750            store_data_long(destoffset, destval);
3751        } else {
3752            u16 destval;
3753
3754            DECODE_PRINTF("WORD PTR ");
3755            destoffset = decode_rmXX_address(mod, rl);
3756            DECODE_PRINTF(",1\n");
3757            destval = fetch_data_word(destoffset);
3758            TRACE_AND_STEP();
3759            destval = (*opcD1_word_operation[rh]) (destval, 1);
3760            store_data_word(destoffset, destval);
3761        }
3762    } else {                     /* register to register */
3763        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3764                        u32 destval;
3765                        u32 *destreg;
3766
3767            destreg = DECODE_RM_LONG_REGISTER(rl);
3768            DECODE_PRINTF(",1\n");
3769            TRACE_AND_STEP();
3770            destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3771            *destreg = destval;
3772        } else {
3773                        u16 destval;
3774                        u16 *destreg;
3775
3776            destreg = DECODE_RM_WORD_REGISTER(rl);
3777            DECODE_PRINTF(",1\n");
3778            TRACE_AND_STEP();
3779            destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3780            *destreg = destval;
3781        }
3782    }
3783    DECODE_CLEAR_SEGOVR();
3784    END_OF_INSTR();
3785}
3786
3787/****************************************************************************
3788REMARKS:
3789Handles opcode 0xd2
3790****************************************************************************/
3791void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3792{
3793    int mod, rl, rh;
3794    u8 *destreg;
3795    uint destoffset;
3796    u8 destval;
3797    u8 amt;
3798
3799    /*
3800     * Yet another weirdo special case instruction format.  Part of
3801     * the opcode held below in "RH".  Doubly nested case would
3802     * result, except that the decoded instruction
3803     */
3804    START_OF_INSTR();
3805    FETCH_DECODE_MODRM(mod, rh, rl);
3806#ifdef CONFIG_X86EMU_DEBUG
3807    if (DEBUG_DECODE()) {
3808        /* XXX DECODE_PRINTF may be changed to something more
3809           general, so that it is important to leave the strings
3810           in the same format, even though the result is that the
3811           above test is done twice. */
3812        switch (rh) {
3813        case 0:
3814            DECODE_PRINTF("ROL\t");
3815            break;
3816        case 1:
3817            DECODE_PRINTF("ROR\t");
3818            break;
3819        case 2:
3820            DECODE_PRINTF("RCL\t");
3821            break;
3822        case 3:
3823            DECODE_PRINTF("RCR\t");
3824            break;
3825        case 4:
3826            DECODE_PRINTF("SHL\t");
3827            break;
3828        case 5:
3829            DECODE_PRINTF("SHR\t");
3830            break;
3831        case 6:
3832            DECODE_PRINTF("SAL\t");
3833            break;
3834        case 7:
3835            DECODE_PRINTF("SAR\t");
3836            break;
3837        }
3838    }
3839#endif
3840    /* know operation, decode the mod byte to find the addressing
3841       mode. */
3842    amt = M.x86.R_CL;
3843    if (mod < 3) {
3844        DECODE_PRINTF("BYTE PTR ");
3845        destoffset = decode_rmXX_address(mod, rl);
3846        DECODE_PRINTF(",CL\n");
3847        destval = fetch_data_byte(destoffset);
3848        TRACE_AND_STEP();
3849        destval = (*opcD0_byte_operation[rh]) (destval, amt);
3850        store_data_byte(destoffset, destval);
3851    } else {                     /* register to register */
3852        destreg = DECODE_RM_BYTE_REGISTER(rl);
3853        DECODE_PRINTF(",CL\n");
3854        TRACE_AND_STEP();
3855        destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3856        *destreg = destval;
3857    }
3858    DECODE_CLEAR_SEGOVR();
3859    END_OF_INSTR();
3860}
3861
3862/****************************************************************************
3863REMARKS:
3864Handles opcode 0xd3
3865****************************************************************************/
3866void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3867{
3868    int mod, rl, rh;
3869    uint destoffset;
3870    u8 amt;
3871
3872    /*
3873     * Yet another weirdo special case instruction format.  Part of
3874     * the opcode held below in "RH".  Doubly nested case would
3875     * result, except that the decoded instruction
3876     */
3877    START_OF_INSTR();
3878    FETCH_DECODE_MODRM(mod, rh, rl);
3879#ifdef CONFIG_X86EMU_DEBUG
3880    if (DEBUG_DECODE()) {
3881        /* XXX DECODE_PRINTF may be changed to something more
3882           general, so that it is important to leave the strings
3883           in the same format, even though the result is that the
3884           above test is done twice. */
3885        switch (rh) {
3886        case 0:
3887            DECODE_PRINTF("ROL\t");
3888            break;
3889        case 1:
3890            DECODE_PRINTF("ROR\t");
3891            break;
3892        case 2:
3893            DECODE_PRINTF("RCL\t");
3894            break;
3895        case 3:
3896            DECODE_PRINTF("RCR\t");
3897            break;
3898        case 4:
3899            DECODE_PRINTF("SHL\t");
3900            break;
3901        case 5:
3902            DECODE_PRINTF("SHR\t");
3903            break;
3904        case 6:
3905            DECODE_PRINTF("SAL\t");
3906            break;
3907        case 7:
3908            DECODE_PRINTF("SAR\t");
3909            break;
3910        }
3911    }
3912#endif
3913    /* know operation, decode the mod byte to find the addressing
3914       mode. */
3915    amt = M.x86.R_CL;
3916    if (mod < 3) {
3917        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3918            u32 destval;
3919
3920            DECODE_PRINTF("DWORD PTR ");
3921            destoffset = decode_rmXX_address(mod, rl);
3922            DECODE_PRINTF(",CL\n");
3923            destval = fetch_data_long(destoffset);
3924            TRACE_AND_STEP();
3925            destval = (*opcD1_long_operation[rh]) (destval, amt);
3926            store_data_long(destoffset, destval);
3927        } else {
3928            u16 destval;
3929
3930            DECODE_PRINTF("WORD PTR ");
3931            destoffset = decode_rmXX_address(mod, rl);
3932            DECODE_PRINTF(",CL\n");
3933            destval = fetch_data_word(destoffset);
3934            TRACE_AND_STEP();
3935            destval = (*opcD1_word_operation[rh]) (destval, amt);
3936            store_data_word(destoffset, destval);
3937        }
3938    } else {                     /* register to register */
3939        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3940            u32 *destreg;
3941
3942            destreg = DECODE_RM_LONG_REGISTER(rl);
3943            DECODE_PRINTF(",CL\n");
3944            TRACE_AND_STEP();
3945            *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3946        } else {
3947            u16 *destreg;
3948
3949            destreg = DECODE_RM_WORD_REGISTER(rl);
3950            DECODE_PRINTF(",CL\n");
3951            TRACE_AND_STEP();
3952            *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3953        }
3954    }
3955    DECODE_CLEAR_SEGOVR();
3956    END_OF_INSTR();
3957}
3958
3959/****************************************************************************
3960REMARKS:
3961Handles opcode 0xd4
3962****************************************************************************/
3963void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3964{
3965    u8 a;
3966
3967    START_OF_INSTR();
3968    DECODE_PRINTF("AAM\n");
3969    a = fetch_byte_imm();      /* this is a stupid encoding. */
3970    if (a != 10) {
3971        ERR_PRINTF("ERROR DECODING AAM\n");
3972        TRACE_REGS();
3973        HALT_SYS();
3974    }
3975    TRACE_AND_STEP();
3976    /* note the type change here --- returning AL and AH in AX. */
3977    M.x86.R_AX = aam_word(M.x86.R_AL);
3978    DECODE_CLEAR_SEGOVR();
3979    END_OF_INSTR();
3980}
3981
3982/****************************************************************************
3983REMARKS:
3984Handles opcode 0xd5
3985****************************************************************************/
3986void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3987{
3988    START_OF_INSTR();
3989    DECODE_PRINTF("AAD\n");
3990    (void)fetch_byte_imm();
3991    TRACE_AND_STEP();
3992    M.x86.R_AX = aad_word(M.x86.R_AX);
3993    DECODE_CLEAR_SEGOVR();
3994    END_OF_INSTR();
3995}
3996
3997/* opcode 0xd6 ILLEGAL OPCODE */
3998
3999/****************************************************************************
4000REMARKS:
4001Handles opcode 0xd7
4002****************************************************************************/
4003void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4004{
4005    u16 addr;
4006
4007    START_OF_INSTR();
4008    DECODE_PRINTF("XLAT\n");
4009    TRACE_AND_STEP();
4010        addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4011    M.x86.R_AL = fetch_data_byte(addr);
4012    DECODE_CLEAR_SEGOVR();
4013    END_OF_INSTR();
4014}
4015
4016/* instuctions  D8 .. DF are in i87_ops.c */
4017
4018/****************************************************************************
4019REMARKS:
4020Handles opcode 0xe0
4021****************************************************************************/
4022void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4023{
4024    s16 ip;
4025
4026    START_OF_INSTR();
4027    DECODE_PRINTF("LOOPNE\t");
4028    ip = (s8) fetch_byte_imm();
4029    ip += (s16) M.x86.R_IP;
4030    DECODE_PRINTF2("%04x\n", ip);
4031    TRACE_AND_STEP();
4032    M.x86.R_CX -= 1;
4033    if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))      /* CX != 0 and !ZF */
4034        M.x86.R_IP = ip;
4035    DECODE_CLEAR_SEGOVR();
4036    END_OF_INSTR();
4037}
4038
4039/****************************************************************************
4040REMARKS:
4041Handles opcode 0xe1
4042****************************************************************************/
4043void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4044{
4045    s16 ip;
4046
4047    START_OF_INSTR();
4048    DECODE_PRINTF("LOOPE\t");
4049    ip = (s8) fetch_byte_imm();
4050    ip += (s16) M.x86.R_IP;
4051    DECODE_PRINTF2("%04x\n", ip);
4052    TRACE_AND_STEP();
4053    M.x86.R_CX -= 1;
4054    if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF))       /* CX != 0 and ZF */
4055        M.x86.R_IP = ip;
4056    DECODE_CLEAR_SEGOVR();
4057    END_OF_INSTR();
4058}
4059
4060/****************************************************************************
4061REMARKS:
4062Handles opcode 0xe2
4063****************************************************************************/
4064void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4065{
4066    s16 ip;
4067
4068    START_OF_INSTR();
4069    DECODE_PRINTF("LOOP\t");
4070    ip = (s8) fetch_byte_imm();
4071    ip += (s16) M.x86.R_IP;
4072    DECODE_PRINTF2("%04x\n", ip);
4073    TRACE_AND_STEP();
4074    M.x86.R_CX -= 1;
4075    if (M.x86.R_CX != 0)
4076        M.x86.R_IP = ip;
4077    DECODE_CLEAR_SEGOVR();
4078    END_OF_INSTR();
4079}
4080
4081/****************************************************************************
4082REMARKS:
4083Handles opcode 0xe3
4084****************************************************************************/
4085void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4086{
4087    u16 target;
4088    s8  offset;
4089
4090    /* jump to byte offset if overflow flag is set */
4091    START_OF_INSTR();
4092    DECODE_PRINTF("JCXZ\t");
4093    offset = (s8)fetch_byte_imm();
4094    target = (u16)(M.x86.R_IP + offset);
4095    DECODE_PRINTF2("%x\n", target);
4096    TRACE_AND_STEP();
4097    if (M.x86.R_CX == 0)
4098        M.x86.R_IP = target;
4099    DECODE_CLEAR_SEGOVR();
4100    END_OF_INSTR();
4101}
4102
4103/****************************************************************************
4104REMARKS:
4105Handles opcode 0xe4
4106****************************************************************************/
4107void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4108{
4109    u8 port;
4110
4111    START_OF_INSTR();
4112    DECODE_PRINTF("IN\t");
4113        port = (u8) fetch_byte_imm();
4114    DECODE_PRINTF2("%x,AL\n", port);
4115    TRACE_AND_STEP();
4116    M.x86.R_AL = (*sys_inb)(port);
4117    DECODE_CLEAR_SEGOVR();
4118    END_OF_INSTR();
4119}
4120
4121/****************************************************************************
4122REMARKS:
4123Handles opcode 0xe5
4124****************************************************************************/
4125void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4126{
4127    u8 port;
4128
4129    START_OF_INSTR();
4130    DECODE_PRINTF("IN\t");
4131        port = (u8) fetch_byte_imm();
4132    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4133        DECODE_PRINTF2("EAX,%x\n", port);
4134    } else {
4135        DECODE_PRINTF2("AX,%x\n", port);
4136    }
4137    TRACE_AND_STEP();
4138    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4139        M.x86.R_EAX = (*sys_inl)(port);
4140    } else {
4141        M.x86.R_AX = (*sys_inw)(port);
4142    }
4143    DECODE_CLEAR_SEGOVR();
4144    END_OF_INSTR();
4145}
4146
4147/****************************************************************************
4148REMARKS:
4149Handles opcode 0xe6
4150****************************************************************************/
4151void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4152{
4153    u8 port;
4154
4155    START_OF_INSTR();
4156    DECODE_PRINTF("OUT\t");
4157        port = (u8) fetch_byte_imm();
4158    DECODE_PRINTF2("%x,AL\n", port);
4159    TRACE_AND_STEP();
4160    (*sys_outb)(port, M.x86.R_AL);
4161    DECODE_CLEAR_SEGOVR();
4162    END_OF_INSTR();
4163}
4164
4165/****************************************************************************
4166REMARKS:
4167Handles opcode 0xe7
4168****************************************************************************/
4169void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4170{
4171    u8 port;
4172
4173    START_OF_INSTR();
4174    DECODE_PRINTF("OUT\t");
4175        port = (u8) fetch_byte_imm();
4176    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4177        DECODE_PRINTF2("%x,EAX\n", port);
4178    } else {
4179        DECODE_PRINTF2("%x,AX\n", port);
4180    }
4181    TRACE_AND_STEP();
4182    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4183        (*sys_outl)(port, M.x86.R_EAX);
4184    } else {
4185        (*sys_outw)(port, M.x86.R_AX);
4186    }
4187    DECODE_CLEAR_SEGOVR();
4188    END_OF_INSTR();
4189}
4190
4191/****************************************************************************
4192REMARKS:
4193Handles opcode 0xe8
4194****************************************************************************/
4195void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4196{
4197    s16 ip;
4198
4199    START_OF_INSTR();
4200        DECODE_PRINTF("CALL\t");
4201        ip = (s16) fetch_word_imm();
4202        ip += (s16) M.x86.R_IP;    /* CHECK SIGN */
4203        DECODE_PRINTF2("%04x\n", ip);
4204        CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4205    TRACE_AND_STEP();
4206    push_word(M.x86.R_IP);
4207    M.x86.R_IP = ip;
4208    DECODE_CLEAR_SEGOVR();
4209    END_OF_INSTR();
4210}
4211
4212/****************************************************************************
4213REMARKS:
4214Handles opcode 0xe9
4215****************************************************************************/
4216void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4217{
4218    int ip;
4219
4220    START_OF_INSTR();
4221    DECODE_PRINTF("JMP\t");
4222    ip = (s16)fetch_word_imm();
4223    ip += (s16)M.x86.R_IP;
4224    DECODE_PRINTF2("%04x\n", ip);
4225    TRACE_AND_STEP();
4226    M.x86.R_IP = (u16)ip;
4227    DECODE_CLEAR_SEGOVR();
4228    END_OF_INSTR();
4229}
4230
4231/****************************************************************************
4232REMARKS:
4233Handles opcode 0xea
4234****************************************************************************/
4235void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4236{
4237    u16 cs, ip;
4238
4239    START_OF_INSTR();
4240    DECODE_PRINTF("JMP\tFAR ");
4241    ip = fetch_word_imm();
4242    cs = fetch_word_imm();
4243    DECODE_PRINTF2("%04x:", cs);
4244    DECODE_PRINTF2("%04x\n", ip);
4245    TRACE_AND_STEP();
4246    M.x86.R_IP = ip;
4247    M.x86.R_CS = cs;
4248    DECODE_CLEAR_SEGOVR();
4249    END_OF_INSTR();
4250}
4251
4252/****************************************************************************
4253REMARKS:
4254Handles opcode 0xeb
4255****************************************************************************/
4256void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4257{
4258    u16 target;
4259    s8 offset;
4260
4261    START_OF_INSTR();
4262    DECODE_PRINTF("JMP\t");
4263    offset = (s8)fetch_byte_imm();
4264    target = (u16)(M.x86.R_IP + offset);
4265    DECODE_PRINTF2("%x\n", target);
4266    TRACE_AND_STEP();
4267    M.x86.R_IP = target;
4268    DECODE_CLEAR_SEGOVR();
4269    END_OF_INSTR();
4270}
4271
4272/****************************************************************************
4273REMARKS:
4274Handles opcode 0xec
4275****************************************************************************/
4276void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4277{
4278    START_OF_INSTR();
4279    DECODE_PRINTF("IN\tAL,DX\n");
4280    TRACE_AND_STEP();
4281    M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4282    DECODE_CLEAR_SEGOVR();
4283    END_OF_INSTR();
4284}
4285
4286/****************************************************************************
4287REMARKS:
4288Handles opcode 0xed
4289****************************************************************************/
4290void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4291{
4292    START_OF_INSTR();
4293    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4294        DECODE_PRINTF("IN\tEAX,DX\n");
4295    } else {
4296        DECODE_PRINTF("IN\tAX,DX\n");
4297    }
4298    TRACE_AND_STEP();
4299    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4300        M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4301    } else {
4302        M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4303    }
4304    DECODE_CLEAR_SEGOVR();
4305    END_OF_INSTR();
4306}
4307
4308/****************************************************************************
4309REMARKS:
4310Handles opcode 0xee
4311****************************************************************************/
4312void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4313{
4314    START_OF_INSTR();
4315    DECODE_PRINTF("OUT\tDX,AL\n");
4316    TRACE_AND_STEP();
4317    (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4318    DECODE_CLEAR_SEGOVR();
4319    END_OF_INSTR();
4320}
4321
4322/****************************************************************************
4323REMARKS:
4324Handles opcode 0xef
4325****************************************************************************/
4326void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4327{
4328    START_OF_INSTR();
4329    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4330        DECODE_PRINTF("OUT\tDX,EAX\n");
4331    } else {
4332        DECODE_PRINTF("OUT\tDX,AX\n");
4333    }
4334    TRACE_AND_STEP();
4335    if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4336        (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4337    } else {
4338        (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4339    }
4340    DECODE_CLEAR_SEGOVR();
4341    END_OF_INSTR();
4342}
4343
4344/****************************************************************************
4345REMARKS:
4346Handles opcode 0xf0
4347****************************************************************************/
4348void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4349{
4350    START_OF_INSTR();
4351    DECODE_PRINTF("LOCK:\n");
4352    TRACE_AND_STEP();
4353    DECODE_CLEAR_SEGOVR();
4354    END_OF_INSTR();
4355}
4356
4357/*opcode 0xf1 ILLEGAL OPERATION */
4358
4359/****************************************************************************
4360REMARKS:
4361Handles opcode 0xf2
4362****************************************************************************/
4363void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4364{
4365    START_OF_INSTR();
4366    DECODE_PRINTF("REPNE\n");
4367    TRACE_AND_STEP();
4368    M.x86.mode |= SYSMODE_PREFIX_REPNE;
4369    DECODE_CLEAR_SEGOVR();
4370    END_OF_INSTR();
4371}
4372
4373/****************************************************************************
4374REMARKS:
4375Handles opcode 0xf3
4376****************************************************************************/
4377void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4378{
4379    START_OF_INSTR();
4380    DECODE_PRINTF("REPE\n");
4381    TRACE_AND_STEP();
4382    M.x86.mode |= SYSMODE_PREFIX_REPE;
4383    DECODE_CLEAR_SEGOVR();
4384    END_OF_INSTR();
4385}
4386
4387/****************************************************************************
4388REMARKS:
4389Handles opcode 0xf4
4390****************************************************************************/
4391void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4392{
4393    START_OF_INSTR();
4394    DECODE_PRINTF("HALT\n");
4395    TRACE_AND_STEP();
4396    HALT_SYS();
4397    DECODE_CLEAR_SEGOVR();
4398    END_OF_INSTR();
4399}
4400
4401/****************************************************************************
4402REMARKS:
4403Handles opcode 0xf5
4404****************************************************************************/
4405void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4406{
4407    /* complement the carry flag. */
4408    START_OF_INSTR();
4409    DECODE_PRINTF("CMC\n");
4410    TRACE_AND_STEP();
4411    TOGGLE_FLAG(F_CF);
4412    DECODE_CLEAR_SEGOVR();
4413    END_OF_INSTR();
4414}
4415
4416/****************************************************************************
4417REMARKS:
4418Handles opcode 0xf6
4419****************************************************************************/
4420void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4421{
4422    int mod, rl, rh;
4423    u8 *destreg;
4424    uint destoffset;
4425    u8 destval, srcval;
4426
4427    /* long, drawn out code follows.  Double switch for a total
4428       of 32 cases.  */
4429    START_OF_INSTR();
4430    FETCH_DECODE_MODRM(mod, rh, rl);
4431    DECODE_PRINTF(opF6_names[rh]);
4432    if (mod < 3) {
4433        DECODE_PRINTF("BYTE PTR ");
4434        destoffset = decode_rmXX_address(mod, rl);
4435        destval = fetch_data_byte(destoffset);
4436
4437        switch (rh) {
4438        case 0:         /* test byte imm */
4439            DECODE_PRINTF(",");
4440            srcval = fetch_byte_imm();
4441            DECODE_PRINTF2("%02x\n", srcval);
4442            TRACE_AND_STEP();
4443            test_byte(destval, srcval);
4444            break;
4445        case 1:
4446            ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4447            HALT_SYS();
4448            break;
4449        case 2:
4450            DECODE_PRINTF("\n");
4451            TRACE_AND_STEP();
4452            destval = not_byte(destval);
4453            store_data_byte(destoffset, destval);
4454            break;
4455        case 3:
4456            DECODE_PRINTF("\n");
4457            TRACE_AND_STEP();
4458            destval = neg_byte(destval);
4459            store_data_byte(destoffset, destval);
4460            break;
4461        case 4:
4462            DECODE_PRINTF("\n");
4463            TRACE_AND_STEP();
4464            mul_byte(destval);
4465            break;
4466        case 5:
4467            DECODE_PRINTF("\n");
4468            TRACE_AND_STEP();
4469            imul_byte(destval);
4470            break;
4471        case 6:
4472            DECODE_PRINTF("\n");
4473            TRACE_AND_STEP();
4474            div_byte(destval);
4475            break;
4476        default:
4477            DECODE_PRINTF("\n");
4478            TRACE_AND_STEP();
4479            idiv_byte(destval);
4480            break;
4481        }
4482    } else {                     /* mod=11 */
4483        destreg = DECODE_RM_BYTE_REGISTER(rl);
4484        switch (rh) {
4485        case 0:         /* test byte imm */
4486            DECODE_PRINTF(",");
4487            srcval = fetch_byte_imm();
4488            DECODE_PRINTF2("%02x\n", srcval);
4489            TRACE_AND_STEP();
4490            test_byte(*destreg, srcval);
4491            break;
4492        case 1:
4493            ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4494            HALT_SYS();
4495            break;
4496        case 2:
4497            DECODE_PRINTF("\n");
4498            TRACE_AND_STEP();
4499            *destreg = not_byte(*destreg);
4500            break;
4501        case 3:
4502            DECODE_PRINTF("\n");
4503            TRACE_AND_STEP();
4504            *destreg = neg_byte(*destreg);
4505            break;
4506        case 4:
4507            DECODE_PRINTF("\n");
4508            TRACE_AND_STEP();
4509            mul_byte(*destreg);      /*!!!  */
4510            break;
4511        case 5:
4512            DECODE_PRINTF("\n");
4513            TRACE_AND_STEP();
4514            imul_byte(*destreg);
4515            break;
4516        case 6:
4517            DECODE_PRINTF("\n");
4518            TRACE_AND_STEP();
4519            div_byte(*destreg);
4520            break;
4521        default:
4522            DECODE_PRINTF("\n");
4523            TRACE_AND_STEP();
4524            idiv_byte(*destreg);
4525            break;
4526        }
4527    }
4528    DECODE_CLEAR_SEGOVR();
4529    END_OF_INSTR();
4530}
4531
4532/****************************************************************************
4533REMARKS:
4534Handles opcode 0xf7
4535****************************************************************************/
4536void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4537{
4538    int mod, rl, rh;
4539    uint destoffset;
4540
4541    START_OF_INSTR();
4542    FETCH_DECODE_MODRM(mod, rh, rl);
4543    DECODE_PRINTF(opF6_names[rh]);
4544    if (mod < 3) {
4545
4546        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4547            u32 destval, srcval;
4548
4549            DECODE_PRINTF("DWORD PTR ");
4550            destoffset = decode_rmXX_address(mod, rl);
4551            destval = fetch_data_long(destoffset);
4552
4553            switch (rh) {
4554            case 0:
4555                DECODE_PRINTF(",");
4556                srcval = fetch_long_imm();
4557                DECODE_PRINTF2("%x\n", srcval);
4558                TRACE_AND_STEP();
4559                test_long(destval, srcval);
4560                break;
4561            case 1:
4562                ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4563                HALT_SYS();
4564                break;
4565            case 2:
4566                DECODE_PRINTF("\n");
4567                TRACE_AND_STEP();
4568                destval = not_long(destval);
4569                store_data_long(destoffset, destval);
4570                break;
4571            case 3:
4572                DECODE_PRINTF("\n");
4573                TRACE_AND_STEP();
4574                destval = neg_long(destval);
4575                store_data_long(destoffset, destval);
4576                break;
4577            case 4:
4578                DECODE_PRINTF("\n");
4579                TRACE_AND_STEP();
4580                mul_long(destval);
4581                break;
4582            case 5:
4583                DECODE_PRINTF("\n");
4584                TRACE_AND_STEP();
4585                imul_long(destval);
4586                break;
4587            case 6:
4588                DECODE_PRINTF("\n");
4589                TRACE_AND_STEP();
4590                div_long(destval);
4591                break;
4592            case 7:
4593                DECODE_PRINTF("\n");
4594                TRACE_AND_STEP();
4595                idiv_long(destval);
4596                break;
4597            }
4598        } else {
4599            u16 destval, srcval;
4600
4601            DECODE_PRINTF("WORD PTR ");
4602            destoffset = decode_rmXX_address(mod, rl);
4603            destval = fetch_data_word(destoffset);
4604
4605            switch (rh) {
4606            case 0:         /* test word imm */
4607                DECODE_PRINTF(",");
4608                srcval = fetch_word_imm();
4609                DECODE_PRINTF2("%x\n", srcval);
4610                TRACE_AND_STEP();
4611                test_word(destval, srcval);
4612                break;
4613            case 1:
4614                ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4615                HALT_SYS();
4616                break;
4617            case 2:
4618                DECODE_PRINTF("\n");
4619                TRACE_AND_STEP();
4620                destval = not_word(destval);
4621                store_data_word(destoffset, destval);
4622                break;
4623            case 3:
4624                DECODE_PRINTF("\n");
4625                TRACE_AND_STEP();
4626                destval = neg_word(destval);
4627                store_data_word(destoffset, destval);
4628                break;
4629            case 4:
4630                DECODE_PRINTF("\n");
4631                TRACE_AND_STEP();
4632                mul_word(destval);
4633                break;
4634            case 5:
4635                DECODE_PRINTF("\n");
4636                TRACE_AND_STEP();
4637                imul_word(destval);
4638                break;
4639            case 6:
4640                DECODE_PRINTF("\n");
4641                TRACE_AND_STEP();
4642                div_word(destval);
4643                break;
4644            case 7:
4645                DECODE_PRINTF("\n");
4646                TRACE_AND_STEP();
4647                idiv_word(destval);
4648                break;
4649            }
4650        }
4651
4652    } else {                     /* mod=11 */
4653
4654        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4655            u32 *destreg;
4656            u32 srcval;
4657
4658            destreg = DECODE_RM_LONG_REGISTER(rl);
4659
4660            switch (rh) {
4661            case 0:         /* test word imm */
4662                DECODE_PRINTF(",");
4663                srcval = fetch_long_imm();
4664                DECODE_PRINTF2("%x\n", srcval);
4665                TRACE_AND_STEP();
4666                test_long(*destreg, srcval);
4667                break;
4668            case 1:
4669                ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4670                HALT_SYS();
4671                break;
4672            case 2:
4673                DECODE_PRINTF("\n");
4674                TRACE_AND_STEP();
4675                *destreg = not_long(*destreg);
4676                break;
4677            case 3:
4678                DECODE_PRINTF("\n");
4679                TRACE_AND_STEP();
4680                *destreg = neg_long(*destreg);
4681                break;
4682            case 4:
4683                DECODE_PRINTF("\n");
4684                TRACE_AND_STEP();
4685                mul_long(*destreg);      /*!!!  */
4686                break;
4687            case 5:
4688                DECODE_PRINTF("\n");
4689                TRACE_AND_STEP();
4690                imul_long(*destreg);
4691                break;
4692            case 6:
4693                DECODE_PRINTF("\n");
4694                TRACE_AND_STEP();
4695                div_long(*destreg);
4696                break;
4697            case 7:
4698                DECODE_PRINTF("\n");
4699                TRACE_AND_STEP();
4700                idiv_long(*destreg);
4701                break;
4702            }
4703        } else {
4704            u16 *destreg;
4705            u16 srcval;
4706
4707            destreg = DECODE_RM_WORD_REGISTER(rl);
4708
4709            switch (rh) {
4710            case 0:         /* test word imm */
4711                DECODE_PRINTF(",");
4712                srcval = fetch_word_imm();
4713                DECODE_PRINTF2("%x\n", srcval);
4714                TRACE_AND_STEP();
4715                test_word(*destreg, srcval);
4716                break;
4717            case 1:
4718                ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4719                HALT_SYS();
4720                break;
4721            case 2:
4722                DECODE_PRINTF("\n");
4723                TRACE_AND_STEP();
4724                *destreg = not_word(*destreg);
4725                break;
4726            case 3:
4727                DECODE_PRINTF("\n");
4728                TRACE_AND_STEP();
4729                *destreg = neg_word(*destreg);
4730                break;
4731            case 4:
4732                DECODE_PRINTF("\n");
4733                TRACE_AND_STEP();
4734                mul_word(*destreg);      /*!!!  */
4735                break;
4736            case 5:
4737                DECODE_PRINTF("\n");
4738                TRACE_AND_STEP();
4739                imul_word(*destreg);
4740                break;
4741            case 6:
4742                DECODE_PRINTF("\n");
4743                TRACE_AND_STEP();
4744                div_word(*destreg);
4745                break;
4746            case 7:
4747                DECODE_PRINTF("\n");
4748                TRACE_AND_STEP();
4749                idiv_word(*destreg);
4750                break;
4751            }
4752        }
4753    }
4754    DECODE_CLEAR_SEGOVR();
4755    END_OF_INSTR();
4756}
4757
4758/****************************************************************************
4759REMARKS:
4760Handles opcode 0xf8
4761****************************************************************************/
4762void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4763{
4764    /* clear the carry flag. */
4765    START_OF_INSTR();
4766    DECODE_PRINTF("CLC\n");
4767    TRACE_AND_STEP();
4768    CLEAR_FLAG(F_CF);
4769    DECODE_CLEAR_SEGOVR();
4770    END_OF_INSTR();
4771}
4772
4773/****************************************************************************
4774REMARKS:
4775Handles opcode 0xf9
4776****************************************************************************/
4777void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4778{
4779    /* set the carry flag. */
4780    START_OF_INSTR();
4781    DECODE_PRINTF("STC\n");
4782    TRACE_AND_STEP();
4783    SET_FLAG(F_CF);
4784    DECODE_CLEAR_SEGOVR();
4785    END_OF_INSTR();
4786}
4787
4788/****************************************************************************
4789REMARKS:
4790Handles opcode 0xfa
4791****************************************************************************/
4792void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4793{
4794    /* clear interrupts. */
4795    START_OF_INSTR();
4796    DECODE_PRINTF("CLI\n");
4797    TRACE_AND_STEP();
4798    CLEAR_FLAG(F_IF);
4799    DECODE_CLEAR_SEGOVR();
4800    END_OF_INSTR();
4801}
4802
4803/****************************************************************************
4804REMARKS:
4805Handles opcode 0xfb
4806****************************************************************************/
4807void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4808{
4809    /* enable  interrupts. */
4810    START_OF_INSTR();
4811    DECODE_PRINTF("STI\n");
4812    TRACE_AND_STEP();
4813    SET_FLAG(F_IF);
4814    DECODE_CLEAR_SEGOVR();
4815    END_OF_INSTR();
4816}
4817
4818/****************************************************************************
4819REMARKS:
4820Handles opcode 0xfc
4821****************************************************************************/
4822void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4823{
4824    /* clear interrupts. */
4825    START_OF_INSTR();
4826    DECODE_PRINTF("CLD\n");
4827    TRACE_AND_STEP();
4828    CLEAR_FLAG(F_DF);
4829    DECODE_CLEAR_SEGOVR();
4830    END_OF_INSTR();
4831}
4832
4833/****************************************************************************
4834REMARKS:
4835Handles opcode 0xfd
4836****************************************************************************/
4837void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4838{
4839    /* clear interrupts. */
4840    START_OF_INSTR();
4841    DECODE_PRINTF("STD\n");
4842    TRACE_AND_STEP();
4843    SET_FLAG(F_DF);
4844    DECODE_CLEAR_SEGOVR();
4845    END_OF_INSTR();
4846}
4847
4848/****************************************************************************
4849REMARKS:
4850Handles opcode 0xfe
4851****************************************************************************/
4852void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4853{
4854    int mod, rh, rl;
4855    u8 destval;
4856    uint destoffset;
4857    u8 *destreg;
4858
4859    /* Yet another special case instruction. */
4860    START_OF_INSTR();
4861    FETCH_DECODE_MODRM(mod, rh, rl);
4862#ifdef CONFIG_X86EMU_DEBUG
4863    if (DEBUG_DECODE()) {
4864        /* XXX DECODE_PRINTF may be changed to something more
4865           general, so that it is important to leave the strings
4866           in the same format, even though the result is that the
4867           above test is done twice. */
4868
4869        switch (rh) {
4870        case 0:
4871            DECODE_PRINTF("INC\t");
4872            break;
4873        case 1:
4874            DECODE_PRINTF("DEC\t");
4875            break;
4876        case 2:
4877        case 3:
4878        case 4:
4879        case 5:
4880        case 6:
4881        case 7:
4882            ERR_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x\n", mod);
4883            HALT_SYS();
4884            break;
4885        }
4886    }
4887#endif
4888    if (mod < 3) {
4889        DECODE_PRINTF("BYTE PTR ");
4890        destoffset = decode_rmXX_address(mod, rl);
4891        DECODE_PRINTF("\n");
4892        destval = fetch_data_byte(destoffset);
4893        TRACE_AND_STEP();
4894        if (rh == 0)
4895          destval = inc_byte(destval);
4896        else
4897          destval = dec_byte(destval);
4898        store_data_byte(destoffset, destval);
4899    } else {
4900        destreg = DECODE_RM_BYTE_REGISTER(rl);
4901        DECODE_PRINTF("\n");
4902        TRACE_AND_STEP();
4903        if (rh == 0)
4904          *destreg = inc_byte(*destreg);
4905        else
4906          *destreg = dec_byte(*destreg);
4907    }
4908    DECODE_CLEAR_SEGOVR();
4909    END_OF_INSTR();
4910}
4911
4912/****************************************************************************
4913REMARKS:
4914Handles opcode 0xff
4915****************************************************************************/
4916void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4917{
4918    int mod, rh, rl;
4919    uint destoffset = 0;
4920        u16 *destreg;
4921        u16 destval,destval2;
4922
4923    /* Yet another special case instruction. */
4924    START_OF_INSTR();
4925    FETCH_DECODE_MODRM(mod, rh, rl);
4926#ifdef CONFIG_X86EMU_DEBUG
4927    if (DEBUG_DECODE()) {
4928        /* XXX DECODE_PRINTF may be changed to something more
4929           general, so that it is important to leave the strings
4930           in the same format, even though the result is that the
4931           above test is done twice. */
4932
4933        switch (rh) {
4934        case 0:
4935            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4936                DECODE_PRINTF("INC\tDWORD PTR ");
4937            } else {
4938                DECODE_PRINTF("INC\tWORD PTR ");
4939            }
4940            break;
4941        case 1:
4942            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4943                DECODE_PRINTF("DEC\tDWORD PTR ");
4944            } else {
4945                DECODE_PRINTF("DEC\tWORD PTR ");
4946            }
4947            break;
4948        case 2:
4949            DECODE_PRINTF("CALL\t ");
4950            break;
4951        case 3:
4952            DECODE_PRINTF("CALL\tFAR ");
4953            break;
4954        case 4:
4955            DECODE_PRINTF("JMP\t");
4956            break;
4957        case 5:
4958            DECODE_PRINTF("JMP\tFAR ");
4959            break;
4960        case 6:
4961            DECODE_PRINTF("PUSH\t");
4962            break;
4963        case 7:
4964            ERR_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4965            HALT_SYS();
4966            break;
4967        }
4968    }
4969#endif
4970    if (mod < 3) {
4971        destoffset = decode_rmXX_address(mod, rl);
4972        DECODE_PRINTF("\n");
4973        switch (rh) {
4974        case 0:         /* inc word ptr ... */
4975            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4976                u32 destval;
4977
4978                destval = fetch_data_long(destoffset);
4979                TRACE_AND_STEP();
4980                destval = inc_long(destval);
4981                store_data_long(destoffset, destval);
4982            } else {
4983                u16 destval;
4984
4985                destval = fetch_data_word(destoffset);
4986                TRACE_AND_STEP();
4987                destval = inc_word(destval);
4988                store_data_word(destoffset, destval);
4989            }
4990            break;
4991        case 1:         /* dec word ptr ... */
4992            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4993                u32 destval;
4994
4995                destval = fetch_data_long(destoffset);
4996                TRACE_AND_STEP();
4997                destval = dec_long(destval);
4998                store_data_long(destoffset, destval);
4999            } else {
5000                u16 destval;
5001
5002                destval = fetch_data_word(destoffset);
5003                TRACE_AND_STEP();
5004                destval = dec_word(destval);
5005                store_data_word(destoffset, destval);
5006            }
5007            break;
5008        case 2:         /* call word ptr ... */
5009            destval = fetch_data_word(destoffset);
5010            TRACE_AND_STEP();
5011            push_word(M.x86.R_IP);
5012            M.x86.R_IP = destval;
5013            break;
5014        case 3:         /* call far ptr ... */
5015            destval = fetch_data_word(destoffset);
5016            destval2 = fetch_data_word(destoffset + 2);
5017            TRACE_AND_STEP();
5018            push_word(M.x86.R_CS);
5019            M.x86.R_CS = destval2;
5020            push_word(M.x86.R_IP);
5021            M.x86.R_IP = destval;
5022            break;
5023        case 4:         /* jmp word ptr ... */
5024            destval = fetch_data_word(destoffset);
5025            TRACE_AND_STEP();
5026            M.x86.R_IP = destval;
5027            break;
5028        case 5:         /* jmp far ptr ... */
5029            destval = fetch_data_word(destoffset);
5030            destval2 = fetch_data_word(destoffset + 2);
5031            TRACE_AND_STEP();
5032            M.x86.R_IP = destval;
5033            M.x86.R_CS = destval2;
5034            break;
5035        case 6:         /*  push word ptr ... */
5036            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5037                u32 destval;
5038
5039                destval = fetch_data_long(destoffset);
5040                TRACE_AND_STEP();
5041                push_long(destval);
5042            } else {
5043                u16 destval;
5044
5045                destval = fetch_data_word(destoffset);
5046                TRACE_AND_STEP();
5047                push_word(destval);
5048            }
5049            break;
5050        }
5051    } else {
5052        switch (rh) {
5053        case 0:
5054            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5055                u32 *destreg;
5056
5057                destreg = DECODE_RM_LONG_REGISTER(rl);
5058                DECODE_PRINTF("\n");
5059                TRACE_AND_STEP();
5060                *destreg = inc_long(*destreg);
5061            } else {
5062                u16 *destreg;
5063
5064                destreg = DECODE_RM_WORD_REGISTER(rl);
5065                DECODE_PRINTF("\n");
5066                TRACE_AND_STEP();
5067                *destreg = inc_word(*destreg);
5068            }
5069            break;
5070        case 1:
5071            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5072                u32 *destreg;
5073
5074                destreg = DECODE_RM_LONG_REGISTER(rl);
5075                DECODE_PRINTF("\n");
5076                TRACE_AND_STEP();
5077                *destreg = dec_long(*destreg);
5078            } else {
5079                u16 *destreg;
5080
5081                destreg = DECODE_RM_WORD_REGISTER(rl);
5082                DECODE_PRINTF("\n");
5083                TRACE_AND_STEP();
5084                *destreg = dec_word(*destreg);
5085            }
5086            break;
5087        case 2:         /* call word ptr ... */
5088            destreg = DECODE_RM_WORD_REGISTER(rl);
5089            DECODE_PRINTF("\n");
5090            TRACE_AND_STEP();
5091            push_word(M.x86.R_IP);
5092            M.x86.R_IP = *destreg;
5093            break;
5094        case 3:         /* jmp far ptr ... */
5095            ERR_PRINTF("OPERATION UNDEFINED 0XFF\n");
5096            TRACE_AND_STEP();
5097            HALT_SYS();
5098            break;
5099
5100        case 4:         /* jmp  ... */
5101            destreg = DECODE_RM_WORD_REGISTER(rl);
5102            DECODE_PRINTF("\n");
5103            TRACE_AND_STEP();
5104            M.x86.R_IP = (u16) (*destreg);
5105            break;
5106        case 5:         /* jmp far ptr ... */
5107            ERR_PRINTF("OPERATION UNDEFINED 0XFF\n");
5108            TRACE_AND_STEP();
5109            HALT_SYS();
5110            break;
5111        case 6:
5112            if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5113                u32 *destreg;
5114
5115                destreg = DECODE_RM_LONG_REGISTER(rl);
5116                DECODE_PRINTF("\n");
5117                TRACE_AND_STEP();
5118                push_long(*destreg);
5119            } else {
5120                u16 *destreg;
5121
5122                destreg = DECODE_RM_WORD_REGISTER(rl);
5123                DECODE_PRINTF("\n");
5124                TRACE_AND_STEP();
5125                push_word(*destreg);
5126            }
5127            break;
5128        }
5129    }
5130    DECODE_CLEAR_SEGOVR();
5131    END_OF_INSTR();
5132}
5133
5134/***************************************************************************
5135 * Single byte operation code table:
5136 **************************************************************************/
5137void (*x86emu_optab[256])(u8) =
5138{
5139/*  0x00 */ x86emuOp_genop_byte_RM_R,
5140/*  0x01 */ x86emuOp_genop_word_RM_R,
5141/*  0x02 */ x86emuOp_genop_byte_R_RM,
5142/*  0x03 */ x86emuOp_genop_word_R_RM,
5143/*  0x04 */ x86emuOp_genop_byte_AL_IMM,
5144/*  0x05 */ x86emuOp_genop_word_AX_IMM,
5145/*  0x06 */ x86emuOp_push_ES,
5146/*  0x07 */ x86emuOp_pop_ES,
5147
5148/*  0x08 */ x86emuOp_genop_byte_RM_R,
5149/*  0x09 */ x86emuOp_genop_word_RM_R,
5150/*  0x0a */ x86emuOp_genop_byte_R_RM,
5151/*  0x0b */ x86emuOp_genop_word_R_RM,
5152/*  0x0c */ x86emuOp_genop_byte_AL_IMM,
5153/*  0x0d */ x86emuOp_genop_word_AX_IMM,
5154/*  0x0e */ x86emuOp_push_CS,
5155/*  0x0f */ x86emuOp_two_byte,
5156
5157/*  0x10 */ x86emuOp_genop_byte_RM_R,
5158/*  0x11 */ x86emuOp_genop_word_RM_R,
5159/*  0x12 */ x86emuOp_genop_byte_R_RM,
5160/*  0x13 */ x86emuOp_genop_word_R_RM,
5161/*  0x14 */ x86emuOp_genop_byte_AL_IMM,
5162/*  0x15 */ x86emuOp_genop_word_AX_IMM,
5163/*  0x16 */ x86emuOp_push_SS,
5164/*  0x17 */ x86emuOp_pop_SS,
5165
5166/*  0x18 */ x86emuOp_genop_byte_RM_R,
5167/*  0x19 */ x86emuOp_genop_word_RM_R,
5168/*  0x1a */ x86emuOp_genop_byte_R_RM,
5169/*  0x1b */ x86emuOp_genop_word_R_RM,
5170/*  0x1c */ x86emuOp_genop_byte_AL_IMM,
5171/*  0x1d */ x86emuOp_genop_word_AX_IMM,
5172/*  0x1e */ x86emuOp_push_DS,
5173/*  0x1f */ x86emuOp_pop_DS,
5174
5175/*  0x20 */ x86emuOp_genop_byte_RM_R,
5176/*  0x21 */ x86emuOp_genop_word_RM_R,
5177/*  0x22 */ x86emuOp_genop_byte_R_RM,
5178/*  0x23 */ x86emuOp_genop_word_R_RM,
5179/*  0x24 */ x86emuOp_genop_byte_AL_IMM,
5180/*  0x25 */ x86emuOp_genop_word_AX_IMM,
5181/*  0x26 */ x86emuOp_segovr_ES,
5182/*  0x27 */ x86emuOp_daa,
5183
5184/*  0x28 */ x86emuOp_genop_byte_RM_R,
5185/*  0x29 */ x86emuOp_genop_word_RM_R,
5186/*  0x2a */ x86emuOp_genop_byte_R_RM,
5187/*  0x2b */ x86emuOp_genop_word_R_RM,
5188/*  0x2c */ x86emuOp_genop_byte_AL_IMM,
5189/*  0x2d */ x86emuOp_genop_word_AX_IMM,
5190/*  0x2e */ x86emuOp_segovr_CS,
5191/*  0x2f */ x86emuOp_das,
5192
5193/*  0x30 */ x86emuOp_genop_byte_RM_R,
5194/*  0x31 */ x86emuOp_genop_word_RM_R,
5195/*  0x32 */ x86emuOp_genop_byte_R_RM,
5196/*  0x33 */ x86emuOp_genop_word_R_RM,
5197/*  0x34 */ x86emuOp_genop_byte_AL_IMM,
5198/*  0x35 */ x86emuOp_genop_word_AX_IMM,
5199/*  0x36 */ x86emuOp_segovr_SS,
5200/*  0x37 */ x86emuOp_aaa,
5201
5202/*  0x38 */ x86emuOp_genop_byte_RM_R,
5203/*  0x39 */ x86emuOp_genop_word_RM_R,
5204/*  0x3a */ x86emuOp_genop_byte_R_RM,
5205/*  0x3b */ x86emuOp_genop_word_R_RM,
5206/*  0x3c */ x86emuOp_genop_byte_AL_IMM,
5207/*  0x3d */ x86emuOp_genop_word_AX_IMM,
5208/*  0x3e */ x86emuOp_segovr_DS,
5209/*  0x3f */ x86emuOp_aas,
5210
5211/*  0x40 */ x86emuOp_inc_register,
5212/*  0x41 */ x86emuOp_inc_register,
5213/*  0x42 */ x86emuOp_inc_register,
5214/*  0x43 */ x86emuOp_inc_register,
5215/*  0x44 */ x86emuOp_inc_register,
5216/*  0x45 */ x86emuOp_inc_register,
5217/*  0x46 */ x86emuOp_inc_register,
5218/*  0x47 */ x86emuOp_inc_register,
5219
5220/*  0x48 */ x86emuOp_dec_register,
5221/*  0x49 */ x86emuOp_dec_register,
5222/*  0x4a */ x86emuOp_dec_register,
5223/*  0x4b */ x86emuOp_dec_register,
5224/*  0x4c */ x86emuOp_dec_register,
5225/*  0x4d */ x86emuOp_dec_register,
5226/*  0x4e */ x86emuOp_dec_register,
5227/*  0x4f */ x86emuOp_dec_register,
5228
5229/*  0x50 */ x86emuOp_push_register,
5230/*  0x51 */ x86emuOp_push_register,
5231/*  0x52 */ x86emuOp_push_register,
5232/*  0x53 */ x86emuOp_push_register,
5233/*  0x54 */ x86emuOp_push_register,
5234/*  0x55 */ x86emuOp_push_register,
5235/*  0x56 */ x86emuOp_push_register,
5236/*  0x57 */ x86emuOp_push_register,
5237
5238/*  0x58 */ x86emuOp_pop_register,
5239/*  0x59 */ x86emuOp_pop_register,
5240/*  0x5a */ x86emuOp_pop_register,
5241/*  0x5b */ x86emuOp_pop_register,
5242/*  0x5c */ x86emuOp_pop_register,
5243/*  0x5d */ x86emuOp_pop_register,
5244/*  0x5e */ x86emuOp_pop_register,
5245/*  0x5f */ x86emuOp_pop_register,
5246
5247/*  0x60 */ x86emuOp_push_all,
5248/*  0x61 */ x86emuOp_pop_all,
5249/*  0x62 */ x86emuOp_illegal_op,   /* bound */
5250/*  0x63 */ x86emuOp_illegal_op,   /* arpl */
5251/*  0x64 */ x86emuOp_segovr_FS,
5252/*  0x65 */ x86emuOp_segovr_GS,
5253/*  0x66 */ x86emuOp_prefix_data,
5254/*  0x67 */ x86emuOp_prefix_addr,
5255
5256/*  0x68 */ x86emuOp_push_word_IMM,
5257/*  0x69 */ x86emuOp_imul_word_IMM,
5258/*  0x6a */ x86emuOp_push_byte_IMM,
5259/*  0x6b */ x86emuOp_imul_byte_IMM,
5260/*  0x6c */ x86emuOp_ins_byte,
5261/*  0x6d */ x86emuOp_ins_word,
5262/*  0x6e */ x86emuOp_outs_byte,
5263/*  0x6f */ x86emuOp_outs_word,
5264
5265/*  0x70 */ x86emuOp_jump_near_cond,
5266/*  0x71 */ x86emuOp_jump_near_cond,
5267/*  0x72 */ x86emuOp_jump_near_cond,
5268/*  0x73 */ x86emuOp_jump_near_cond,
5269/*  0x74 */ x86emuOp_jump_near_cond,
5270/*  0x75 */ x86emuOp_jump_near_cond,
5271/*  0x76 */ x86emuOp_jump_near_cond,
5272/*  0x77 */ x86emuOp_jump_near_cond,
5273
5274/*  0x78 */ x86emuOp_jump_near_cond,
5275/*  0x79 */ x86emuOp_jump_near_cond,
5276/*  0x7a */ x86emuOp_jump_near_cond,
5277/*  0x7b */ x86emuOp_jump_near_cond,
5278/*  0x7c */ x86emuOp_jump_near_cond,
5279/*  0x7d */ x86emuOp_jump_near_cond,
5280/*  0x7e */ x86emuOp_jump_near_cond,
5281/*  0x7f */ x86emuOp_jump_near_cond,
5282
5283/*  0x80 */ x86emuOp_opc80_byte_RM_IMM,
5284/*  0x81 */ x86emuOp_opc81_word_RM_IMM,
5285/*  0x82 */ x86emuOp_opc82_byte_RM_IMM,
5286/*  0x83 */ x86emuOp_opc83_word_RM_IMM,
5287/*  0x84 */ x86emuOp_test_byte_RM_R,
5288/*  0x85 */ x86emuOp_test_word_RM_R,
5289/*  0x86 */ x86emuOp_xchg_byte_RM_R,
5290/*  0x87 */ x86emuOp_xchg_word_RM_R,
5291
5292/*  0x88 */ x86emuOp_mov_byte_RM_R,
5293/*  0x89 */ x86emuOp_mov_word_RM_R,
5294/*  0x8a */ x86emuOp_mov_byte_R_RM,
5295/*  0x8b */ x86emuOp_mov_word_R_RM,
5296/*  0x8c */ x86emuOp_mov_word_RM_SR,
5297/*  0x8d */ x86emuOp_lea_word_R_M,
5298/*  0x8e */ x86emuOp_mov_word_SR_RM,
5299/*  0x8f */ x86emuOp_pop_RM,
5300
5301/*  0x90 */ x86emuOp_nop,
5302/*  0x91 */ x86emuOp_xchg_word_AX_register,
5303/*  0x92 */ x86emuOp_xchg_word_AX_register,
5304/*  0x93 */ x86emuOp_xchg_word_AX_register,
5305/*  0x94 */ x86emuOp_xchg_word_AX_register,
5306/*  0x95 */ x86emuOp_xchg_word_AX_register,
5307/*  0x96 */ x86emuOp_xchg_word_AX_register,
5308/*  0x97 */ x86emuOp_xchg_word_AX_register,
5309
5310/*  0x98 */ x86emuOp_cbw,
5311/*  0x99 */ x86emuOp_cwd,
5312/*  0x9a */ x86emuOp_call_far_IMM,
5313/*  0x9b */ x86emuOp_wait,
5314/*  0x9c */ x86emuOp_pushf_word,
5315/*  0x9d */ x86emuOp_popf_word,
5316/*  0x9e */ x86emuOp_sahf,
5317/*  0x9f */ x86emuOp_lahf,
5318
5319/*  0xa0 */ x86emuOp_mov_AL_M_IMM,
5320/*  0xa1 */ x86emuOp_mov_AX_M_IMM,
5321/*  0xa2 */ x86emuOp_mov_M_AL_IMM,
5322/*  0xa3 */ x86emuOp_mov_M_AX_IMM,
5323/*  0xa4 */ x86emuOp_movs_byte,
5324/*  0xa5 */ x86emuOp_movs_word,
5325/*  0xa6 */ x86emuOp_cmps_byte,
5326/*  0xa7 */ x86emuOp_cmps_word,
5327/*  0xa8 */ x86emuOp_test_AL_IMM,
5328/*  0xa9 */ x86emuOp_test_AX_IMM,
5329/*  0xaa */ x86emuOp_stos_byte,
5330/*  0xab */ x86emuOp_stos_word,
5331/*  0xac */ x86emuOp_lods_byte,
5332/*  0xad */ x86emuOp_lods_word,
5333/*  0xac */ x86emuOp_scas_byte,
5334/*  0xad */ x86emuOp_scas_word,
5335
5336/*  0xb0 */ x86emuOp_mov_byte_register_IMM,
5337/*  0xb1 */ x86emuOp_mov_byte_register_IMM,
5338/*  0xb2 */ x86emuOp_mov_byte_register_IMM,
5339/*  0xb3 */ x86emuOp_mov_byte_register_IMM,
5340/*  0xb4 */ x86emuOp_mov_byte_register_IMM,
5341/*  0xb5 */ x86emuOp_mov_byte_register_IMM,
5342/*  0xb6 */ x86emuOp_mov_byte_register_IMM,
5343/*  0xb7 */ x86emuOp_mov_byte_register_IMM,
5344
5345/*  0xb8 */ x86emuOp_mov_word_register_IMM,
5346/*  0xb9 */ x86emuOp_mov_word_register_IMM,
5347/*  0xba */ x86emuOp_mov_word_register_IMM,
5348/*  0xbb */ x86emuOp_mov_word_register_IMM,
5349/*  0xbc */ x86emuOp_mov_word_register_IMM,
5350/*  0xbd */ x86emuOp_mov_word_register_IMM,
5351/*  0xbe */ x86emuOp_mov_word_register_IMM,
5352/*  0xbf */ x86emuOp_mov_word_register_IMM,
5353
5354/*  0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5355/*  0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5356/*  0xc2 */ x86emuOp_ret_near_IMM,
5357/*  0xc3 */ x86emuOp_ret_near,
5358/*  0xc4 */ x86emuOp_les_R_IMM,
5359/*  0xc5 */ x86emuOp_lds_R_IMM,
5360/*  0xc6 */ x86emuOp_mov_byte_RM_IMM,
5361/*  0xc7 */ x86emuOp_mov_word_RM_IMM,
5362/*  0xc8 */ x86emuOp_enter,
5363/*  0xc9 */ x86emuOp_leave,
5364/*  0xca */ x86emuOp_ret_far_IMM,
5365/*  0xcb */ x86emuOp_ret_far,
5366/*  0xcc */ x86emuOp_int3,
5367/*  0xcd */ x86emuOp_int_IMM,
5368/*  0xce */ x86emuOp_into,
5369/*  0xcf */ x86emuOp_iret,
5370
5371/*  0xd0 */ x86emuOp_opcD0_byte_RM_1,
5372/*  0xd1 */ x86emuOp_opcD1_word_RM_1,
5373/*  0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5374/*  0xd3 */ x86emuOp_opcD3_word_RM_CL,
5375/*  0xd4 */ x86emuOp_aam,
5376/*  0xd5 */ x86emuOp_aad,
5377/*  0xd6 */ x86emuOp_illegal_op,   /* Undocumented SETALC instruction */
5378/*  0xd7 */ x86emuOp_xlat,
5379/*  0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5380/*  0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5381/*  0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5382/*  0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5383/*  0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5384/*  0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5385/*  0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5386/*  0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5387
5388/*  0xe0 */ x86emuOp_loopne,
5389/*  0xe1 */ x86emuOp_loope,
5390/*  0xe2 */ x86emuOp_loop,
5391/*  0xe3 */ x86emuOp_jcxz,
5392/*  0xe4 */ x86emuOp_in_byte_AL_IMM,
5393/*  0xe5 */ x86emuOp_in_word_AX_IMM,
5394/*  0xe6 */ x86emuOp_out_byte_IMM_AL,
5395/*  0xe7 */ x86emuOp_out_word_IMM_AX,
5396
5397/*  0xe8 */ x86emuOp_call_near_IMM,
5398/*  0xe9 */ x86emuOp_jump_near_IMM,
5399/*  0xea */ x86emuOp_jump_far_IMM,
5400/*  0xeb */ x86emuOp_jump_byte_IMM,
5401/*  0xec */ x86emuOp_in_byte_AL_DX,
5402/*  0xed */ x86emuOp_in_word_AX_DX,
5403/*  0xee */ x86emuOp_out_byte_DX_AL,
5404/*  0xef */ x86emuOp_out_word_DX_AX,
5405
5406/*  0xf0 */ x86emuOp_lock,
5407/*  0xf1 */ x86emuOp_illegal_op,
5408/*  0xf2 */ x86emuOp_repne,
5409/*  0xf3 */ x86emuOp_repe,
5410/*  0xf4 */ x86emuOp_halt,
5411/*  0xf5 */ x86emuOp_cmc,
5412/*  0xf6 */ x86emuOp_opcF6_byte_RM,
5413/*  0xf7 */ x86emuOp_opcF7_word_RM,
5414
5415/*  0xf8 */ x86emuOp_clc,
5416/*  0xf9 */ x86emuOp_stc,
5417/*  0xfa */ x86emuOp_cli,
5418/*  0xfb */ x86emuOp_sti,
5419/*  0xfc */ x86emuOp_cld,
5420/*  0xfd */ x86emuOp_std,
5421/*  0xfe */ x86emuOp_opcFE_byte_RM,
5422/*  0xff */ x86emuOp_opcFF_word_RM,
5423};
5424