"Fossies" - the Fresh Open Source Software Archive

Member "dosemu-1.4.0/src/emu-i386/simx86/interp.c" (4 May 2007, 76412 Bytes) of package /linux/misc/old/dosemu-1.4.0.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "interp.c" see the Fossies "Dox" file reference documentation.

    1 /***************************************************************************
    2  * 
    3  * All modifications in this file to the original code are
    4  * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team".
    5  *
    6  * for details see file COPYING.DOSEMU in the DOSEMU distribution
    7  *
    8  *
    9  *  SIMX86 a Intel 80x86 cpu emulator
   10  *  Copyright (C) 1997,2001 Alberto Vignani, FIAT Research Center
   11  *              a.vignani@crf.it
   12  *
   13  *  This program is free software; you can redistribute it and/or modify
   14  *  it under the terms of the GNU General Public License as published by
   15  *  the Free Software Foundation; either version 2 of the License, or
   16  *  (at your option) any later version.
   17  *
   18  *  This program is distributed in the hope that it will be useful,
   19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21  *  GNU General Public License for more details.
   22  *
   23  *  You should have received a copy of the GNU General Public License
   24  *  along with this program; if not, write to the Free Software
   25  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   26  *
   27  * Additional copyright notes:
   28  *
   29  * 1. The kernel-level vm86 handling was taken out of the Linux kernel
   30  *  (linux/arch/i386/kernel/vm86.c). This code originaly was written by
   31  *  Linus Torvalds with later enhancements by Lutz Molgedey and Hans Lermen.
   32  *
   33  ***************************************************************************/
   34 
   35 #include <stddef.h>
   36 #include <string.h>
   37 #include "emu86.h"
   38 #include "codegen-arch.h"
   39 #include "port.h"
   40 #include "dpmi.h"
   41 
   42 unsigned char *P0;
   43 #ifdef PROFILE
   44 int EmuSignals = 0;
   45 #endif
   46 
   47 static int NewNode = 1;
   48 static int basemode = 0;
   49 
   50 static int ArOpsR[] =
   51     { O_ADD_R, O_OR_R, O_ADC_R, O_SBB_R, O_AND_R, O_SUB_R, O_XOR_R, O_CMP_R };
   52 static int ArOpsFR[] =
   53     {      -1,     -1,      -1, O_SBB_FR,     -1, O_SUB_FR,     -1, O_CMP_FR};
   54 static char R1Tab_b[8] =
   55     { Ofs_AL, Ofs_CL, Ofs_DL, Ofs_BL, Ofs_AH, Ofs_CH, Ofs_DH, Ofs_BH };
   56 static char R1Tab_l[14] =
   57     { Ofs_EAX, Ofs_ECX, Ofs_EDX, Ofs_EBX, Ofs_ESP, Ofs_EBP, Ofs_ESI, Ofs_EDI,
   58       Ofs_ES,  Ofs_CS,  Ofs_SS,  Ofs_DS,  Ofs_FS,  Ofs_GS };
   59 
   60 #define SEL_B_X(r)      R1Tab_b[(r)]
   61 
   62 #define INC_WL_PCA(m,i) PC=(PC+(i)+BT24(BitADDR16, m))
   63 #define INC_WL_PC(m,i)  PC=(PC+(i)+BT24(BitDATA16, m))
   64 
   65 static __inline__ unsigned long GetCPU_WL(int m, char o)
   66 {
   67     if (m&DATA16) return CPUWORD(o); else return CPULONG(o);
   68 }
   69 
   70 static __inline__ void SetCPU_WL(int m, char o, unsigned long v)
   71 {
   72     if (m&DATA16) CPUWORD(o)=v; else CPULONG(o)=v;
   73 }
   74 
   75 /*
   76  * close any pending instruction in the code cache and execute the
   77  * current sequence.
   78  * P0 is the start of current instruction, where the sequence stops
   79  *  if there are no jumps at the end.
   80  * P2 is the address of the next instruction to execute. If different
   81  *  from P0, abort the current instruction and resume the parsing
   82  *  loop at P2.
   83  */
   84 #define CODE_FLUSH()    if (CONFIG_CPUSIM || CurrIMeta>0) {\
   85               unsigned char *P2 = CloseAndExec(P0, NULL, mode, __LINE__);\
   86               if (TheCPU.err) return P2;\
   87               if (!CONFIG_CPUSIM && P2 != P0) { PC=P2; continue; }\
   88             } NewNode=0
   89 
   90 #define UNPREFIX(m) ((m)&~(DATA16|ADDR16))|(basemode&(DATA16|ADDR16))
   91 
   92 #if 1   // VIF kernel patch
   93 #define EFLAGS_IFK  (EFLAGS_IF|EFLAGS_VIF)
   94 #else
   95 #define EFLAGS_IFK  EFLAGS_IF
   96 #endif
   97 
   98 /////////////////////////////////////////////////////////////////////////////
   99 
  100 
  101 static int MAKESEG(int mode, int ofs, unsigned short sv)
  102 {
  103     SDTR tseg, *segc;
  104     int e;
  105     char big;
  106 
  107 //  if ((ofs<0)||(ofs>=0x60)) return EXCP06_ILLOP;
  108 
  109     if (REALADDR()) {
  110         return SetSegReal(sv,ofs);
  111     }
  112 
  113     segc = (SDTR *)CPUOFFS(e_ofsseg[(ofs>>2)]);
  114 //  if (segc==NULL) return EXCP06_ILLOP;
  115 
  116     memcpy(&tseg,segc,sizeof(SDTR));
  117     e = SetSegProt(mode&ADDR16, ofs, &big, sv);
  118     /* must NOT change segreg and LONG_xx if error! */
  119     if (e) {
  120         memcpy(segc,&tseg,sizeof(SDTR));
  121         return e;
  122     }
  123     CPUWORD(ofs) = sv;
  124     if (ofs==Ofs_CS) {
  125         if (big) basemode &= ~(ADDR16|DATA16);
  126         else basemode |= (ADDR16|DATA16);
  127         if (debug_level('e')>1) e_printf("MAKESEG CS: big=%d basemode=%04x\n",big&1,basemode);
  128     }
  129     if (ofs==Ofs_SS) {
  130         TheCPU.StackMask = (big? 0xffffffff : 0x0000ffff);
  131         if (debug_level('e')>1) e_printf("MAKESEG SS: big=%d basemode=%04x\n",big&1,basemode);
  132     }
  133     return 0;
  134 }
  135 
  136 
  137 /////////////////////////////////////////////////////////////////////////////
  138 //
  139 // jmp      b8 j j j j c3
  140 //  link    e9 l l l l --
  141 // jcc      7x 06 b8 a a a a c3 b8 b b b b c3
  142 //  link    7x 06 e9 l l l l -- e9 l l l l --
  143 //
  144 
  145 static unsigned char *JumpGen(unsigned char *P2, int mode, int cond,
  146                   int btype)
  147 {
  148     unsigned char *P1;
  149     int taken=0, tailjmp=0;
  150     int dsp, cxv, gim, rc;
  151     int pskip;
  152     unsigned long d_t, d_nt, j_t, j_nt;
  153 
  154     /* pskip points to start of next instruction
  155      * dsp is the displacement relative to this jump instruction,
  156      * some cases:
  157      *  eb 00   dsp=2   jmp to next inst (dsp==pskip)
  158      *  eb ff   dsp=1   illegal or tricky
  159      *  eb fe   dsp=0   loop forever
  160      */
  161     if ((btype&5)==0) { // short branch (byte)
  162         pskip = 2;
  163         dsp = pskip + (signed char)Fetch(P2+1);
  164     }
  165     else if ((btype&5)==4) {    // jmp (word/long)
  166         pskip = 1 + BT24(BitADDR16,mode);
  167         dsp = pskip + (int)AddrFetchWL_S(mode, P2+1);
  168     }
  169     else {      // long branch (word/long)
  170         pskip = 2 + BT24(BitADDR16,mode);
  171         dsp = pskip + (int)AddrFetchWL_S(mode, P2+2);
  172     }
  173 
  174     /* displacement for taken branch */
  175     d_t  = ((long)P2 - LONG_CS) + dsp;
  176     /* displacement for not taken branch */
  177     d_nt = ((long)P2 - LONG_CS) + pskip;
  178     if (mode&DATA16) { d_t &= 0xffff; d_nt &= 0xffff; }
  179 
  180     /* jump address for taken branch */
  181     j_t  = d_t  + LONG_CS;
  182     /* jump address for not taken branch, usually next instruction */
  183     j_nt = d_nt + LONG_CS;
  184 
  185 #ifdef HOST_ARCH_X86
  186 #if !defined(SINGLESTEP)&&!defined(SINGLEBLOCK)
  187     if (!UseLinker || CONFIG_CPUSIM || (EFLAGS & TF))
  188 #endif
  189 #endif
  190         goto jgnolink;
  191 
  192     gim = 0;
  193     switch(cond) {
  194     case 0x00 ... 0x0f:
  195     case 0x31:
  196         P1 = P2 + pskip;
  197         /* is there a jump after the condition? if yes, simplify */
  198         if (Fetch(P1)==JMPsid) {    /* eb xx */
  199             int dsp2 = (signed char)Fetch(P1+1) + 2;
  200                 if (dsp2 < 0) mode |= CKSIGN;
  201             d_nt = ((long)P1 - LONG_CS) + dsp2;
  202             if (mode&ADDR16) d_nt &= 0xffff;
  203             j_nt = d_nt + LONG_CS;
  204                 e_printf("JMPs (%02x,%d) at %08lx after Jcc: t=%08lx nt=%08lx\n",
  205             P1[0],dsp2,(long)P1,j_t,j_nt);
  206         }
  207         else if (Fetch(P1)==JMPd) { /* e9 xxxx{xxxx} */
  208             int skp2 = BT24(BitADDR16,mode) + 1;
  209             int dsp2 = skp2 + (int)AddrFetchWL_S(mode, P1+1);
  210                 if (dsp2 < 0) mode |= CKSIGN;
  211             d_nt = ((long)P1 - LONG_CS) + dsp2;
  212             if (mode&ADDR16) d_nt &= 0xffff;
  213             j_nt = d_nt + LONG_CS;
  214                 e_printf("JMPl (%02x,%d) at %08lx after Jcc: t=%08lx nt=%08lx\n",
  215             P1[0],dsp2,(long)P1,j_t,j_nt);
  216         }
  217 
  218         /* backwards jump limited to 256 bytes */
  219         if ((dsp > -256) && (dsp < 0)) {
  220             Gen(JB_LINK, mode, cond, P2, j_t, j_nt, &InstrMeta[0].clink);
  221             gim = 1;
  222         }
  223         else if (dsp) {
  224             /* forward jump or backward jump >=256 bytes */
  225             if ((dsp < 0) || (dsp > pskip)) {
  226             Gen(JF_LINK, mode, cond, P2, j_t, j_nt, &InstrMeta[0].clink);
  227             gim = 1;
  228             }
  229             else if (dsp==pskip) {
  230             e_printf("### jmp %x 00\n",cond);
  231             TheCPU.mode |= SKIPOP;
  232             goto notakejmp;
  233             }
  234             else {  // dsp>0 && dsp<pskip: jumps in the jmp itself
  235             TheCPU.err = -103;
  236             dbug_printf("### err 103 jmp=%x dsp=%d pskip=%d\n",cond,dsp,pskip);
  237             return NULL;
  238             }
  239         }
  240         else {  // dsp==0
  241             /* strange but possible, very tight loop with an external
  242              * condition changing a flag */
  243             e_printf("### dsp=0 jmp=%x pskip=%d\n",cond,pskip);
  244             break;
  245         }
  246         tailjmp=1;
  247         break;
  248     case 0x10:
  249         if (dsp==0) {   // eb fe
  250             dbug_printf("!Forever loop!\n");
  251             leavedos(0xebfe);
  252         }
  253 #ifdef HOST_ARCH_X86
  254 #ifdef NOJUMPS
  255         if (!CONFIG_CPUSIM &&
  256             (((long)P2 ^ j_t) & PAGE_MASK)==0) {    // same page
  257             e_printf("** JMP: ignored\n");
  258             TheCPU.mode |= SKIPOP;
  259             goto takejmp;
  260         }
  261 #endif
  262 #endif
  263     case 0x11:
  264         Gen(JMP_LINK, mode, cond, j_t, d_nt, &InstrMeta[0].clink);
  265         gim = 1;
  266         tailjmp=1;
  267         break;
  268     case 0x20: case 0x24: case 0x25:
  269         if (dsp == 0) {
  270                 // ndiags: shorten delay loops (e2 fe)
  271             e_printf("### loop %x 0xfe\n",cond);
  272             TheCPU.mode |= SKIPOP;
  273             if (mode&ADDR16) rCX=0; else rECX=0;
  274             goto notakejmp;
  275         }
  276         else {
  277             Gen(JLOOP_LINK, mode, cond, j_t, j_nt, &InstrMeta[0].clink);
  278             gim = 1;
  279             tailjmp=1;
  280         }
  281         break;
  282     default: dbug_printf("JumpGen: unknown condition\n");
  283         break;
  284     }
  285 
  286     if (gim)
  287         (void)NewIMeta(P2, mode, &rc);
  288 
  289 jgnolink:
  290     /* we just generated a jump, so the returned eip (P1) is
  291      * (almost) always different from P2.
  292      */
  293     P1 = CloseAndExec(P2, NULL, mode, __LINE__); NewNode=0;
  294     if (TheCPU.err) return NULL;
  295     if (tailjmp) return P1;
  296 
  297     /* evaluate cond at RUNTIME after exec'ing */
  298     switch(cond) {
  299     case 0x00:
  300         if (CONFIG_CPUSIM) FlagSync_O();
  301         taken = IS_OF_SET; break;
  302     case 0x01:
  303         if (CONFIG_CPUSIM) FlagSync_O();
  304         taken = !IS_OF_SET; break;
  305     case 0x02: taken = IS_CF_SET; break;
  306     case 0x03: taken = !IS_CF_SET; break;
  307     case 0x04: taken = IS_ZF_SET; break;
  308     case 0x05: taken = !IS_ZF_SET; break;
  309     case 0x06: taken = IS_CF_SET || IS_ZF_SET; break;
  310     case 0x07: taken = !IS_CF_SET && !IS_ZF_SET; break;
  311     case 0x08: taken = IS_SF_SET; break;
  312     case 0x09: taken = !IS_SF_SET; break;
  313     case 0x0a:
  314         e_printf("!!! JPset\n");
  315         if (CONFIG_CPUSIM) FlagSync_AP();
  316         taken = IS_PF_SET; break;
  317     case 0x0b:
  318         e_printf("!!! JPclr\n");
  319         if (CONFIG_CPUSIM) FlagSync_AP();
  320         taken = !IS_PF_SET; break;
  321     case 0x0c:
  322         if (CONFIG_CPUSIM) FlagSync_O();
  323         taken = IS_SF_SET ^ IS_OF_SET; break;
  324     case 0x0d:
  325         if (CONFIG_CPUSIM) FlagSync_O();
  326         taken = !(IS_SF_SET ^ IS_OF_SET); break;
  327     case 0x0e:
  328         if (CONFIG_CPUSIM) FlagSync_O();
  329         taken = (IS_SF_SET ^ IS_OF_SET) || IS_ZF_SET; break;
  330     case 0x0f:
  331         if (CONFIG_CPUSIM) FlagSync_O();
  332         taken = !(IS_SF_SET ^ IS_OF_SET) && !IS_ZF_SET; break;
  333     case 0x10: taken = 1; break;
  334     case 0x11: {
  335             PUSH(mode, &d_nt);
  336             if (debug_level('e')>2) e_printf("CALL: ret=%08lx\n",d_nt);
  337             taken = 1;
  338            } break;
  339     case 0x20:  // LOOP
  340            cxv = (mode&ADDR16? --rCX : --rECX);
  341            taken = (cxv != 0); break;
  342     case 0x24:  // LOOPZ
  343            cxv = (mode&ADDR16? --rCX : --rECX);
  344            taken = (cxv != 0) && IS_ZF_SET; break;
  345     case 0x25:  // LOOPNZ
  346            cxv = (mode&ADDR16? --rCX : --rECX);
  347            taken = (cxv != 0) && !IS_ZF_SET; break;
  348     case 0x31:  // JCXZ
  349            cxv = (mode&ADDR16? rCX : rECX);
  350            taken = (cxv == 0); break;
  351     }
  352     NewNode = 0;
  353     if (taken) {
  354         if (dsp==0) {   // infinite loop
  355             if ((cond&0xf0)==0x20) {    // loops
  356                 // ndiags: shorten delay loops (e2 fe)
  357             if (mode&ADDR16) rCX=0; else rECX=0;
  358             return (unsigned char *)j_nt;
  359             }
  360             TheCPU.err = -103;
  361             return NULL;
  362         }
  363         if (debug_level('e')>2) e_printf("** Jump taken to %08lx\n",(long)j_t);
  364 #ifdef HOST_ARCH_X86
  365 takejmp:
  366 #endif
  367         TheCPU.eip = d_t;
  368         return (unsigned char *)j_t;
  369     }
  370 notakejmp:
  371     TheCPU.eip = d_nt;
  372     return (unsigned char *)j_nt;
  373 }
  374 
  375 
  376 /////////////////////////////////////////////////////////////////////////////
  377 
  378 
  379 unsigned char *Interp86(unsigned char *PC, int mod0)
  380 {
  381     unsigned char opc;
  382     unsigned int temp;
  383     register int mode;
  384 #ifdef HOST_ARCH_X86
  385     TNode *G;
  386 #endif
  387 
  388     NewNode = 0;
  389     basemode = mod0;
  390     TheCPU.err = 0;
  391     CEmuStat &= ~CeS_TRAP;
  392 
  393     while (Running) {
  394         OVERR_DS = Ofs_XDS;
  395         OVERR_SS = Ofs_XSS;
  396         P0 = PC;    // P0 changes on instruction boundaries
  397         TheCPU.mode = mode = basemode;
  398 
  399         if (!NewNode) {
  400 #if !defined(SINGLESTEP)&&!defined(SINGLEBLOCK)&&defined(HOST_ARCH_X86)
  401             if (!CONFIG_CPUSIM && !(EFLAGS & TF)) {
  402             /* for a sequence to be found, it must begin with
  403              * an allowable opcode. Look into table.
  404              * NOTE - this while can loop forever and stop
  405              * any signal processing. Jumps are defined as
  406              * a 'descheduling point' for checking signals.
  407              */
  408             temp = 100; /* safety count */
  409             while (temp && ((InterOps[Fetch(PC)]&1)==0) && (G=FindTree((long)PC)) != NULL) {
  410                 if (debug_level('e')>2)
  411                     e_printf("** Found compiled code at %08lx\n",(long)(PC));
  412                 if (CurrIMeta>0) {      // open code?
  413                     if (debug_level('e')>2)
  414                         e_printf("============ Closing open sequence at %08lx\n",(long)(PC));
  415                     PC = CloseAndExec(PC, NULL, mode, __LINE__);
  416                     if (TheCPU.err) return PC;
  417                 }
  418                 /* ---- this is the MAIN EXECUTE point ---- */
  419                 { int m = mode | (G->flags<<16) | XECFND;
  420                   unsigned char *tmp = CloseAndExec(NULL, G, m, __LINE__);
  421                   if (!tmp) goto bad_return;
  422                   P0 = PC = tmp; }
  423                 if (TheCPU.err) return PC;
  424                 /* on jumps, exit to process signals */
  425                 if (InterOps[Fetch(PC)]&0x80) break;
  426                 /* if all fails, stop infinite loops here */
  427                 temp--;
  428             }
  429             }
  430 #endif
  431             if (CEmuStat & (CeS_TRAP|CeS_DRTRAP|CeS_SIGPEND|CeS_LOCK|CeS_RPIC|CeS_STI)) {
  432 #ifdef PROFILE
  433                 EmuSignals++;
  434 #endif
  435                 if (CEmuStat & CeS_LOCK)
  436                     CEmuStat &= ~CeS_LOCK;
  437                 else {
  438                     if (CEmuStat & CeS_TRAP) {
  439                         /* force exit for single step trap */
  440                         if (!TheCPU.err)
  441                             TheCPU.err = EXCP01_SSTP;
  442                         return PC;
  443                     }
  444                     //else if (CEmuStat & CeS_DRTRAP) {
  445                     //  if (e_debug_check(PC)) {
  446                     //      TheCPU.err = EXCP01_SSTP;
  447                     //      return PC;
  448                     //  }
  449                     //}
  450                     else if (CEmuStat & CeS_SIGPEND) {
  451                         /* force exit after signal */
  452                         CEmuStat = (CEmuStat & ~CeS_SIGPEND) | CeS_SIGACT;
  453                         TheCPU.err=EXCP_SIGNAL;
  454                         return PC;
  455                     }
  456                     else if (CEmuStat & CeS_RPIC) {
  457                         /* force exit for PIC */
  458                         CEmuStat &= ~CeS_RPIC;
  459                         TheCPU.err=EXCP_PICSIGNAL;
  460                         return PC;
  461                     }
  462                     else if (CEmuStat & CeS_STI) {
  463                         /* force exit for IF set */
  464                         CEmuStat &= ~CeS_STI;
  465                         TheCPU.err=EXCP_STISIGNAL;
  466                         return PC;
  467                     }
  468                 }
  469             }
  470             CEmuStat &= ~CeS_TRAP;
  471             if (EFLAGS & TF) {
  472                 CEmuStat |= CeS_TRAP;
  473             }
  474         }
  475 // ------ temp ------- debug ------------------------
  476         if ((PC==NULL)||(*((int *)PC)==0)) {
  477             set_debug_level('e',9);
  478             dbug_printf("\n%s\nFetch %08x at %p mode %x\n",
  479                 e_print_regs(),*((int *)PC),PC,mode);
  480             TheCPU.err = -99; return PC;
  481         }
  482 // ------ temp ------- debug ------------------------
  483         NewNode = 1;
  484 
  485 override:
  486         switch ((opc=Fetch(PC))) {
  487 /*28*/  case SUBbfrm:
  488 /*30*/  case XORbfrm:
  489 /*32*/  case XORbtrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  490                 Gen(O_CLEAR, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]);
  491                 PC+=2; break;
  492             } goto intop28;
  493 /*08*/  case ORbfrm:
  494 /*0a*/  case ORbtrm:
  495 /*20*/  case ANDbfrm:
  496 /*22*/  case ANDbtrm:
  497 /*84*/  case TESTbrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  498                 Gen(O_TEST, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]);
  499                 PC+=2; break;
  500             } goto intop28;
  501 /*18*/  case SBBbfrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  502                 Gen(O_SBSELF, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]);
  503                 PC+=2; break;
  504             }
  505 /*00*/  case ADDbfrm:
  506 /*02*/  case ADDbtrm:
  507 /*10*/  case ADCbfrm:
  508 /*12*/  case ADCbtrm:
  509 /*38*/  case CMPbfrm:
  510 intop28:        { int m = mode | MBYTE;
  511             int op = (opc==TESTbrm? O_AND_R:ArOpsR[D_MO(opc)]);
  512             PC += ModRM(opc, PC, m);    // SI=reg DI=mem
  513                 Gen(L_DI_R1, m);        // mov al,[edi]
  514                 Gen(op, m, REG1);       // op  al,[ebx+reg]
  515                 if ((opc!=CMPbfrm)&&(opc!=TESTbrm)) {
  516                 if (opc & 2)
  517                     Gen(S_REG, m, REG1);    // mov [ebx+reg],al     reg=mem op reg
  518                 else
  519                     Gen(S_DI, m);       // mov [edi],al         mem=mem op reg
  520                 }
  521             }
  522             break; 
  523 /*2a*/  case SUBbtrm:   if (RmIsReg[Fetch(PC+1)]&2) {
  524                 Gen(O_CLEAR, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]);
  525                 PC+=2; break;
  526             } goto intop3a;
  527 /*1a*/  case SBBbtrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  528                 Gen(O_SBSELF, mode|MBYTE, R1Tab_b[Fetch(PC+1)&7]);
  529                 PC+=2; break;
  530             }
  531 /*3a*/  case CMPbtrm:
  532 intop3a:        { int m = mode | MBYTE;
  533             int op = ArOpsFR[D_MO(opc)];
  534             PC += ModRM(opc, PC, m);    // SI=reg DI=mem
  535             Gen(L_DI_R1, m);        // mov al,[edi]
  536             Gen(op, m, REG1);       // op [ebx+reg], al
  537             // reg=reg op mem
  538             }
  539             break; 
  540 /*29*/  case SUBwfrm:
  541 /*31*/  case XORwfrm:
  542 /*33*/  case XORwtrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  543                 Gen(O_CLEAR, mode, R1Tab_l[Fetch(PC+1)&7]);
  544                 PC+=2; break;
  545             } goto intop29;
  546 /*09*/  case ORwfrm:
  547 /*0b*/  case ORwtrm:
  548 /*21*/  case ANDwfrm:
  549 /*23*/  case ANDwtrm:
  550 /*85*/  case TESTwrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  551                 Gen(O_TEST, mode, R1Tab_l[Fetch(PC+1)&7]);
  552                 PC+=2; break;
  553             } goto intop29;
  554 /*19*/  case SBBwfrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  555                 Gen(O_SBSELF, mode, R1Tab_l[Fetch(PC+1)&7]);
  556                 PC+=2; break;
  557             }
  558 /*01*/  case ADDwfrm:
  559 /*03*/  case ADDwtrm:
  560 /*11*/  case ADCwfrm:
  561 /*13*/  case ADCwtrm:
  562 /*39*/  case CMPwfrm:
  563 intop29:        { int op = (opc==TESTwrm? O_AND_R:ArOpsR[D_MO(opc)]);
  564             PC += ModRM(opc, PC, mode); // SI=reg DI=mem
  565                 Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
  566                 Gen(op, mode, REG1);        // op  (e)ax,[ebx+reg]
  567                 if ((opc!=CMPwfrm)&&(opc!=TESTwrm)) {
  568                 if (opc & 2)
  569                     Gen(S_REG, mode, REG1); // mov [ebx+reg],(e)ax  reg=mem op reg
  570                 else
  571                     Gen(S_DI, mode);    // mov [edi],(e)ax  mem=mem op reg
  572                 }
  573             }
  574             break; 
  575 /*2b*/  case SUBwtrm:   if (RmIsReg[Fetch(PC+1)]&2) {
  576                 Gen(O_CLEAR, mode, R1Tab_l[Fetch(PC+1)&7]);
  577                 PC+=2; break;
  578             } goto intop3b;
  579 /*1b*/  case SBBwtrm:   if (RmIsReg[Fetch(PC+1)]&2) {   // same reg
  580                 Gen(O_SBSELF, mode, R1Tab_l[Fetch(PC+1)&7]);
  581                 PC+=2; break;
  582             }
  583 /*3b*/  case CMPwtrm:
  584 intop3b:        { int op = ArOpsFR[D_MO(opc)];
  585             PC += ModRM(opc, PC, mode); // SI=reg DI=mem
  586             Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
  587             Gen(op, mode, REG1);        // op [ebx+reg], (e)ax
  588             // reg=reg op mem
  589             }
  590             break; 
  591 /*a8*/  case TESTbi:
  592 /*04*/  case ADDbia:
  593 /*0c*/  case ORbi:
  594 /*14*/  case ADCbi:
  595 /*24*/  case ANDbi:
  596 /*34*/  case XORbi: {
  597             int m = mode | MBYTE;
  598             int op = (opc==TESTbi? O_AND_R:ArOpsR[D_MO(opc)]);
  599             Gen(L_IMM_R1, m, Fetch(PC+1)); PC+=2;   // mov al,#imm
  600             Gen(op, m, Ofs_AL);         // op al,[ebx+reg]
  601             if (opc != TESTbi)
  602                 Gen(S_REG, m, Ofs_AL);  // mov [ebx+reg],al
  603             }
  604             break; 
  605 /*1c*/  case SBBbi:
  606 /*2c*/  case SUBbi:
  607 /*3c*/  case CMPbi: {
  608             int m = mode | MBYTE;
  609             int op = ArOpsFR[D_MO(opc)];
  610             // op [ebx+Ofs_EAX],#imm
  611             Gen(op, m|IMMED, Fetch(PC+1)); PC+=2;
  612             }
  613             break; 
  614 /*a9*/  case TESTwi:
  615 /*05*/  case ADDwia:
  616 /*0d*/  case ORwi:
  617 /*15*/  case ADCwi:
  618 /*25*/  case ANDwi:
  619 /*35*/  case XORwi: {
  620             int op = (opc==TESTwi? O_AND_R:ArOpsR[D_MO(opc)]);
  621             Gen(L_IMM_R1, mode|IMMED, DataFetchWL_U(mode,PC+1));
  622             INC_WL_PC(mode,1);
  623             Gen(op, mode, Ofs_EAX);
  624             if (opc != TESTwi)
  625                 Gen(S_REG, mode, Ofs_EAX);
  626             }
  627             break; 
  628 /*1d*/  case SBBwi:
  629 /*2d*/  case SUBwi:
  630 /*3d*/  case CMPwi: {
  631             int m = mode;
  632             int op = ArOpsFR[D_MO(opc)];
  633             // op [ebx+Ofs_EAX],#imm
  634             Gen(op, m|IMMED, DataFetchWL_U(mode,PC+1));
  635             INC_WL_PC(mode,1);
  636             }
  637             break; 
  638 /*69*/  case IMULwrm:
  639             PC += ModRM(opc, PC, mode);
  640             Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
  641             Gen(O_IMUL,mode|IMMED,DataFetchWL_S(mode,PC),REG1);
  642             INC_WL_PC(mode, 0);
  643             break;
  644 /*6b*/  case IMULbrm:
  645             PC += ModRM(opc, PC, mode);
  646             Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
  647             Gen(O_IMUL,mode|MBYTE|IMMED,(signed char)Fetch(PC),REG1);
  648             PC++;
  649             break;
  650 
  651 /*9c*/  case PUSHF: {
  652             if (V86MODE() && (IOPL<3)) {
  653                 if (CONFIG_CPUSIM) FlagSync_All();
  654 #ifdef HOST_ARCH_X86
  655                 else CODE_FLUSH();
  656 #endif
  657                 /* virtual-8086 monitor */
  658                 temp = EFLAGS & 0xdff;
  659                 if (eVEFLAGS & VIF) temp |= EFLAGS_IF;
  660                 temp |= ((eVEFLAGS & (eTSSMASK|VIF)) |
  661                 (vm86s.regs.eflags&VIP));  // this one FYI
  662                 PUSH(mode, &temp);
  663                 if (debug_level('e')>1)
  664                 e_printf("Pushed flags %08x fl=%08x vf=%08x\n",
  665                         temp,EFLAGS,eVEFLAGS);
  666 checkpic:           if (vm86s.vm86plus.force_return_for_pic &&
  667                     (eVEFLAGS & EFLAGS_IFK)) {
  668                 if (debug_level('e')>1)
  669                     e_printf("Return for PIC fl=%08x vf=%08x\n",
  670                         EFLAGS,eVEFLAGS);
  671                 TheCPU.err=EXCP_PICSIGNAL;
  672                 return PC+1;
  673                     }
  674             }
  675             else {
  676                 Gen(O_PUSH2F, mode);
  677             }
  678             PC++; }
  679             break;
  680 /*9e*/  case SAHF:
  681             Gen(O_SLAHF, mode, 1);
  682             PC++; break;
  683 /*9f*/  case LAHF:
  684             Gen(O_SLAHF, mode, 0);
  685             PC++; break;
  686 
  687 /*27*/  case DAA:
  688             Gen(O_OPAX, mode, 1, DAA); PC++; break;
  689 /*2f*/  case DAS:
  690             Gen(O_OPAX, mode, 1, DAS); PC++; break;
  691 /*37*/  case AAA:
  692             Gen(O_OPAX, mode, 1, AAA); PC++; break;
  693 /*3f*/  case AAS:
  694             Gen(O_OPAX, mode, 1, AAS); PC++; break;
  695 /*d4*/  case AAM:
  696             Gen(O_OPAX, mode, 2, AAM, Fetch(PC+1)); PC+=2; break;
  697 /*d5*/  case AAD:
  698             Gen(O_OPAX, mode, 2, AAD, Fetch(PC+1)); PC+=2; break;
  699 
  700 /*d6*/  case 0xd6:  /* Undocumented */
  701             CODE_FLUSH();
  702             e_printf("Undocumented op 0xd6\n");
  703             rAL = (EFLAGS & EFLAGS_CF? 0xff:0x00);
  704             PC++; break;
  705 /*62*/  case BOUND:
  706             CODE_FLUSH();
  707             goto not_implemented;
  708 /*63*/  case ARPL:
  709             CODE_FLUSH();
  710             goto not_implemented;
  711 
  712 /*d7*/  case XLAT:
  713             Gen(O_XLAT, mode); PC++; break;
  714 /*98*/  case CBW:
  715             Gen(O_CBWD, mode|MBYTE); PC++; break;
  716 /*99*/  case CWD:
  717             Gen(O_CBWD, mode); PC++; break;
  718 
  719 /*07*/  case POPes: if (REALADDR()) {
  720                 Gen(O_POP, mode, Ofs_ES);
  721                 AddrGen(A_SR_SH4, mode, Ofs_ES, Ofs_XES);
  722             } else { /* restartable */
  723                 unsigned short sv = 0;
  724                 CODE_FLUSH();
  725                 TOS_WORD(mode, &sv);
  726                 TheCPU.err = MAKESEG(mode, Ofs_ES, sv);
  727                 if (TheCPU.err) return P0;
  728                 POP_ONLY(mode);
  729                 TheCPU.es = sv;
  730             }
  731             PC++;
  732             break;
  733 /*17*/  case POPss: if (REALADDR()) {
  734                 Gen(O_POP, mode, Ofs_SS);
  735                 AddrGen(A_SR_SH4, mode, Ofs_SS, Ofs_XSS);
  736             } else { /* restartable */
  737                 unsigned short sv = 0;
  738                 CODE_FLUSH();
  739                 TOS_WORD(mode, &sv);
  740                 TheCPU.err = MAKESEG(mode, Ofs_SS, sv);
  741                 if (TheCPU.err) return P0;
  742                 POP_ONLY(mode);
  743                 TheCPU.ss = sv;
  744             }
  745             CEmuStat |= CeS_LOCK;
  746             PC++;
  747             break;
  748 /*1f*/  case POPds: if (REALADDR()) {
  749                 Gen(O_POP, mode, Ofs_DS);
  750                 AddrGen(A_SR_SH4, mode, Ofs_DS, Ofs_XDS);
  751             } else { /* restartable */
  752                 unsigned short sv = 0;
  753                 CODE_FLUSH();
  754                 TOS_WORD(mode, &sv);
  755                 TheCPU.err = MAKESEG(mode, Ofs_DS, sv);
  756                 if (TheCPU.err) return P0;
  757                 POP_ONLY(mode);
  758                 TheCPU.ds = sv;
  759             }
  760             PC++;
  761             break;
  762 
  763 /*26*/  case SEGes:
  764             OVERR_DS = OVERR_SS = Ofs_XES; PC++; goto override;
  765 /*2e*/  case SEGcs:     /* CS is already checked */
  766             OVERR_DS = OVERR_SS = Ofs_XCS; PC++; goto override;
  767 /*36*/  case SEGss:     /* SS is already checked */
  768             OVERR_DS = OVERR_SS = Ofs_XSS; PC++; goto override;
  769 /*3e*/  case SEGds:
  770             OVERR_DS = OVERR_SS = Ofs_XDS; PC++; goto override;
  771 /*64*/  case SEGfs:
  772             OVERR_DS = OVERR_SS = Ofs_XFS; PC++; goto override;
  773 /*65*/  case SEGgs:
  774             OVERR_DS = OVERR_SS = Ofs_XGS; PC++; goto override;
  775 /*66*/  case OPERoverride:  /* 0x66: 32 bit operand, 16 bit addressing */
  776             mode = (mode & ~DATA16) | (~basemode & DATA16);
  777             if (debug_level('e')>4)
  778                 e_printf("OPERoverride: new mode %04x\n",mode);
  779             PC++; goto override;
  780 /*67*/  case ADDRoverride:  /* 0x67: 16 bit operand, 32 bit addressing */
  781             mode = (mode & ~ADDR16) | (~basemode & ADDR16);
  782             if (debug_level('e')>4)
  783                 e_printf("ADDRoverride: new mode %04x\n",mode);
  784             PC++; goto override;
  785 
  786 /*40*/  case INCax:
  787 /*41*/  case INCcx:
  788 /*42*/  case INCdx:
  789 /*43*/  case INCbx:
  790 /*44*/  case INCsp:
  791 /*45*/  case INCbp:
  792 /*46*/  case INCsi:
  793 /*47*/  case INCdi:
  794             Gen(O_INC_R, mode, R1Tab_l[D_LO(opc)]); PC++; break;
  795 /*48*/  case DECax:
  796 /*49*/  case DECcx:
  797 /*4a*/  case DECdx:
  798 /*4b*/  case DECbx:
  799 /*4c*/  case DECsp:
  800 /*4d*/  case DECbp:
  801 /*4e*/  case DECsi:
  802 /*4f*/  case DECdi:
  803             Gen(O_DEC_R, mode, R1Tab_l[D_LO(opc)]); PC++; break;
  804 
  805 /*06*/  case PUSHes:
  806 /*0e*/  case PUSHcs:
  807 /*16*/  case PUSHss:
  808 /*1e*/  case PUSHds:
  809 /*50*/  case PUSHax:
  810 /*51*/  case PUSHcx:
  811 /*52*/  case PUSHdx:
  812 /*53*/  case PUSHbx:
  813 /*54*/  case PUSHsp:
  814 /*55*/  case PUSHbp:
  815 /*56*/  case PUSHsi:
  816 /*57*/  case PUSHdi:    opc = OpIsPush[opc];    // 1..12, 0x66=13
  817 #ifndef SINGLESTEP
  818             if (!(EFLAGS & TF))
  819             { int m = mode;     // enter with prefix
  820             Gen(O_PUSH1, m);
  821             /* optimized multiple register push */
  822             do {
  823                 Gen(O_PUSH2, m, R1Tab_l[opc-1]);
  824                 PC++; opc = OpIsPush[Fetch(PC)];
  825                 m &= ~DATA16;
  826                 if (opc==13) {  // prefix 0x66
  827                 m |= (~basemode & DATA16);
  828                 if ((opc=OpIsPush[Fetch(PC+1)])!=0) PC++;
  829                 }
  830                 else {
  831                 m |= (basemode & DATA16);
  832                 }
  833             } while (opc);
  834             Gen(O_PUSH3, m); break; }
  835 #endif
  836             Gen(O_PUSH, mode, R1Tab_l[opc-1]); PC++;
  837             break;
  838 /*68*/  case PUSHwi:
  839             Gen(O_PUSHI, mode, DataFetchWL_U(mode,(PC+1))); 
  840             INC_WL_PC(mode,1);
  841             break;
  842 /*6a*/  case PUSHbi:
  843             Gen(O_PUSHI, mode, (signed char)Fetch(PC+1)); PC+=2; break;
  844 /*60*/  case PUSHA:
  845             Gen(O_PUSHA, mode); PC++; break;
  846 /*61*/  case POPA:
  847             Gen(O_POPA, mode); PC++; break;
  848 
  849 /*58*/  case POPax:
  850 /*59*/  case POPcx:
  851 /*5a*/  case POPdx:
  852 /*5b*/  case POPbx:
  853 /*5c*/  case POPsp:
  854 /*5d*/  case POPbp:
  855 /*5e*/  case POPsi:
  856 /*5f*/  case POPdi:
  857 #ifndef SINGLESTEP
  858             if (!(EFLAGS & TF)) {
  859             int m = mode;
  860             Gen(O_POP1, m);
  861             do {
  862                 Gen(O_POP2, m, R1Tab_l[D_LO(Fetch(PC))]);
  863                 m = UNPREFIX(m);
  864                 PC++;
  865             } while ((Fetch(PC)&0xf8)==0x58);
  866             if (opc!=POPsp) Gen(O_POP3, m); break; }
  867 #endif
  868             Gen(O_POP, mode, R1Tab_l[D_LO(opc)]); PC++;
  869             break;
  870 /*8f*/  case POPrm:
  871             // pop data into temporary storage and adjust esp
  872             Gen(O_POP, mode|MEMADR);
  873             // now calculate address. This way when using %esp
  874             //  as index we use the value AFTER the pop
  875             PC += ModRM(opc, PC, mode);
  876             // store data
  877             Gen(S_DI, mode);
  878             break;
  879 
  880 /*70*/  case JO:
  881 /*71*/  case JNO:
  882 /*72*/  case JB_JNAE:
  883 /*73*/  case JNB_JAE:
  884 /*74*/  case JE_JZ:
  885 /*75*/  case JNE_JNZ:
  886 /*76*/  case JBE_JNA:
  887 /*77*/  case JNBE_JA:
  888 /*78*/  case JS:
  889 /*79*/  case JNS:
  890 /*7a*/  case JP_JPE:
  891 /*7b*/  case JNP_JPO:
  892 /*7c*/  case JL_JNGE:
  893 /*7d*/  case JNL_JGE:
  894 /*7e*/  case JLE_JNG: 
  895 /*7f*/  case JNLE_JG:   {
  896               unsigned char *p2 = JumpGen(PC, mode, (opc-JO), 0);
  897               if (TheCPU.err) return PC; else if (p2) PC = p2;
  898             }
  899             break;
  900 /*eb*/  case JMPsid:    {
  901               unsigned char *p2 = JumpGen(PC, mode, 0x10, 0);
  902               if (TheCPU.err) return PC; else if (p2) PC = p2;
  903             }
  904             break;
  905 
  906 /*e0*/  case LOOPNZ_LOOPNE: {
  907               unsigned char *p2 = JumpGen(PC, mode, 0x25, 2);
  908               if (TheCPU.err) return PC; else if (p2) PC = p2;
  909             }
  910             break;
  911 /*e1*/  case LOOPZ_LOOPE: {
  912               unsigned char *p2 = JumpGen(PC, mode, 0x24, 2);
  913               if (TheCPU.err) return PC; else if (p2) PC = p2;
  914             }
  915             break;
  916 /*e2*/  case LOOP:  {
  917               unsigned char *p2 = JumpGen(PC, mode, 0x20, 2);
  918               if (TheCPU.err) return PC; else if (p2) PC = p2;
  919             }
  920             break;
  921 /*e3*/  case JCXZ:  {
  922               unsigned char *p2 = JumpGen(PC, mode, 0x31, 2);
  923               if (TheCPU.err) return PC; else if (p2) PC = p2;
  924             }
  925             break;
  926 
  927 /*82*/  case IMMEDbrm2:     // add mem8,signed imm8: no AND,OR,XOR
  928 /*80*/  case IMMEDbrm: {
  929             int m = mode | MBYTE;
  930             int op = ArOpsR[D_MO(Fetch(PC+1))];
  931             PC += ModRM(opc, PC, m);    // DI=mem
  932             Gen(L_DI_R1, m);        // mov al,[edi]
  933             Gen(op, m|IMMED, Fetch(PC));    // op al,#imm
  934             if (op!=O_CMP_R)
  935                 Gen(S_DI, m);       // mov [edi],al mem=mem op #imm
  936             PC++; }
  937             break;
  938 /*81*/  case IMMEDwrm: {
  939             int op = ArOpsR[D_MO(Fetch(PC+1))];
  940             PC += ModRM(opc, PC, mode); // DI=mem
  941             Gen(L_DI_R1, mode);     // mov ax,[edi]
  942             Gen(op, mode|IMMED, DataFetchWL_U(mode,PC)); // op ax,#imm
  943             if (op!=O_CMP_R)
  944                 Gen(S_DI, mode);    // mov [edi],ax mem=mem op #imm
  945             INC_WL_PC(mode,0);
  946             }
  947             break;
  948 /*83*/  case IMMEDisrm: {
  949             int op = ArOpsR[D_MO(Fetch(PC+1))];
  950             long v;
  951             PC += ModRM(opc, PC, mode); // DI=mem
  952             v = (signed char)Fetch(PC);
  953             Gen(L_DI_R1, mode);     // mov ax,[edi]
  954             Gen(op, mode|IMMED, v);     // op ax,#imm
  955             if (op != O_CMP_R)
  956                 Gen(S_DI, mode);    // mov [edi],ax mem=mem op #imm
  957             PC++; }
  958             break;
  959 /*86*/  case XCHGbrm:
  960             if (RmIsReg[Fetch(PC+1)]&2) {
  961                 Gen(L_NOP, mode); PC+=2;
  962             }
  963             else {
  964                 PC += ModRM(opc, PC, mode|MBYTE);   // EDI=mem
  965                 Gen(L_DI_R1, mode|MBYTE);
  966                 Gen(O_XCHG, mode|MBYTE, REG1);
  967                 Gen(S_DI, mode|MBYTE);
  968             }
  969             break;
  970 /*87*/  case XCHGwrm:
  971             if (RmIsReg[Fetch(PC+1)]&2) {
  972                 Gen(L_NOP, mode); PC+=2;
  973             }
  974             else {
  975                 PC += ModRM(opc, PC, mode);     // EDI=mem
  976                 Gen(L_DI_R1, mode);
  977                 Gen(O_XCHG, mode, REG1);
  978                 Gen(S_DI, mode);
  979             }
  980             break;
  981 /*88*/  case MOVbfrm:
  982             if (ModGetReg1(PC, MBYTE)==3) {
  983                 Gen(L_REG2REG, MBYTE, REG1, REG3); PC+=2;
  984             } else {
  985                 PC += ModRM(opc, PC, mode|MBYTE);   // mem=reg
  986                 Gen(L_REG, mode|MBYTE, REG1);
  987                 Gen(S_DI, mode|MBYTE);
  988             }
  989             break; 
  990 /*89*/  case MOVwfrm:
  991             if (ModGetReg1(PC, mode)==3) {
  992                 Gen(L_REG2REG, mode, REG1, REG3); PC+=2;
  993             } else {
  994                 PC += ModRM(opc, PC, mode);
  995                 Gen(L_REG, mode, REG1);
  996                 Gen(S_DI, mode);
  997             }
  998             break; 
  999 /*8a*/  case MOVbtrm:
 1000             if (ModGetReg1(PC, MBYTE)==3) {
 1001                 Gen(L_REG2REG, MBYTE, REG3, REG1); PC+=2;
 1002             } else {
 1003                 PC += ModRM(opc, PC, mode|MBYTE);   // reg=mem
 1004                 Gen(L_DI_R1, mode|MBYTE);
 1005                 Gen(S_REG, mode|MBYTE, REG1);
 1006             }
 1007             break; 
 1008 /*8b*/  case MOVwtrm:
 1009             if (ModGetReg1(PC, mode)==3) {
 1010                 Gen(L_REG2REG, mode, REG3, REG1); PC+=2;
 1011             } else {
 1012                 PC += ModRM(opc, PC, mode);
 1013                 Gen(L_DI_R1, mode);
 1014                 Gen(S_REG, mode, REG1);
 1015             }
 1016             break; 
 1017 /*8c*/  case MOVsrtrm:
 1018             PC += ModRM(opc, PC, mode|SEGREG);
 1019             Gen(L_REG, mode|DATA16, REG1);
 1020             if (REG1==Ofs_SS) CEmuStat |= CeS_LOCK;
 1021             //Gen(L_ZXAX, mode);
 1022             Gen(S_DI, mode|DATA16);
 1023             break; 
 1024 /*8d*/  case LEA:
 1025             PC += ModRM(opc, PC, mode|MLEA);
 1026             Gen(S_DI_R, mode, REG1);
 1027             break; 
 1028 
 1029 /*c4*/  case LES:
 1030             if (REALADDR()) {
 1031                 PC += ModRM(opc, PC, mode);
 1032                 Gen(L_LXS1, mode, REG1);
 1033                 Gen(L_LXS2, mode, Ofs_ES, Ofs_XES);
 1034             }
 1035             else {
 1036                 unsigned short sv = 0;
 1037                 unsigned long rv;
 1038                 CODE_FLUSH();
 1039                 PC += ModRMSim(PC, mode);
 1040                 rv = DataGetWL_U(mode,TheCPU.mem_ref);
 1041                 TheCPU.mem_ref += BT24(BitDATA16, mode);
 1042                 sv = GetDWord(TheCPU.mem_ref);
 1043                 TheCPU.err = MAKESEG(mode, Ofs_ES, sv);
 1044                 if (TheCPU.err) return P0;
 1045                 SetCPU_WL(mode, REG1, rv);
 1046                 TheCPU.es = sv;
 1047             }
 1048             break;
 1049 /*c5*/  case LDS:
 1050             if (REALADDR()) {
 1051                 PC += ModRM(opc, PC, mode);
 1052                 Gen(L_LXS1, mode, REG1);
 1053                 Gen(L_LXS2, mode, Ofs_DS, Ofs_XDS);
 1054             }
 1055             else {
 1056                 unsigned short sv = 0;
 1057                 unsigned long rv;
 1058                 CODE_FLUSH();
 1059                 PC += ModRMSim(PC, mode);
 1060                 rv = DataGetWL_U(mode,TheCPU.mem_ref);
 1061                 TheCPU.mem_ref += BT24(BitDATA16, mode);
 1062                 sv = GetDWord(TheCPU.mem_ref);
 1063                 TheCPU.err = MAKESEG(mode, Ofs_DS, sv);
 1064                 if (TheCPU.err) return P0;
 1065                 SetCPU_WL(mode, REG1, rv);
 1066                 TheCPU.ds = sv;
 1067             }
 1068             break;
 1069 /*8e*/  case MOVsrfrm:
 1070             if (REALADDR()) {
 1071                 PC += ModRM(opc, PC, mode|SEGREG);
 1072                 Gen(L_DI_R1, mode|DATA16);
 1073                 Gen(S_REG, mode|DATA16, REG1);
 1074                 AddrGen(A_SR_SH4, mode, REG1, e_ofsseg[REG1>>2]);
 1075             }
 1076             else {
 1077                 unsigned short sv = 0;
 1078                 CODE_FLUSH();
 1079                 PC += ModRMSim(PC, mode|SEGREG);
 1080                 sv = GetDWord(TheCPU.mem_ref);
 1081                 TheCPU.err = MAKESEG(mode, REG1, sv);
 1082                 if (TheCPU.err) return P0;
 1083                 switch (REG1) {
 1084                 case Ofs_DS: TheCPU.ds=sv; break;
 1085                 case Ofs_SS: TheCPU.ss=sv;
 1086                     CEmuStat |= CeS_LOCK;
 1087                     break;
 1088                 case Ofs_ES: TheCPU.es=sv; break;
 1089                 case Ofs_FS: TheCPU.fs=sv; break;
 1090                 case Ofs_GS: TheCPU.gs=sv; break;
 1091                 default: goto illegal_op;
 1092                 }
 1093             }
 1094             break; 
 1095 
 1096 /*9b*/  case oWAIT:
 1097 /*90*/  case NOP:   //if (!IsCodeInBuf()) Gen(L_NOP, mode);
 1098             if (CurrIMeta<0) Gen(L_NOP, mode); else TheCPU.mode|=SKIPOP;
 1099             PC++;
 1100             if (!(EFLAGS & TF))
 1101                 while (Fetch(PC)==NOP) PC++;
 1102             break;
 1103 /*91*/  case XCHGcx:
 1104 /*92*/  case XCHGdx:
 1105 /*93*/  case XCHGbx:
 1106 /*94*/  case XCHGsp:
 1107 /*95*/  case XCHGbp:
 1108 /*96*/  case XCHGsi:
 1109 /*97*/  case XCHGdi:
 1110             Gen(O_XCHG_R, mode, Ofs_EAX, R1Tab_l[D_LO(opc)]); 
 1111             PC++; break;
 1112 
 1113 /*a0*/  case MOVmal:
 1114             AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1));
 1115             Gen(L_DI_R1, mode|MBYTE);
 1116             Gen(S_REG, mode|MBYTE, Ofs_AL);
 1117             INC_WL_PCA(mode,1);
 1118             break;
 1119 /*a1*/  case MOVmax:
 1120             AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1));
 1121             Gen(L_DI_R1, mode);
 1122             Gen(S_REG, mode, Ofs_EAX);
 1123             INC_WL_PCA(mode,1);
 1124             break;
 1125 /*a2*/  case MOValm:
 1126             AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1));
 1127             Gen(L_REG, mode|MBYTE, Ofs_AL);
 1128             Gen(S_DI, mode|MBYTE);
 1129             INC_WL_PCA(mode,1);
 1130             break;
 1131 /*a3*/  case MOVaxm:
 1132             AddrGen(A_DI_0, mode|IMMED, OVERR_DS, AddrFetchWL_U(mode,PC+1));
 1133             Gen(L_REG, mode, Ofs_EAX);
 1134             Gen(S_DI, mode);
 1135             INC_WL_PCA(mode,1);
 1136             break;
 1137 
 1138 /*a4*/  case MOVSb: {   int m = mode|(MBYTE|MOVSSRC|MOVSDST);
 1139             Gen(O_MOVS_SetA, m);
 1140             Gen(O_MOVS_MovD, m);
 1141             Gen(O_MOVS_SavA, m);
 1142             PC++;
 1143             } break;
 1144 /*a5*/  case MOVSw: {   int m = mode|(MOVSSRC|MOVSDST);
 1145             Gen(O_MOVS_SetA, m);
 1146 #ifndef SINGLESTEP
 1147             /* optimize common sequence MOVSw..MOVSw..MOVSb */
 1148             if (!(EFLAGS & TF)) {
 1149                 do {
 1150                     Gen(O_MOVS_MovD, m);
 1151                     m = UNPREFIX(m);
 1152                     PC++;
 1153                 } while (Fetch(PC) == MOVSw);
 1154                 if (Fetch(PC) == MOVSb) {
 1155                     Gen(O_MOVS_MovD, m|MBYTE);
 1156                     PC++;
 1157                 }
 1158             } else
 1159 #endif
 1160             {
 1161                 Gen(O_MOVS_MovD, m); PC++;
 1162             }
 1163             Gen(O_MOVS_SavA, m);
 1164             } break;
 1165 /*a6*/  case CMPSb: {   int m = mode|(MBYTE|MOVSSRC|MOVSDST);
 1166             Gen(O_MOVS_SetA, m);
 1167             Gen(O_MOVS_CmpD, m);
 1168             Gen(O_MOVS_SavA, m);
 1169             PC++; } break;
 1170 /*a7*/  case CMPSw: {   int m = mode|(MOVSSRC|MOVSDST);
 1171             Gen(O_MOVS_SetA, m);
 1172             Gen(O_MOVS_CmpD, m);
 1173             Gen(O_MOVS_SavA, m);
 1174             PC++; } break;
 1175 /*aa*/  case STOSb: {   int m = mode|(MBYTE|MOVSDST);
 1176             Gen(O_MOVS_SetA, m);
 1177             Gen(L_REG, m, Ofs_AL);
 1178             Gen(O_MOVS_StoD, m);
 1179             Gen(O_MOVS_SavA, m);
 1180             PC++; } break;
 1181 /*ab*/  case STOSw: {   int m = mode|MOVSDST;
 1182             Gen(O_MOVS_SetA, m);
 1183             Gen(L_REG, m, Ofs_EAX);
 1184 #ifndef SINGLESTEP
 1185             if (!(EFLAGS & TF)) do {
 1186                 Gen(O_MOVS_StoD, m);
 1187                 m = UNPREFIX(m);
 1188                 PC++;
 1189             } while (Fetch(PC) == STOSw); else
 1190 #endif
 1191             {
 1192                 Gen(O_MOVS_StoD, m); PC++;
 1193             }
 1194             Gen(O_MOVS_SavA, m);
 1195             } break;
 1196 /*ac*/  case LODSb: {   int m = mode|(MBYTE|MOVSSRC);
 1197             Gen(O_MOVS_SetA, m);
 1198             Gen(O_MOVS_LodD, m);
 1199             Gen(S_REG, m, Ofs_AL); PC++;
 1200 #ifndef SINGLESTEP
 1201             /* optimize common sequence LODSb-STOSb */
 1202             if (!(EFLAGS & TF) && Fetch(PC) == STOSb) {
 1203                 Gen(O_MOVS_SetA, (m&ADDR16)|MOVSDST);
 1204                 Gen(O_MOVS_StoD, m);
 1205                 m |= MOVSDST;
 1206                 PC++;
 1207             }
 1208 #endif
 1209             Gen(O_MOVS_SavA, m);
 1210             } break;
 1211 /*ad*/  case LODSw: {   int m = mode|MOVSSRC;
 1212             Gen(O_MOVS_SetA, m);
 1213             Gen(O_MOVS_LodD, m);
 1214             Gen(S_REG, m, Ofs_EAX); PC++;
 1215 #ifndef SINGLESTEP
 1216             /* optimize common sequence LODSw-STOSw */
 1217             if (!(EFLAGS & TF) && Fetch(PC) == STOSw) {
 1218                 Gen(O_MOVS_SetA, (m&ADDR16)|MOVSDST);
 1219                 Gen(O_MOVS_StoD, m);
 1220                 m |= MOVSDST;
 1221                 PC++;
 1222             }
 1223 #endif
 1224             Gen(O_MOVS_SavA, m);
 1225             } break;
 1226 /*ae*/  case SCASb: {   int m = mode|(MBYTE|MOVSDST);
 1227             Gen(O_MOVS_SetA, m);
 1228             Gen(L_REG, m, Ofs_AL);
 1229             Gen(O_MOVS_ScaD, m);
 1230             Gen(O_MOVS_SavA, m);
 1231             PC++; } break;
 1232 /*af*/  case SCASw: {   int m = mode|MOVSDST;
 1233             Gen(O_MOVS_SetA, m);
 1234             Gen(L_REG, m, Ofs_EAX);
 1235             Gen(O_MOVS_ScaD, m);
 1236             Gen(O_MOVS_SavA, m);
 1237             PC++; } break;
 1238 
 1239 /*b0*/  case MOVial:
 1240 /*b1*/  case MOVicl:
 1241 /*b2*/  case MOVidl:
 1242 /*b3*/  case MOVibl:
 1243 /*b4*/  case MOViah:
 1244 /*b5*/  case MOVich:
 1245 /*b6*/  case MOVidh:
 1246 /*b7*/  case MOVibh:
 1247             Gen(L_IMM, mode|MBYTE, SEL_B_X(D_LO(opc)), Fetch(PC+1));
 1248             PC += 2; break;
 1249 /*b8*/  case MOViax:
 1250 /*b9*/  case MOVicx:
 1251 /*ba*/  case MOVidx:
 1252 /*bb*/  case MOVibx:
 1253 /*bc*/  case MOVisp:
 1254 /*bd*/  case MOVibp:
 1255 /*be*/  case MOVisi:
 1256 /*bf*/  case MOVidi:
 1257             Gen(L_IMM, mode, R1Tab_l[D_LO(opc)], DataFetchWL_U(mode,PC+1));
 1258             INC_WL_PC(mode, 1); break;
 1259 
 1260 /*d0*/  case SHIFTb:
 1261 /*d2*/  case SHIFTbv:
 1262 /*c0*/  case SHIFTbi: {
 1263             int m = mode | MBYTE;
 1264             unsigned char count = 0;
 1265             PC += ModRM(opc, PC, m);
 1266             if (opc==SHIFTb) { m |= IMMED; count = 1; }
 1267             else if (opc==SHIFTbi) {
 1268                 m |= IMMED; count = Fetch(PC)&0x1f; PC++;
 1269             }
 1270             switch (REG1) {
 1271             case Ofs_AL:    /*0*/   // ROL
 1272                 Gen(O_ROL, m, count);
 1273                 break;
 1274             case Ofs_CL:    /*1*/   // ROR
 1275                 Gen(O_ROR, m, count);
 1276                 break;
 1277             case Ofs_DL:    /*2*/   // RCL
 1278                 Gen(O_RCL, m, count);
 1279                 break;
 1280             case Ofs_BL:    /*3*/   // RCR
 1281                 Gen(O_RCR, m, count);
 1282                 break;
 1283             case Ofs_DH:    /*6*/   // undoc
 1284                 if (opc==SHIFTbv) {
 1285                     CODE_FLUSH();
 1286                     goto illegal_op;
 1287                 }
 1288             case Ofs_AH:    /*4*/   // SHL,SAL
 1289                 Gen(O_SHL, m, count);
 1290                 break;
 1291             case Ofs_CH:    /*5*/   // SHR
 1292                 Gen(O_SHR, m, count);
 1293                 break;
 1294             case Ofs_BH:    /*7*/   // SAR
 1295                 Gen(O_SAR, m, count);
 1296                 break;
 1297             }
 1298         }
 1299         break;
 1300 /*d1*/  case SHIFTw:
 1301 /*d3*/  case SHIFTwv:
 1302 /*c1*/  case SHIFTwi: {
 1303             int m = mode;
 1304             unsigned char count = 0;
 1305             PC += ModRM(opc, PC, m);
 1306             if (opc==SHIFTw) { m |= IMMED; count = 1; }
 1307             else if (opc==SHIFTwi) {
 1308                 m |= IMMED; count = Fetch(PC)&0x1f; PC++;
 1309             }
 1310             switch (REG1) {
 1311             case Ofs_AX:    /*0*/   // ROL
 1312                 Gen(O_ROL, m, count);
 1313                 break;
 1314             case Ofs_CX:    /*1*/   // ROR
 1315                 Gen(O_ROR, m, count);
 1316                 break;
 1317             case Ofs_DX:    /*2*/   // RCL
 1318                 Gen(O_RCL, m, count);
 1319                 break;
 1320             case Ofs_BX:    /*3*/   // RCR
 1321                 Gen(O_RCR, m, count);
 1322                 break;
 1323             case Ofs_SI:    /*6*/   // undoc
 1324                 if ((opc==SHIFTw)||(opc==SHIFTwv)) {
 1325                     CODE_FLUSH();
 1326                     goto illegal_op;
 1327                 }
 1328             case Ofs_SP:    /*4*/   // SHL,SAL
 1329                 Gen(O_SHL, m, count);
 1330                 break;
 1331             case Ofs_BP:    /*5*/   // SHR
 1332                 Gen(O_SHR, m, count);
 1333                 break;
 1334             case Ofs_DI:    /*7*/   // SAR
 1335                 Gen(O_SAR, m, count);
 1336                 break;
 1337             }
 1338         }
 1339         break;
 1340 
 1341 /*e9*/  case JMPd: {
 1342             unsigned char *p2 = JumpGen(PC, mode, 0x10, 4);
 1343             if (TheCPU.err) return PC; else if (p2) PC = p2;
 1344            }
 1345            break;
 1346 /*e8*/  case CALLd: {
 1347             unsigned char *p2 = JumpGen(PC, mode, 0x11, 4);
 1348             if (TheCPU.err) return PC; else if (p2) PC = p2;
 1349            }
 1350            break;
 1351 
 1352 /*9a*/  case CALLl:
 1353 /*ea*/  case JMPld: {
 1354             unsigned short jcs,ocs;
 1355             unsigned long oip,xcs,jip=0;
 1356             CODE_FLUSH();
 1357             /* get new cs:ip */
 1358             jip = AddrFetchWL_U(mode, PC+1);
 1359             INC_WL_PCA(mode,1);
 1360             jcs = AddrFetchWL_U(mode, PC);
 1361             INC_WL_PCA(mode,0);
 1362             /* check if new cs is valid, save old for error */
 1363             ocs = TheCPU.cs;
 1364             xcs = LONG_CS;
 1365             TheCPU.err = MAKESEG(mode, Ofs_CS, jcs);
 1366             if (TheCPU.err) {
 1367                 TheCPU.cs = ocs; LONG_CS = xcs; // should not change
 1368                 return P0;
 1369             }
 1370             if (opc==CALLl) {
 1371                 /* ok, now push old cs:eip */
 1372                 oip = (long)PC - xcs;
 1373                 PUSH(mode, &ocs);
 1374                 PUSH(mode, &oip);
 1375                 if (debug_level('e')>2)
 1376                 e_printf("CALL_FAR: ret=%04x:%08lx\n  calling:      %04x:%08lx\n",
 1377                     ocs,oip,jcs,jip);
 1378             }
 1379             else {
 1380                 if (debug_level('e')>2)
 1381                 e_printf("JMP_FAR: %04x:%08lx\n",jcs,jip);
 1382             }
 1383             TheCPU.eip = jip;
 1384             PC = (unsigned char *)(LONG_CS + jip);
 1385 #ifdef SKIP_EMU_VBIOS
 1386             if ((jcs&0xf000)==config.vbios_seg) {
 1387                 /* return the new PC after the jump */
 1388                 TheCPU.err = EXCP_GOBACK; return PC;
 1389             }
 1390 #endif
 1391             }
 1392             break;
 1393 
 1394 /*c2*/  case RETisp: {
 1395             int dr;
 1396             CODE_FLUSH();
 1397             dr = (signed short)FetchW(PC+1);
 1398             POP(mode, &TheCPU.eip);
 1399             if (debug_level('e')>2)
 1400                 e_printf("RET: ret=%08x inc_sp=%d\n",TheCPU.eip,dr);
 1401             temp = rESP + dr;
 1402             rESP = (temp&TheCPU.StackMask) | (rESP&~TheCPU.StackMask);
 1403             PC = (unsigned char *)(uintptr_t)(LONG_CS + TheCPU.eip); }
 1404             break;
 1405 /*c3*/  case RET:
 1406             CODE_FLUSH();
 1407             POP(mode, &TheCPU.eip);
 1408             if (debug_level('e')>2) e_printf("RET: ret=%08x\n",TheCPU.eip);
 1409             PC = (unsigned char *)(uintptr_t)(LONG_CS + TheCPU.eip);
 1410             break;
 1411 /*c6*/  case MOVbirm:
 1412             PC += ModRM(opc, PC, mode|MBYTE);
 1413             Gen(S_DI_IMM, mode|MBYTE, Fetch(PC));
 1414             PC++; break;
 1415 /*c7*/  case MOVwirm:
 1416             PC += ModRM(opc, PC, mode);
 1417             Gen(S_DI_IMM, mode, DataFetchWL_U(mode,PC));
 1418             INC_WL_PC(mode,0);
 1419             break;
 1420 /*c8*/  case ENTER: {
 1421             unsigned int sp, bp, frm;
 1422             int level, ds;
 1423             CODE_FLUSH();
 1424             level = Fetch(PC+3) & 0x1f;
 1425             ds = BT24(BitDATA16, mode);
 1426             sp = LONG_SS + ((rESP - ds) & TheCPU.StackMask);
 1427             bp = LONG_SS + (rEBP & TheCPU.StackMask);
 1428             PUSH(mode, &rEBP);
 1429             frm = sp - LONG_SS;
 1430             if (level) {
 1431                 sp -= ds*level;
 1432                 while (--level) {
 1433                     bp -= ds;
 1434                     PUSH(mode, (void *)(uintptr_t)bp);
 1435                 }
 1436                 PUSH(mode, &frm);
 1437             }
 1438             if (mode&DATA16) rBP = frm; else rEBP = frm;
 1439             sp -= FetchW(PC+1);
 1440             temp = sp - LONG_SS;
 1441             rESP = (temp&TheCPU.StackMask) | (rESP&~TheCPU.StackMask);
 1442             PC += 4; }
 1443             break;
 1444 /*c9*/  case LEAVE:
 1445             Gen(O_LEAVE, mode); PC++;
 1446             break;
 1447 /*ca*/  case RETlisp: { /* restartable */
 1448             unsigned long dr, sv=0;
 1449             CODE_FLUSH();
 1450             NOS_WORD(mode, &sv);
 1451             dr = AddrFetchWL_U(mode,PC+1);
 1452             TheCPU.err = MAKESEG(mode, Ofs_CS, sv);
 1453             if (TheCPU.err) return P0;
 1454             TheCPU.eip=0; POP(mode, &TheCPU.eip);
 1455             POP_ONLY(mode);
 1456             if (debug_level('e')>2)
 1457                 e_printf("RET_%ld: ret=%08x\n",dr,TheCPU.eip);
 1458             PC = (unsigned char *)(uintptr_t)(LONG_CS + TheCPU.eip);
 1459             temp = rESP + dr;
 1460             rESP = (temp&TheCPU.StackMask) | (rESP&~TheCPU.StackMask);
 1461             }
 1462             break;
 1463 /*cc*/  case INT3:
 1464             CODE_FLUSH();
 1465             e_printf("Interrupt 03\n");
 1466             TheCPU.err=EXCP03_INT3; PC++;
 1467             return PC;
 1468 /*ce*/  case INTO:
 1469             CODE_FLUSH();
 1470             e_printf("Overflow interrupt 04\n");
 1471             TheCPU.err=EXCP04_INTO;
 1472             return P0;
 1473 /*cd*/  case INT:
 1474             CODE_FLUSH();
 1475 #ifdef ASM_DUMP
 1476             fprintf(aLog,"%08lx:\t\tint %02x\n",(long)P0,Fetch(PC+1));
 1477 #endif
 1478             if (Fetch(PC+1)==0x31) InvalidateSegs();
 1479             goto not_permitted;
 1480             break;
 1481 
 1482 /*cb*/  case RETl:
 1483 /*cf*/  case IRET: {    /* restartable */
 1484             long sv=0;
 1485             int m = mode;
 1486             CODE_FLUSH();
 1487             NOS_WORD(m, &sv);   /* get segment */
 1488             TheCPU.err = MAKESEG(m, Ofs_CS, sv);
 1489             if (TheCPU.err) return P0;
 1490             TheCPU.eip=0; POP(m, &TheCPU.eip);
 1491             POP_ONLY(m);
 1492             PC = (unsigned char *)(uintptr_t)(LONG_CS + TheCPU.eip);
 1493             if (opc==RETl) {
 1494                 if (debug_level('e')>1)
 1495                 e_printf("RET_FAR: ret=%04lx:%08x\n",sv,TheCPU.eip);
 1496                 break;  /* un-fall */
 1497             }
 1498             if (debug_level('e')>1) {
 1499                 e_printf("IRET: ret=%04lx:%08x\n",sv,TheCPU.eip);
 1500             }
 1501             temp=0; POP(m, &temp);
 1502             if (REALMODE())
 1503                 FLAGS = temp;
 1504             else if (V86MODE()) {
 1505                 goto stack_return_from_vm86;
 1506             }
 1507             else {
 1508                 /* if (EFLAGS&EFLAGS_NT) goto task_return */
 1509                 /* if (temp&EFLAGS_VM) goto stack_return_to_vm86 */
 1510                 /* else stack_return */
 1511                 int amask = (CPL==0? 0:EFLAGS_IOPL_MASK) | 2;
 1512                 if (mode & DATA16)
 1513                 FLAGS = (FLAGS&amask) | ((temp&0x7fd7)&~amask);
 1514                 else    /* should use eTSSMASK */
 1515                 EFLAGS = (EFLAGS&amask) |
 1516                      ((temp&(eTSSMASK|0xfd7))&~amask);
 1517                 if (debug_level('e')>1)
 1518                 e_printf("Popped flags %08x->{r=%08x v=%08x}\n",temp,EFLAGS,get_vFLAGS(EFLAGS));
 1519             }
 1520             if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 1521             } break;
 1522 
 1523 /*9d*/  case POPF: {
 1524             CODE_FLUSH();
 1525             temp=0; POP(mode, &temp);
 1526             if (V86MODE()) {
 1527 stack_return_from_vm86:
 1528                 if (debug_level('e')>1)
 1529                 e_printf("Popped flags %08x fl=%08x vf=%08x\n",
 1530                     temp,EFLAGS,eVEFLAGS);
 1531                 if (IOPL==3) {  /* Intel manual */
 1532                 if (mode & DATA16)
 1533                     FLAGS = temp;   /* oh,really? */
 1534                 else
 1535                     EFLAGS = (temp&~0x1b3000) | (EFLAGS&0x1b3000);
 1536                 }
 1537                 else {
 1538                 /* virtual-8086 monitor */
 1539                 if (vm86s.vm86plus.vm86dbg_active &&
 1540                     vm86s.vm86plus.vm86dbg_TFpendig) {
 1541                     temp |= TF;
 1542                 }
 1543                 /* move TSSMASK from pop{e}flags to V{E}FLAGS */
 1544                 eVEFLAGS = (eVEFLAGS & ~eTSSMASK) | (temp & eTSSMASK);
 1545                 /* move 0xdd5 from pop{e}flags to regs->eflags */
 1546                 EFLAGS = (EFLAGS & ~0xdd5) | (temp & 0xdd5);
 1547                 if (temp & EFLAGS_IF) {
 1548                     eVEFLAGS |= EFLAGS_VIF;
 1549                         if (vm86s.regs.eflags & VIP) {
 1550                     if (debug_level('e')>1)
 1551                         e_printf("Return for STI fl=%08x vf=%08x\n",
 1552                             EFLAGS,eVEFLAGS);
 1553                     TheCPU.err=EXCP_STISIGNAL;
 1554                     return PC + (opc==POPF);
 1555                     }
 1556                 }
 1557                 if (vm86s.vm86plus.force_return_for_pic &&
 1558                     (eVEFLAGS & EFLAGS_IFK)) {
 1559                     if (debug_level('e')>1)
 1560                     e_printf("Return for PIC fl=%08x vf=%08x\n",
 1561                             EFLAGS,eVEFLAGS);
 1562                     TheCPU.err=EXCP_PICSIGNAL;
 1563                     return PC + (opc==POPF);
 1564                 }
 1565                 }
 1566             }
 1567             else {
 1568                 int amask = (CPL==0? 0:EFLAGS_IOPL_MASK) |
 1569                         (CPL<=IOPL? 0:EFLAGS_IF) |
 1570                         (EFLAGS_VM|EFLAGS_RF) | 2;
 1571                 if (mode & DATA16)
 1572                 FLAGS = (FLAGS&amask) | ((temp&0x7fd7)&~amask);
 1573                 else
 1574                 EFLAGS = (EFLAGS&amask) |
 1575                      ((temp&(eTSSMASK|0xfd7))&~amask);
 1576                 if (in_dpmi) {
 1577                 if (temp & EFLAGS_IF)
 1578                     set_IF();
 1579                 else {
 1580                     clear_IF();
 1581                 }
 1582                 }
 1583                 if (debug_level('e')>1)
 1584                 e_printf("Popped flags %08x->{r=%08x v=%08x}\n",temp,EFLAGS,_EFLAGS);
 1585             }
 1586             if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 1587             if (opc==POPF) PC++; }
 1588             break;
 1589 
 1590 /*f2*/  case REPNE:
 1591 /*f3*/  case REP: /* also is REPE */ {
 1592             unsigned char repop; int repmod;
 1593             PC++;
 1594             repmod = mode | (opc==REPNE? MREPNE:MREP);
 1595 repag0:
 1596             repop = Fetch(PC);
 1597             switch (repop) {
 1598                 case INSb:
 1599                 case INSw:
 1600                 case OUTSb:
 1601                 case OUTSw:
 1602                     CODE_FLUSH();
 1603                     goto not_permitted;
 1604                 case LODSb:
 1605                     repmod |= (MBYTE|MOVSSRC);
 1606                     Gen(O_MOVS_SetA, repmod);
 1607                     Gen(O_MOVS_LodD, repmod);
 1608                     Gen(S_REG, repmod, Ofs_AL);
 1609                     Gen(O_MOVS_SavA, repmod);
 1610                     PC++; break;
 1611                 case LODSw:
 1612                     repmod |= MOVSSRC;
 1613                     Gen(O_MOVS_SetA, repmod);
 1614                     Gen(O_MOVS_LodD, repmod);
 1615                     Gen(S_REG, repmod, Ofs_AX);
 1616                     Gen(O_MOVS_SavA, repmod);
 1617                     PC++; break;
 1618                 case MOVSb:
 1619                     repmod |= (MBYTE|MOVSSRC|MOVSDST);
 1620                     Gen(O_MOVS_SetA, repmod);
 1621                     Gen(O_MOVS_MovD, repmod);
 1622                     Gen(O_MOVS_SavA, repmod);
 1623                     PC++; break;
 1624                 case MOVSw:
 1625                     repmod |= (MOVSSRC|MOVSDST);
 1626                     Gen(O_MOVS_SetA, repmod);
 1627                     Gen(O_MOVS_MovD, repmod);
 1628                     Gen(O_MOVS_SavA, repmod);
 1629                     PC++; break;
 1630                 case CMPSb:
 1631                     repmod |= (MBYTE|MOVSSRC|MOVSDST|MREPCOND);
 1632                     Gen(O_MOVS_SetA, repmod);
 1633                     Gen(O_MOVS_CmpD, repmod);
 1634                     Gen(O_MOVS_SavA, repmod);
 1635                     PC++; break;
 1636                 case CMPSw:
 1637                     repmod |= (MOVSSRC|MOVSDST|MREPCOND);
 1638                     Gen(O_MOVS_SetA, repmod);
 1639                     Gen(O_MOVS_CmpD, repmod);
 1640                     Gen(O_MOVS_SavA, repmod);
 1641                     PC++; break;
 1642                 case STOSb:
 1643                     repmod |= (MBYTE|MOVSDST);
 1644                     Gen(O_MOVS_SetA, repmod);
 1645                     Gen(L_REG, repmod|MBYTE, Ofs_AL);
 1646                     Gen(O_MOVS_StoD, repmod);
 1647                     Gen(O_MOVS_SavA, repmod);
 1648                     PC++; break;
 1649                 case STOSw:
 1650                     repmod |= MOVSDST;
 1651                     Gen(O_MOVS_SetA, repmod);
 1652                     Gen(L_REG, repmod, Ofs_EAX);
 1653                     Gen(O_MOVS_StoD, repmod);
 1654                     Gen(O_MOVS_SavA, repmod);
 1655                     PC++; break;
 1656                 case SCASb:
 1657                     repmod |= (MBYTE|MOVSDST|MREPCOND);
 1658                     Gen(O_MOVS_SetA, repmod);
 1659                     Gen(L_REG, repmod|MBYTE, Ofs_AL);
 1660                     Gen(O_MOVS_ScaD, repmod);
 1661                     Gen(O_MOVS_SavA, repmod);
 1662                     PC++; break;
 1663                 case SCASw:
 1664                     repmod |= MOVSDST|MREPCOND;
 1665                     Gen(O_MOVS_SetA, repmod);
 1666                     Gen(L_REG, repmod, Ofs_EAX);
 1667                     Gen(O_MOVS_ScaD, repmod);
 1668                     Gen(O_MOVS_SavA, repmod);
 1669                     PC++; break;
 1670                 case SEGes:
 1671                     OVERR_DS = OVERR_SS = Ofs_XES; PC++; goto repag0;
 1672                 case SEGcs:
 1673                     OVERR_DS = OVERR_SS = Ofs_XCS; PC++; goto repag0;
 1674                 case SEGss:
 1675                     OVERR_DS = OVERR_SS = Ofs_XSS; PC++; goto repag0;
 1676                 case SEGds:
 1677                     OVERR_DS = OVERR_SS = Ofs_XDS; PC++; goto repag0;
 1678                 case SEGfs:
 1679                     OVERR_DS = OVERR_SS = Ofs_XFS; PC++; goto repag0;
 1680                 case SEGgs:
 1681                     OVERR_DS = OVERR_SS = Ofs_XGS; PC++; goto repag0;
 1682                 case OPERoverride:
 1683                     repmod = (repmod & ~DATA16) | (~basemode & DATA16);
 1684                     if (debug_level('e')>4)
 1685                         e_printf("OPERoverride: new mode %04x\n",repmod);
 1686                     PC++; goto repag0;
 1687                 case ADDRoverride:
 1688                     repmod = (repmod & ~ADDR16) | (~basemode & ADDR16);
 1689                     if (debug_level('e')>4)
 1690                         e_printf("ADDRoverride: new mode %04x\n",repmod);
 1691                     PC++; goto repag0;
 1692             } }
 1693             break;
 1694 /*f4*/  case HLT:
 1695             CODE_FLUSH();
 1696             goto not_permitted;
 1697 /*f5*/  case CMC:   PC++;
 1698             if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1))
 1699                 EFLAGS ^= EFLAGS_CF;
 1700             else
 1701                 Gen(O_SETFL, mode, CMC);
 1702             break;
 1703 /*f6*/  case GRP1brm: {
 1704             PC += ModRM(opc, PC, mode|MBYTE);   // EDI=mem
 1705             Gen(L_DI_R1, mode|MBYTE);       // mov al,[edi]
 1706             switch(REG1) {
 1707             case Ofs_AL:    /*0*/   /* TEST */
 1708             case Ofs_CL:    /*1*/   /* undocumented */
 1709                 Gen(O_AND_R, mode|MBYTE|IMMED, Fetch(PC));  // op al,#imm
 1710                 PC++;
 1711                 break;
 1712             case Ofs_DL:    /*2*/   /* NOT */
 1713                 Gen(O_NOT, mode|MBYTE);         // not al
 1714                 Gen(S_DI, mode|MBYTE);
 1715                 break;
 1716             case Ofs_BL:    /*3*/   /* NEG */
 1717                 Gen(O_NEG, mode|MBYTE);         // neg al
 1718                 Gen(S_DI, mode|MBYTE);
 1719                 break;
 1720             case Ofs_AH:    /*4*/   /* MUL AL */
 1721                 Gen(O_MUL, mode|MBYTE);         // al*[edi]->AX unsigned
 1722                 break;
 1723             case Ofs_CH:    /*5*/   /* IMUL AL */
 1724                 Gen(O_IMUL, mode|MBYTE);        // al*[edi]->AX signed
 1725                 break;
 1726             case Ofs_DH:    /*6*/   /* DIV AL */
 1727                 Gen(O_DIV, mode|MBYTE, P0);         // ah:al/[edi]->AH:AL unsigned
 1728                 break;
 1729             case Ofs_BH:    /*7*/   /* IDIV AL */
 1730                 Gen(O_IDIV, mode|MBYTE, P0);        // ah:al/[edi]->AH:AL signed
 1731                 break;
 1732             } }
 1733             break;
 1734 /*f7*/  case GRP1wrm: {
 1735             PC += ModRM(opc, PC, mode);         // EDI=mem
 1736             Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
 1737             switch(REG1) {
 1738             case Ofs_AX:    /*0*/   /* TEST */
 1739             case Ofs_CX:    /*1*/   /* undocumented */
 1740                 Gen(O_AND_R, mode|IMMED, DataFetchWL_U(mode,PC));   // op al,#imm
 1741                 INC_WL_PC(mode,0);
 1742                 break;
 1743             case Ofs_DX:    /*2*/   /* NOT */
 1744                 Gen(O_NOT, mode);           // not (e)ax
 1745                 Gen(S_DI, mode);
 1746                 break;
 1747             case Ofs_BX:    /*3*/   /* NEG */
 1748                 Gen(O_NEG, mode);           // neg (e)ax
 1749                 Gen(S_DI, mode);
 1750                 break;
 1751             case Ofs_SP:    /*4*/   /* MUL AX */
 1752                 Gen(O_MUL, mode);           // (e)ax*[edi]->(E)DX:(E)AX unsigned
 1753                 break;
 1754             case Ofs_BP:    /*5*/   /* IMUL AX */
 1755                 Gen(O_IMUL, mode);          // (e)ax*[edi]->(E)DX:(E)AX signed
 1756                 break;
 1757             case Ofs_SI:    /*6*/   /* DIV AX+DX */
 1758                 Gen(O_DIV, mode, P0);       // (e)ax:(e)dx/[edi]->(E)AX:(E)DX unsigned
 1759                 break;
 1760             case Ofs_DI:    /*7*/   /* IDIV AX+DX */
 1761                 Gen(O_IDIV, mode, P0);      // (e)ax:(e)dx/[edi]->(E)AX:(E)DX signed
 1762                 break;
 1763             } }
 1764             break;
 1765 /*f8*/  case CLC:   PC++;
 1766             if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1))
 1767                 EFLAGS &= ~EFLAGS_CF;
 1768             else
 1769                 Gen(O_SETFL, mode, CLC);
 1770             break;
 1771 /*f9*/  case STC:   PC++;
 1772             if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1))
 1773                 EFLAGS |= EFLAGS_CF;
 1774             else
 1775                 Gen(O_SETFL, mode, STC);
 1776             break;
 1777 /*fa*/  case CLI:
 1778             CODE_FLUSH();
 1779             if (REALMODE() || (CPL <= IOPL) || (IOPL==3)) {
 1780                 EFLAGS &= ~EFLAGS_IF;
 1781             }
 1782             else {
 1783                 /* virtual-8086 monitor */
 1784                 if (V86MODE()) {
 1785                 if (debug_level('e')>2) e_printf("Virtual VM86 CLI\n");
 1786                 eVEFLAGS &= ~EFLAGS_VIF;
 1787                 goto checkpic;
 1788                 }
 1789                 else if (in_dpmi) {
 1790                 if (debug_level('e')>2) e_printf("Virtual DPMI CLI\n");
 1791                 clear_IF();
 1792                 }
 1793                 else
 1794                 goto not_permitted; /* GPF */
 1795             }
 1796             PC++;
 1797             break;
 1798 /*fb*/  case STI:
 1799             CODE_FLUSH();
 1800             if (V86MODE()) {    /* traps always (Intel man) */
 1801                 /* virtual-8086 monitor */
 1802                 if (debug_level('e')>2) e_printf("Virtual VM86 STI\n");
 1803                 eVEFLAGS |= EFLAGS_VIF;
 1804                 if (vm86s.regs.eflags & VIP) {
 1805                     if (debug_level('e')>1)
 1806                     e_printf("Return for STI fl=%08x vf=%08x\n",
 1807                             EFLAGS,eVEFLAGS);
 1808                     TheCPU.err=EXCP_STISIGNAL;
 1809                     return PC+1;
 1810                 }
 1811             }
 1812             else {
 1813                 if (REALMODE() || (CPL <= IOPL) || (IOPL==3)) {
 1814                 EFLAGS |= EFLAGS_IF;
 1815                 }
 1816                 else if (in_dpmi) {
 1817                 if (debug_level('e')>2) e_printf("Virtual DPMI STI\n");
 1818                 set_IF();
 1819                 }
 1820                 else
 1821                 goto not_permitted; /* GPF */
 1822             }
 1823             PC++;
 1824             break;
 1825 /*fc*/  case CLD:   PC++;
 1826             if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1))
 1827                 EFLAGS &= ~EFLAGS_DF;
 1828             else
 1829                 Gen(O_SETFL, mode, CLD);
 1830             break;
 1831 /*fd*/  case STD:   PC++;
 1832             if ((CurrIMeta<0)&&(InterOps[Fetch(PC)]&1))
 1833                 EFLAGS |= EFLAGS_DF;
 1834             else
 1835                 Gen(O_SETFL, mode, STD);
 1836             break;
 1837 /*fe*/  case GRP2brm:   /* only INC and DEC are legal on bytes */
 1838             ModGetReg1(PC, mode);
 1839             switch(REG1) {
 1840             case Ofs_AL:    /*0*/
 1841                 if (PC[1] >= 0xc0) {
 1842                     Gen(O_INC_R, mode|MBYTE,
 1843                         R1Tab_b[PC[1] & 7]);
 1844                     PC += 2;
 1845                     break;
 1846                 }
 1847                 PC += ModRM(opc, PC, mode|MBYTE); // EDI=mem
 1848                 Gen(L_DI_R1, mode|MBYTE);
 1849                 Gen(O_INC, mode|MBYTE);
 1850                 Gen(S_DI, mode|MBYTE);
 1851                 break;
 1852             case Ofs_CL:    /*1*/
 1853                 if (PC[1] >= 0xc8) {
 1854                     Gen(O_DEC_R, mode|MBYTE,
 1855                         R1Tab_b[PC[1] & 7]);
 1856                     PC += 2;
 1857                     break;
 1858                 }
 1859                 PC += ModRM(opc, PC, mode|MBYTE); // EDI=mem
 1860                 Gen(L_DI_R1, mode|MBYTE);
 1861                 Gen(O_DEC, mode|MBYTE);
 1862                 Gen(S_DI, mode|MBYTE);
 1863                 break;
 1864             default:
 1865                 CODE_FLUSH();
 1866                 goto illegal_op;
 1867             }
 1868             break;
 1869 /*ff*/  case GRP2wrm:
 1870             ModGetReg1(PC, mode);
 1871             switch (REG1) {
 1872             case Ofs_AX:    /*0*/
 1873                 /* it's not worth optimizing for registers
 1874                    here (single byte DEC/INC exist) */
 1875                 PC += ModRM(opc, PC, mode);
 1876                 Gen(L_DI_R1, mode);
 1877                 Gen(O_INC, mode);
 1878                 Gen(S_DI, mode);
 1879                 break;
 1880             case Ofs_CX:    /*1*/
 1881                 PC += ModRM(opc, PC, mode);
 1882                 Gen(L_DI_R1, mode);
 1883                 Gen(O_DEC, mode);
 1884                 Gen(S_DI, mode);
 1885                 break;
 1886             case Ofs_SP:    /*4*/    // JMP near indirect
 1887             case Ofs_DX: {  /*2*/    // CALL near indirect
 1888                     int dp;
 1889                     CODE_FLUSH();
 1890                     PC += ModRMSim(PC, mode|NOFLDR);
 1891                     TheCPU.eip = (long)PC - LONG_CS;
 1892                     dp = DataGetWL_U(mode, TheCPU.mem_ref);
 1893                     if (REG1==Ofs_DX) { 
 1894                         PUSH(mode, &TheCPU.eip);
 1895                         if (debug_level('e')>2)
 1896                             e_printf("CALL indirect: ret=%08x\n\tcalling: %08x\n",
 1897                                 TheCPU.eip,dp);
 1898                     }
 1899                     PC = (unsigned char *)(uintptr_t)(LONG_CS + dp);
 1900                 }
 1901                 break;
 1902             case Ofs_BX:    /*3*/    // CALL long indirect restartable
 1903             case Ofs_BP: {  /*5*/    // JMP long indirect restartable
 1904                     unsigned short ocs,jcs;
 1905                     unsigned long oip,xcs,jip=0;
 1906                     CODE_FLUSH();
 1907                     PC += ModRMSim(PC, mode|NOFLDR);
 1908                     TheCPU.eip = (long)PC - LONG_CS;
 1909                     /* get new cs:ip */
 1910                     jip = DataGetWL_U(mode, TheCPU.mem_ref);
 1911                     jcs = GetDWord(TheCPU.mem_ref+BT24(BitDATA16,mode));
 1912                     /* check if new cs is valid, save old for error */
 1913                     ocs = TheCPU.cs;
 1914                     xcs = LONG_CS;
 1915                     TheCPU.err = MAKESEG(mode, Ofs_CS, jcs);
 1916                     if (TheCPU.err) {
 1917                         TheCPU.cs = ocs; LONG_CS = xcs; // should not change
 1918                         return P0;
 1919                     }
 1920                     if (REG1==Ofs_BX) {
 1921                         /* ok, now push old cs:eip */
 1922                         oip = (long)PC - xcs;
 1923                         PUSH(mode, &ocs);
 1924                         PUSH(mode, &oip);
 1925                         if (debug_level('e')>2)
 1926                         e_printf("CALL_FAR indirect: ret=%04x:%08lx\n\tcalling: %04x:%08lx\n",
 1927                             ocs,oip,jcs,jip);
 1928                     }
 1929                     else {
 1930                         if (debug_level('e')>2)
 1931                         e_printf("JMP_FAR indirect: %04x:%08lx\n",jcs,jip);
 1932                     }
 1933                     TheCPU.eip = jip;
 1934                     PC = (unsigned char *)(uintptr_t)(LONG_CS + jip);
 1935 #ifdef SKIP_EMU_VBIOS
 1936                     if ((jcs&0xf000)==config.vbios_seg) {
 1937                         /* return the new PC after the jump */
 1938                         TheCPU.err = EXCP_GOBACK; return PC;
 1939                     }
 1940 #endif
 1941                 }
 1942                 break;
 1943             case Ofs_SI:    /*6*/    // PUSH
 1944                 PC += ModRM(opc, PC, mode);
 1945                 Gen(O_PUSH, mode|MEMADR); break;    // push [mem]
 1946                 break;
 1947             default:
 1948                 CODE_FLUSH();
 1949                 goto illegal_op;
 1950             }
 1951             break;
 1952 
 1953 /*6c*/  case INSb: {
 1954             unsigned short a;
 1955             unsigned long rd;
 1956             CODE_FLUSH();
 1957             a = rDX;
 1958             rd = (mode&ADDR16? rDI:rEDI);
 1959             if (test_ioperm(a))
 1960                 ((char *)(uintptr_t)LONG_ES)[rd] = port_real_inb(a);
 1961             else
 1962                 ((char *)(uintptr_t)LONG_ES)[rd] = port_inb(a);
 1963             if (EFLAGS & EFLAGS_DF) rd--; else rd++;
 1964             if (mode&ADDR16) rDI=rd; else rEDI=rd;
 1965             PC++; } break;
 1966 /*ec*/  case INvb: {
 1967             unsigned short a;
 1968             CODE_FLUSH();
 1969             a = rDX;
 1970             if (config.X && (a>=0x3c0) && (a<=0x3df)) {
 1971               switch(a&0x1f) {
 1972                 // [012.456789a.c.ef....45....a.....]
 1973                 case 0x00:  /*ATTRIBUTE_INDEX*/
 1974                 case 0x01:  /*ATTRIBUTE_DATA*/
 1975                 case 0x02:  /*INPUT_STATUS_0*/
 1976                 case 0x04:  /*SEQUENCER_INDEX*/
 1977                 case 0x05:  /*SEQUENCER_DATA*/
 1978                 case 0x06:  /*DAC_PEL_MASK*/
 1979                 case 0x07:  /*DAC_STATE*/
 1980                 case 0x08:  /*DAC_WRITE_INDEX*/
 1981                 case 0x09:  /*DAC_DATA*/
 1982                 case 0x0a:  /*FEATURE_CONTROL_R*/
 1983                 case 0x0c:  /*MISC_OUTPUT_R*/
 1984                 case 0x0e:  /*GFX_INDEX*/
 1985                 case 0x0f:  /*GFX_DATA*/
 1986                 case 0x14:  /*CRTC_INDEX*/
 1987                 case 0x15:  /*CRTC_DATA*/
 1988                 case 0x1a:  /*INPUT_STATUS_1*/
 1989                 rAL = VGA_emulate_inb(a);
 1990                 break;
 1991                 default: dbug_printf("not emulated EC %x\n",a);
 1992                 leavedos(0);
 1993               }
 1994               PC++; break;
 1995             }
 1996 #ifdef TRAP_RETRACE
 1997             if (a==0x3da) {     // video retrace bits
 1998                 /* bit 0 = DE  bit 3 = VR
 1999                  * display=0 hor.retr.=1 ver.retr.=9 */
 2000                 int c1 = *((int *)(PC+1));
 2001                 int c2 = *((int *)(PC+5));
 2002                 int tp = test_ioperm(a) & 1;
 2003                 dbug_printf("IN 3DA %08lx %08lx PP=%d\n",c1,c2,tp);
 2004                 if (c1==0xfb7408a8) {
 2005                 // 74 fb = wait for VR==1
 2006                 if (tp==0) set_ioperm(a,1,1);
 2007                 while (((rAL=port_real_inb(a))&8)==0);
 2008                 if (tp==0) set_ioperm(a,1,0);
 2009                 PC+=5; break;
 2010                 }
 2011                 //else if (c1==0xfb7508a8) {
 2012                 // 75 fb = wait for VR==0
 2013                 //}
 2014                 //else if (c1==0xfbe008a8) {
 2015                 // e0 fb = loop while VR==1
 2016                 //unsigned int rcx = mode&DATA16? rCX:rECX;
 2017                 //if (tp==0) set_ioperm(a,1,1);
 2018                 //while ((((rAL=port_real_inb(a))&8)!=0) && rcx)
 2019                 //    rcx--;
 2020                 //if (tp==0) set_ioperm(a,1,0);
 2021                 //if (mode&DATA16) rCX=rcx; else rECX=rcx;
 2022                 //PC+=5; break;
 2023                 //}
 2024                 else if (c1==0xfbe108a8) {
 2025                 // e1 fb = loop while VR==0
 2026                 unsigned int rcx = mode&DATA16? rCX:rECX;
 2027                 if (tp==0) set_ioperm(a,1,1);
 2028                 while ((((rAL=port_real_inb(a))&8)==0) && rcx)
 2029                     rcx--;
 2030                 if (tp==0) set_ioperm(a,1,0);
 2031                 if (mode&DATA16) rCX=rcx; else rECX=rcx;
 2032                 PC+=5; break;
 2033                 }
 2034                 else if (((c1&0xfffff6ff)==0xc0080024) &&
 2035                 ((c2&0xfffffffe)==0xf4eb0274)) {
 2036                 // 74 02 eb f4 = wait for HR,VR==0
 2037                 // 75 02 eb f4 = wait for HR,VR==1
 2038                 register unsigned char amk = Fetch(PC+1);
 2039                 if (amk==8) {
 2040                     if (tp==0) set_ioperm(a,1,1);
 2041                     if (PC[5]&1)
 2042                     while (((rAL=port_real_inb(a))&amk)==0);
 2043                     else
 2044                     while (((rAL=port_real_inb(a))&amk)!=0);
 2045                     if (tp==0) set_ioperm(a,1,0);
 2046                 }
 2047                 else
 2048                     rAL = (PC[5]&1? amk:0);
 2049                 PC+=9; break;
 2050                 }
 2051             }
 2052 #endif
 2053             if (test_ioperm(a)) {
 2054 #ifdef CPUEMU_DIRECT_IO
 2055                 Gen(O_INPDX, mode|MBYTE); NewNode=1;
 2056 #else
 2057                 rAL = port_real_inb(a);
 2058 #endif
 2059             }
 2060             else
 2061                 rAL = port_inb(a);
 2062             }
 2063             PC++; break;
 2064 /*e4*/  case INb: {
 2065             unsigned short a;
 2066             CODE_FLUSH();
 2067             E_TIME_STRETCH;     // for PIT
 2068             /* there's no reason to compile this, as most of
 2069              * the ports under 0x100 are emulated by dosemu */
 2070             a = Fetch(PC+1);
 2071             if (test_ioperm(a)) rAL = port_real_inb(a);
 2072                 else rAL = port_inb(a);
 2073             PC += 2; } break;
 2074 /*6d*/  case INSw: {
 2075             unsigned long rd;
 2076             void *p;
 2077             int dp;
 2078             CODE_FLUSH();
 2079             rd = (mode&ADDR16? rDI:rEDI);
 2080             p = (void *)(LONG_ES+rd);
 2081             if (mode&DATA16) {
 2082                 *((short *)p) = port_inw(rDX); dp=2;
 2083             }
 2084             else {
 2085                 *((int *)p) = port_ind(rDX); dp=4;
 2086             }
 2087             if (EFLAGS & EFLAGS_DF) rd-=dp; else rd+=dp;
 2088             if (mode&ADDR16) rDI=rd; else rEDI=rd;
 2089             PC++; } break;
 2090 /*ed*/  case INvw: {
 2091             CODE_FLUSH();
 2092             if (config.X && (rDX>=0x3c0) && (rDX<=0x3de)) {
 2093                 dbug_printf("X: INW,IND %x in VGA space\n",rDX);
 2094                 leavedos(0);
 2095             }
 2096             if (mode&DATA16) rAX = port_inw(rDX);
 2097             else rEAX = port_ind(rDX);
 2098             } PC++; break;
 2099 /*e5*/  case INw: {
 2100             unsigned short a;
 2101             CODE_FLUSH();
 2102             a = Fetch(PC+1);
 2103             if (mode&DATA16) rAX = port_inw(a); else rEAX = port_ind(a);
 2104             PC += 2; } break;
 2105 
 2106 /*6e*/  case OUTSb: {
 2107             unsigned short a;
 2108             unsigned long rs;
 2109             int iop;
 2110             CODE_FLUSH();
 2111             a = rDX;
 2112             rs = (mode&ADDR16? rSI:rESI);
 2113             iop = test_ioperm(a);
 2114             do {
 2115                 if (iop)
 2116                 port_real_outb(a,((char *)(uintptr_t)LONG_DS)[rs]);
 2117                 else
 2118                 port_outb(a,((char *)(uintptr_t)LONG_DS)[rs]);
 2119                 if (EFLAGS & EFLAGS_DF) rs--; else rs++;
 2120                 PC++;
 2121             } while (Fetch(PC)==OUTSb);
 2122             if (mode&ADDR16) rSI=rs; else rESI=rs;
 2123             } break;
 2124 /*ee*/  case OUTvb: {
 2125             unsigned short a;
 2126             CODE_FLUSH();
 2127             a = rDX;
 2128             if (config.X && (a>=0x3c0) && (a<=0x3df)) {
 2129               switch(a&0x1f) {
 2130                 // [0.2.456789....e.....45...9a.....]
 2131                 case 0x00:  /*ATTRIBUTE_INDEX*/
 2132                 case 0x02:  /*MISC_OUTPUT_W*/
 2133                 case 0x04:  /*SEQUENCER_INDEX*/
 2134                 case 0x05:  /*SEQUENCER_DATA*/
 2135                 case 0x06:  /*DAC_PEL_MASK*/
 2136                 case 0x07:  /*DAC_READ_INDEX*/
 2137                 case 0x08:  /*DAC_WRITE_INDEX*/
 2138                 case 0x09:  /*DAC_DATA*/
 2139                 case 0x0e:  /*GFX_INDEX*/
 2140                 case 0x0f:  /*GFX_DATA*/
 2141                 case 0x14:  /*CRTC_INDEX*/
 2142                 case 0x15:  /*CRTC_DATA*/
 2143                 case 0x19:  /*COLOR_SELECT*/
 2144                 case 0x1a:  /*FEATURE_CONTROL_W*/
 2145                 VGA_emulate_outb(a,rAL);
 2146                 break;
 2147                 default: dbug_printf("not emulated EE %x\n",a);
 2148                 leavedos(0);
 2149               }
 2150               PC++; break;
 2151             }
 2152             if (test_ioperm(a)) {
 2153 #ifdef CPUEMU_DIRECT_IO
 2154                 Gen(O_OUTPDX, mode|MBYTE); NewNode=1;
 2155 #else
 2156                 port_real_outb(a,rAL);
 2157 #endif
 2158             }
 2159             else
 2160                 port_outb(a,rAL);
 2161             }
 2162             PC++; break;
 2163 /*e6*/  case OUTb:  {
 2164             unsigned short a;
 2165             CODE_FLUSH();
 2166             a = Fetch(PC+1);
 2167             if ((a&0xfc)==0x40) E_TIME_STRETCH; // for PIT
 2168             /* there's no reason to compile this, as most of
 2169              * the ports under 0x100 are emulated by dosemu */
 2170             if (test_ioperm(a)) port_real_outb(a,rAL);
 2171                 else port_outb(a,rAL);
 2172             PC += 2; } break;
 2173 /*6f*/  case OUTSw:
 2174             CODE_FLUSH();
 2175             goto not_implemented;
 2176 /*ef*/  case OUTvw: {
 2177             unsigned short a;
 2178             CODE_FLUSH();
 2179             a = rDX;
 2180             if (config.X && (a>=0x3c0) && (a<=0x3de)) {
 2181               if (mode&DATA16) {
 2182                 switch(a&0x1f) {
 2183                   // [....456789..........45..........]
 2184                   case 0x04:    /*SEQUENCER_INDEX*/
 2185                   case 0x06:    /*DAC_PEL_MASK*/
 2186                   case 0x08:    /*DAC_WRITE_INDEX*/
 2187                   case 0x0e:    /*GFX_INDEX*/
 2188                   case 0x14:    /*CRTC_INDEX*/
 2189                 VGA_emulate_outw(a,rAX);
 2190                 break;
 2191                   default: dbug_printf("not emulated EF %x\n",a);
 2192                 leavedos(0);
 2193                 }
 2194               }
 2195               else {
 2196                 dbug_printf("X: OUTD %x in VGA space\n",a);
 2197                 leavedos(0);
 2198               }
 2199               PC++; break;
 2200             }
 2201             if (test_ioperm(a)) {
 2202 #ifdef CPUEMU_DIRECT_IO
 2203                 Gen(O_OUTPDX, mode); NewNode=1;
 2204 #else
 2205                 if (mode&DATA16) port_real_outw(a,rAX); else port_real_outd(a,rEAX);
 2206 #endif
 2207             }
 2208             else {
 2209                 if (mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX);
 2210             } }
 2211             PC++; break;
 2212 
 2213 /*e7*/  case OUTw:  {
 2214             unsigned short a;
 2215             CODE_FLUSH();
 2216             a = Fetch(PC+1);
 2217             if (test_ioperm(a)) {
 2218                 if (mode&DATA16) port_real_outw(a,rAX); else port_real_outd(a,rEAX);
 2219             }
 2220             else {
 2221                 if (mode&DATA16) port_outw(a,rAX); else port_outd(a,rEAX);
 2222             }
 2223             PC += 2; } break;
 2224 
 2225 /*d8*/  case ESC0:
 2226 /*d9*/  case ESC1:
 2227 /*da*/  case ESC2:
 2228 /*db*/  case ESC3:
 2229 /*dc*/  case ESC4:
 2230 /*dd*/  case ESC5:
 2231 /*de*/  case ESC6:
 2232 /*df*/  case ESC7:  {
 2233             unsigned char b=Fetch(PC+1);
 2234             // extended opcode
 2235             // 1101.1ooo xxeeerrr -> eeeooo,rrr
 2236             // D8 -> 00,08,10,18...38
 2237             // DF -> 07,0f,17,1f...3f
 2238             int exop = (b & 0x38) | (opc & 7);
 2239             int sim = 0;
 2240             if ((b&0xc0)==0xc0) {
 2241                 exop |= 0x40;
 2242                 if (exop==0x63) {
 2243                     CODE_FLUSH(); sim=1;
 2244                 }
 2245                 PC += 2;
 2246             }
 2247             else {
 2248                 if ((exop&0xeb)==0x21) {
 2249                     CODE_FLUSH();
 2250                     PC += ModRMSim(PC, mode|NOFLDR);
 2251                     b = mode; sim=1;
 2252                 }
 2253                 else {
 2254                     PC += ModRM(opc, PC, mode|NOFLDR);
 2255                 }
 2256             }
 2257             b &= 7;
 2258             TheCPU.mode |= M_FPOP;
 2259             if (sim) {
 2260                 if (Fp87_op(exop,b)) { TheCPU.err = -96; return P0; }
 2261             }
 2262             else
 2263                 Gen(O_FOP, mode, exop, b);
 2264             }
 2265             break;
 2266 
 2267 /*0f*/  case TwoByteESC: {
 2268             unsigned char opc2 = Fetch(PC+1);
 2269             switch (opc2) {
 2270 //
 2271             case 0x00: { /* GRP6 - Extended Opcode 20 */
 2272                 unsigned char opm = D_MO(Fetch(PC+2));
 2273                 switch (opm) {
 2274                 case 0: /* SLDT */
 2275                 case 1: /* STR */
 2276                     /* Store Task Register */
 2277                 case 2: /* LLDT */
 2278                     /* Load Local Descriptor Table Register */
 2279                 case 3: /* LTR */
 2280                     /* Load Task Register */
 2281                 case 4: { /* VERR */
 2282                     unsigned short sv; int tmp;
 2283                     CODE_FLUSH();
 2284                     if (REALMODE()) goto illegal_op;
 2285                     PC += ModRMSim(PC+1, mode) + 1;
 2286                     sv = GetDWord(TheCPU.mem_ref);
 2287                     tmp = hsw_verr(sv);
 2288                     if (tmp < 0) goto illegal_op;
 2289                     EFLAGS &= ~EFLAGS_ZF;
 2290                     if (tmp) EFLAGS |= EFLAGS_ZF;
 2291                     if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 2292                     }
 2293                     break;
 2294                 case 5: { /* VERW */
 2295                     unsigned short sv; int tmp;
 2296                     CODE_FLUSH();
 2297                     if (REALMODE()) goto illegal_op;
 2298                     PC += ModRMSim(PC+1, mode) + 1;
 2299                     sv = GetDWord(TheCPU.mem_ref);
 2300                     tmp = hsw_verw(sv);
 2301                     if (tmp < 0) goto illegal_op;
 2302                     EFLAGS &= ~EFLAGS_ZF;
 2303                     if (tmp) EFLAGS |= EFLAGS_ZF;
 2304                     if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 2305                     }
 2306                     break;
 2307                 case 6: /* JMP indirect to IA64 code */
 2308                 case 7: /* Illegal */
 2309                     CODE_FLUSH();
 2310                     goto illegal_op;
 2311                 } }
 2312                 break;
 2313             case 0x01: { /* GRP7 - Extended Opcode 21 */
 2314                 unsigned char opm = D_MO(Fetch(PC+2));
 2315                 switch (opm) {
 2316                 case 0: /* SGDT */
 2317                     /* Store Global Descriptor Table Register */
 2318                 case 1: /* SIDT */
 2319                     /* Store Interrupt Descriptor Table Register */
 2320                 case 2: /* LGDT */ /* PM privileged AND real mode */
 2321                     /* Load Global Descriptor Table Register */
 2322                 case 3: /* LIDT */ /* PM privileged AND real mode */
 2323                     /* Load Interrupt Descriptor Table Register */
 2324                 case 4: /* SMSW, 80286 compatibility */
 2325                     /* Store Machine Status Word */
 2326                     PC++; PC += ModRM(opc, PC, mode);
 2327                     Gen(L_CR0, mode);
 2328                     Gen(S_DI, mode|DATA16);
 2329                     break;
 2330                 case 5: /* Illegal */
 2331                 case 6: /* LMSW, 80286 compatibility, Privileged */
 2332                     /* Load Machine Status Word */
 2333                 case 7: /* Illegal */
 2334                     CODE_FLUSH();
 2335                     goto illegal_op;
 2336                 } }
 2337                 break;
 2338 
 2339             case 0x02:   /* LAR */ /* Load Access Rights Byte */
 2340             case 0x03: { /* LSL */ /* Load Segment Limit */
 2341                 unsigned short sv; int tmp;
 2342                 CODE_FLUSH();
 2343                 if (REALMODE()) goto illegal_op;
 2344                 PC += ModRMSim(PC+1, mode) + 1;
 2345                 sv = GetDWord(TheCPU.mem_ref);
 2346                 if (!e_larlsl(mode, sv)) {
 2347                     EFLAGS &= ~EFLAGS_ZF;
 2348                     if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 2349                 }
 2350                 else {
 2351                     if (opc2==0x02) {   /* LAR */
 2352                     tmp = GetSelectorFlags(sv);
 2353                     if (mode&DATA16) tmp &= 0xff;
 2354                     tmp <<= 8;
 2355                     if (tmp) SetFlagAccessed(sv);
 2356                     }
 2357                     else {      /* LSL */
 2358                     tmp = GetSelectorByteLimit(sv);
 2359                     }
 2360                     EFLAGS |= EFLAGS_ZF;
 2361                     if (CONFIG_CPUSIM) RFL.valid = V_INVALID;
 2362                     SetCPU_WL(mode, REG1, tmp);
 2363                 } }
 2364                 break;
 2365 
 2366             /* case 0x04:   LOADALL */
 2367             /* case 0x05:   LOADALL(286) - SYSCALL(K6) */
 2368             case 0x06: /* CLTS */ /* Privileged */
 2369                 /* Clear Task State Register */
 2370                 CODE_FLUSH();
 2371                 if (CPL != 0) goto not_permitted;
 2372                 TheCPU.cr[0] &= ~8;
 2373                 PC += 2; break;
 2374             /* case 0x07:   LOADALL(386) - SYSRET(K6) etc. */
 2375             case 0x08: /* INVD */
 2376                 /* INValiDate cache */
 2377             case 0x09: /* WBINVD */
 2378                 /* Write-Back and INValiDate cache */
 2379                 PC += 2; break;
 2380             case 0x0a:
 2381             case 0x0b:
 2382                 CODE_FLUSH();
 2383                 goto illegal_op;    /* UD2 */
 2384             /* case 0x0d:   Code Extension 25(AMD-3D) */
 2385             /* case 0x0e:   FEMMS(K6-3D) */
 2386             case 0x0f:  /* AMD-3D */
 2387             /* case 0x10-0x1f:  various V20/MMX instr. */
 2388                 CODE_FLUSH();
 2389                 goto not_implemented;
 2390             case 0x20:   /* MOVcdrd */ /* Privileged */
 2391             case 0x22:   /* MOVrdcd */ /* Privileged */
 2392             case 0x21:   /* MOVddrd */ /* Privileged */
 2393             case 0x23:   /* MOVrddd */ /* Privileged */
 2394             case 0x24:   /* MOVtdrd */ /* Privileged */
 2395             case 0x26: { /* MOVrdtd */ /* Privileged */
 2396                 int *srg; int reg; unsigned char b,opd;
 2397                 CODE_FLUSH();
 2398                 if (REALMODE()) goto not_permitted;
 2399                 b = Fetch(PC+2);
 2400                 if (D_HO(b)!=3) goto illegal_op;
 2401                 reg = D_MO(b); b = D_LO(b);
 2402                 if ((b==4)||(b==5)) goto illegal_op;
 2403                 srg = (int *)CPUOFFS(R1Tab_l[b]);
 2404                 opd = Fetch(PC+1)&2;
 2405                     if (opc2&1) {
 2406                     if (opd) TheCPU.dr[reg] = *srg;
 2407                     else *srg = TheCPU.dr[reg];
 2408                     }
 2409                     else if (opc2&4) {
 2410                     reg-=6; if (reg<0) goto illegal_op;
 2411                     if (opd) TheCPU.tr[reg] = *srg;
 2412                     else *srg = TheCPU.tr[reg];
 2413                     }
 2414                     else {
 2415                     if ((reg==1)||(reg>4)) goto illegal_op;
 2416                         if (opd) {  /* write to CRs */
 2417                     if (reg==0) {
 2418                             if ((TheCPU.cr[0] ^ *srg) & 1) {
 2419                         dbug_printf("RM/PM switch not allowed\n");
 2420                         TheCPU.err = -94; return P0;
 2421                         }
 2422                             TheCPU.cr[0] = (*srg&0xe005002f)|0x10;
 2423                     }
 2424                     else TheCPU.cr[reg] = *srg;
 2425                         } else {
 2426                     *srg = TheCPU.cr[reg];
 2427                         }
 2428                     }
 2429                     } PC += 3; break;
 2430             case 0x30: /* WRMSR */
 2431                 CODE_FLUSH();
 2432                 goto not_implemented;
 2433 
 2434             case 0x31: /* RDTSC */
 2435                 Gen(O_RDTSC, mode);
 2436                 PC+=2; break;
 2437             case 0x32: /* RDMSR */
 2438                 CODE_FLUSH();
 2439                 goto not_implemented;
 2440 
 2441             /* case 0x33:   RDPMC(P6) */
 2442             /* case 0x34:   SYSENTER(PII) */
 2443             /* case 0x35:   SYSEXIT(PII) */
 2444             /* case 0x40-0x4f:  CMOV(P6) */
 2445             /* case 0x50-0x5f:  various Cyrix/MMX */
 2446             case 0x60 ... 0x6b: /* MMX */
 2447             case 0x6e: case 0x6f:
 2448             case 0x74 ... 0x77:
 2449             /* case 0x78-0x7e:  Cyrix */
 2450             case 0x7e: case 0x7f:
 2451                 CODE_FLUSH();
 2452                 goto not_implemented;
 2453 //
 2454             case 0x80: /* JOimmdisp */
 2455             case 0x81: /* JNOimmdisp */
 2456             case 0x82: /* JBimmdisp */
 2457             case 0x83: /* JNBimmdisp */
 2458             case 0x84: /* JZimmdisp */
 2459             case 0x85: /* JNZimmdisp */
 2460             case 0x86: /* JBEimmdisp */
 2461             case 0x87: /* JNBEimmdisp */
 2462             case 0x88: /* JSimmdisp */
 2463             case 0x89: /* JNSimmdisp */
 2464             case 0x8a: /* JPimmdisp */
 2465             case 0x8b: /* JNPimmdisp */
 2466             case 0x8c: /* JLimmdisp */
 2467             case 0x8d: /* JNLimmdisp */
 2468             case 0x8e: /* JLEimmdisp */
 2469             case 0x8f: /* JNLEimmdisp */
 2470                 {
 2471                   unsigned char *p2 = JumpGen(PC, mode, (opc2-0x80), 1);
 2472                   if (TheCPU.err) return PC; else if (p2) PC = p2;
 2473                 }
 2474                 break;
 2475 ///
 2476             case 0x90: /* SETObrm */
 2477             case 0x91: /* SETNObrm */
 2478             case 0x92: /* SETBbrm */
 2479             case 0x93: /* SETNBbrm */
 2480             case 0x94: /* SETZbrm */
 2481             case 0x95: /* SETNZbrm */
 2482             case 0x96: /* SETBEbrm */
 2483             case 0x97: /* SETNBEbrm */
 2484             case 0x98: /* SETSbrm */
 2485             case 0x99: /* SETNSbrm */
 2486             case 0x9a: /* SETPbrm */
 2487             case 0x9b: /* SETNPbrm */
 2488             case 0x9c: /* SETLbrm */
 2489             case 0x9d: /* SETNLbrm */
 2490             case 0x9e: /* SETLEbrm */
 2491             case 0x9f: /* SETNLEbrm */
 2492                 PC++; PC += ModRM(opc, PC, mode|MBYTE);
 2493                 Gen(O_SETCC, mode, (opc2&0x0f));
 2494                 break;
 2495 ///
 2496             case 0xa0: /* PUSHfs */
 2497                 Gen(O_PUSH, mode, Ofs_FS); PC+=2;
 2498                 break;
 2499             case 0xa1: /* POPfs */
 2500                 if (REALADDR()) {
 2501                     Gen(O_POP, mode, Ofs_FS);
 2502                     AddrGen(A_SR_SH4, mode, Ofs_FS, Ofs_XFS);
 2503                 } else { /* restartable */
 2504                     unsigned short sv = 0;
 2505                     CODE_FLUSH();
 2506                     TOS_WORD(mode, &sv);
 2507                     TheCPU.err = MAKESEG(mode, Ofs_FS, sv);
 2508                     if (TheCPU.err) return P0;
 2509                     POP_ONLY(mode);
 2510                     TheCPU.fs = sv;
 2511                 }
 2512                 PC+=2;
 2513                 break;
 2514 ///
 2515             case 0xa2: /* CPUID */
 2516                 CODE_FLUSH();
 2517                 if (rEAX==0) {
 2518                     rEAX = 1; rEBX = 0x756e6547;
 2519                     rECX = 0x6c65746e; rEDX = 0x49656e69;
 2520                 }
 2521                 else if (rEAX==1) {
 2522                     rEAX = 0x052c; rEBX = rECX = 0;
 2523                     rEDX = 0x1bf;
 2524                 }
 2525                 PC+=2; break;
 2526 
 2527             case 0xa3: /* BT */
 2528             case 0xab: /* BTS */
 2529             case 0xb3: /* BTR */
 2530             case 0xbb: /* BTC */
 2531             case 0xbc: /* BSF */
 2532             case 0xbd: /* BSR */
 2533                 PC++; PC += ModRM(opc, PC, mode);
 2534                 Gen(O_BITOP, mode, (opc2-0xa0), REG1);
 2535                 break;
 2536             case 0xba: { /* GRP8 - Code Extension 22 */
 2537                 unsigned char opm = (Fetch(PC+2))&0x38;
 2538                 switch (opm) {
 2539                 case 0x00: /* Illegal */
 2540                 case 0x08: /* Illegal */
 2541                 case 0x10: /* Illegal */
 2542                 case 0x18: /* Illegal */
 2543                     CODE_FLUSH();
 2544                     goto illegal_op;
 2545                 case 0x20: /* BT */
 2546                 case 0x28: /* BTS */
 2547                 case 0x30: /* BTR */
 2548                 case 0x38: /* BTC */
 2549                     PC++; PC += ModRM(opc, PC, mode);
 2550                     Gen(O_BITOP, mode, opm, Fetch(PC));
 2551                     PC++;
 2552                     break;
 2553                 } }
 2554                 break;
 2555 
 2556             case 0xa4: /* SHLDimm */
 2557                 /* Double Precision Shift Left by IMMED */
 2558             case 0xa5: /* SHLDcl */
 2559                 /* Double Precision Shift Left by CL */
 2560             case 0xac: /* SHRDimm */
 2561                 /* Double Precision Shift Left by IMMED */
 2562             case 0xad: /* SHRDcl */
 2563                 /* Double Precision Shift Left by CL */
 2564                 PC++; PC += ModRM(opc, PC, mode);
 2565                 if (opc2&1) {
 2566                     Gen(O_SHFD, mode, (opc2&8), REG1);
 2567                 }
 2568                 else {
 2569                     Gen(O_SHFD, mode|IMMED, (opc2&8), REG1, Fetch(PC));
 2570                     PC++;
 2571                 }
 2572                 break;
 2573 
 2574             case 0xa6: /* CMPXCHGb */
 2575             case 0xa7: /* CMPXCHGw */
 2576                 CODE_FLUSH();
 2577                 goto not_implemented;
 2578 ///
 2579             case 0xa8: /* PUSHgs */
 2580                 Gen(O_PUSH, mode, Ofs_GS); PC+=2;
 2581                 break;
 2582             case 0xa9: /* POPgs */
 2583                 if (REALADDR()) {
 2584                     Gen(O_POP, mode, Ofs_GS);
 2585                     AddrGen(A_SR_SH4, mode, Ofs_GS, Ofs_XGS);
 2586                 } else { /* restartable */
 2587                     unsigned short sv = 0;
 2588                     CODE_FLUSH();
 2589                     TOS_WORD(mode, &sv);
 2590                     TheCPU.err = MAKESEG(mode, Ofs_GS, sv);
 2591                     if (TheCPU.err) return P0;
 2592                     POP_ONLY(mode);
 2593                     TheCPU.gs = sv;
 2594                 }
 2595                 PC+=2;
 2596                 break;
 2597 ///
 2598             case 0xaa:
 2599                 CODE_FLUSH();
 2600                 goto illegal_op;
 2601             /* case 0xae:   Code Extension 24(MMX) */
 2602             case 0xaf: /* IMULregrm */
 2603                 PC++; PC += ModRM(opc, PC, mode);
 2604                 Gen(L_DI_R1, mode);     // mov (e)ax,[edi]
 2605                 Gen(O_IMUL, mode|MEMADR, REG1); // reg*[edi]->reg signed
 2606                 break;
 2607             case 0xb0:
 2608             case 0xb1:      /* CMPXCHG */
 2609                 CODE_FLUSH();
 2610                 goto not_implemented;
 2611 ///
 2612             case 0xb2: /* LSS */
 2613                 if (REALADDR()) {
 2614                     PC++; PC += ModRM(opc, PC, mode);
 2615                     Gen(L_LXS1, mode, REG1);
 2616                     Gen(L_LXS2, mode, Ofs_SS, Ofs_XSS);
 2617                 }
 2618                 else {
 2619                     unsigned short sv = 0;
 2620                     unsigned long rv;
 2621                     CODE_FLUSH();
 2622                     CEmuStat |= CeS_LOCK;
 2623                     PC++; PC += ModRMSim(PC, mode);
 2624                     rv = DataGetWL_U(mode,TheCPU.mem_ref);
 2625                     TheCPU.mem_ref += BT24(BitDATA16,mode);
 2626                     sv = GetDWord(TheCPU.mem_ref);
 2627                     TheCPU.err = MAKESEG(mode, Ofs_SS, sv);
 2628                     if (TheCPU.err) return P0;
 2629                     SetCPU_WL(mode, REG1, rv);
 2630                     TheCPU.ss = sv;
 2631                 }
 2632                 break;
 2633             case 0xb4: /* LFS */
 2634                 if (REALADDR()) {
 2635                     PC++; PC += ModRM(opc, PC, mode);
 2636                     Gen(L_LXS1, mode, REG1);
 2637                     Gen(L_LXS2, mode, Ofs_FS, Ofs_XFS);
 2638                 }
 2639                 else {
 2640                     unsigned short sv = 0;
 2641                     unsigned long rv;
 2642                     CODE_FLUSH();
 2643                     PC++; PC += ModRMSim(PC, mode);
 2644                     rv = DataGetWL_U(mode,TheCPU.mem_ref);
 2645                     TheCPU.mem_ref += BT24(BitDATA16,mode);
 2646                     sv = GetDWord(TheCPU.mem_ref);
 2647                     TheCPU.err = MAKESEG(mode, Ofs_FS, sv);
 2648                     if (TheCPU.err) return P0;
 2649                     SetCPU_WL(mode, REG1, rv);
 2650                     TheCPU.fs = sv;
 2651                 }
 2652                 break;
 2653             case 0xb5: /* LGS */
 2654                 if (REALADDR()) {
 2655                     PC++; PC += ModRM(opc, PC, mode);
 2656                     Gen(L_LXS1, mode, REG1);
 2657                     Gen(L_LXS2, mode, Ofs_GS, Ofs_XGS);
 2658                 }
 2659                 else {
 2660                     unsigned short sv = 0;
 2661                     unsigned long rv;
 2662                     CODE_FLUSH();
 2663                     PC++; PC += ModRMSim(PC, mode);
 2664                     rv = DataGetWL_U(mode,TheCPU.mem_ref);
 2665                     TheCPU.mem_ref += BT24(BitDATA16,mode);
 2666                     sv = GetDWord(TheCPU.mem_ref);
 2667                     TheCPU.err = MAKESEG(mode, Ofs_GS, sv);
 2668                     if (TheCPU.err) return P0;
 2669                     SetCPU_WL(mode, REG1, rv);
 2670                     TheCPU.gs = sv;
 2671                 }
 2672                 break;
 2673             case 0xb6: /* MOVZXb */
 2674                 PC++; PC += ModRM(opc, PC, mode|MBYTX);
 2675                 Gen(L_MOVZS, mode|MBYTX, 0, REG1);
 2676                 break;
 2677             case 0xb7: /* MOVZXw */
 2678                 PC++; PC += ModRM(opc, PC, mode);
 2679                 Gen(L_MOVZS, mode, 0, REG1);
 2680                 break;
 2681             case 0xbe: /* MOVSXb */
 2682                 PC++; PC += ModRM(opc, PC, mode|MBYTX);
 2683                 Gen(L_MOVZS, mode|MBYTX, 1, REG1);
 2684                 break;
 2685             case 0xbf: /* MOVSXw */
 2686                 PC++; PC += ModRM(opc, PC, mode);
 2687                 Gen(L_MOVZS, mode, 1, REG1);
 2688                 break;
 2689 ///
 2690             case 0xb8:  /* JMP absolute to IA64 code */
 2691             case 0xb9:
 2692                 CODE_FLUSH();
 2693                 goto illegal_op;    /* UD2 */
 2694             case 0xc0: /* XADDb */
 2695             case 0xc1: /* XADDw */
 2696             /* case 0xc2-0xc6:  MMX */
 2697             /* case 0xc7:   Code Extension 23 - 01=CMPXCHG8B mem */
 2698                 CODE_FLUSH();
 2699                 goto not_implemented;
 2700 
 2701             case 0xc8: /* BSWAPeax */
 2702             case 0xc9: /* BSWAPecx */
 2703             case 0xca: /* BSWAPedx */
 2704             case 0xcb: /* BSWAPebx */
 2705             case 0xcc: /* BSWAPesp */
 2706             case 0xcd: /* BSWAPebp */
 2707             case 0xce: /* BSWAPesi */
 2708             case 0xcf: /* BSWAPedi */
 2709                 if (!(mode&DATA16)) {
 2710                     Gen(O_BSWAP, 0, R1Tab_l[D_LO(opc2)]);
 2711                 } /* else undefined */
 2712                 PC+=2; break;
 2713             case 0xd1 ... 0xd3: /* MMX */
 2714             case 0xd5: case 0xd7: case 0xda: case 0xde:
 2715             case 0xdf:
 2716             case 0xe0 ... 0xe5:
 2717             case 0xf1 ... 0xf3:
 2718             case 0xf5 ... 0xf7:
 2719             case 0xfc ... 0xfe:
 2720                 CODE_FLUSH();
 2721                 goto not_implemented;
 2722 ///
 2723             case 0xff: /* illegal, used by Windows */
 2724                 CODE_FLUSH();
 2725                 goto illegal_op;
 2726             default:
 2727                 CODE_FLUSH();
 2728                 goto not_implemented;
 2729             } }
 2730             break;
 2731 
 2732 /*xx*/  default:
 2733             CODE_FLUSH();
 2734             goto not_implemented;
 2735         }
 2736 
 2737         if (NewNode) {
 2738             int rc=0;
 2739             if (!(TheCPU.mode&SKIPOP))
 2740                 (void)NewIMeta(P0, TheCPU.mode, &rc);
 2741 #ifdef HOST_ARCH_X86
 2742             if (!CONFIG_CPUSIM && rc < 0) { // metadata table full
 2743                 if (debug_level('e')>2)
 2744                     e_printf("============ Tab full:cannot close sequence\n");
 2745                 leavedos(0x9000);
 2746             }
 2747 #endif
 2748         }
 2749         else
 2750         {
 2751             if (debug_level('e')>2)
 2752             e_printf("\n%s",e_print_regs());
 2753             TheCPU.EMUtime += FAKE_INS_TIME;
 2754         }
 2755 #ifdef ASM_DUMP
 2756         {
 2757 #else
 2758         if (debug_level('e')>2) {
 2759 #endif
 2760             char *ds = e_emu_disasm(P0,(~basemode&3));
 2761 #ifdef ASM_DUMP
 2762             fprintf(aLog,"%s\n",ds);
 2763 #endif
 2764             if (debug_level('e')>2) e_printf("  %s\n", ds);
 2765         }
 2766 
 2767         P0 = PC;
 2768 #ifndef SINGLESTEP
 2769         if (!(CEmuStat & CeS_TRAP)) continue;
 2770 #endif
 2771         CloseAndExec(P0, NULL, mode, __LINE__);
 2772         e_printf("\n%s",e_print_regs());
 2773         NewNode = 0;
 2774     }
 2775     return 0;
 2776 
 2777 not_implemented:
 2778     dbug_printf("!!! Unimplemented %02x %02x %02x at %p\n",opc,PC[1],PC[2],PC);
 2779     TheCPU.err = -2; return PC;
 2780 #ifdef HOST_ARCH_X86
 2781 bad_return:
 2782     dbug_printf("!!! Bad code return\n");
 2783     TheCPU.err = -3; return PC;
 2784 #endif
 2785 not_permitted:
 2786     if (debug_level('e')>1) e_printf("!!! Not permitted %02x\n",opc);
 2787     TheCPU.err = EXCP0D_GPF; return PC;
 2788 //div_by_zero:
 2789 //  dbug_printf("!!! Div by 0 %02x\n",opc);
 2790 //  TheCPU.err = -6; return PC;
 2791 illegal_op:
 2792     dbug_printf("!!! Illegal op %02x %02x %02x\n",opc,PC[1],PC[2]);
 2793     TheCPU.err = EXCP06_ILLOP; return PC;
 2794 }
 2795