about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/emu/x64run.c101
-rw-r--r--src/emu/x64run66f0.c101
-rw-r--r--src/emu/x64runf0.c541
3 files changed, 331 insertions, 412 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 7f933920..d1a9bcbc 100644
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -472,10 +472,10 @@ x64emurun:
             break;
         case 0x62:                  /* BOUND Gd, Ed */
             nextop = F8;
-            if(rex.is32bits && MODREG) {
+            if(rex.is32bits && !MODREG) {
                 GETGD;
                 int* bounds = (int*)GETEA(0);
-                if(bounds[0]<GD->dword[0] || bounds[1]>GD->dword[0])
+                if((GD->sdword[0]<bounds[0]) || (GD->sdword[0]>bounds[1]))
                     EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xb09d);
             } else {
                 unimp = 2;
@@ -758,10 +758,15 @@ x64emurun:
         case 0x8C:                      /* MOV Ed, Seg */
             nextop = F8;
             GETED(0);
+            tmp8u = (nextop&0x38)>>3;
+            if(tmp8u>5) {
+                unimp = 2;
+                goto fini;
+            }
             if(MODREG)
-                ED->q[0] = emu->segs[((nextop&0x38)>>3)];
+                ED->q[0] = emu->segs[tmp8u];
             else
-                ED->word[0] = emu->segs[((nextop&0x38)>>3)];
+                ED->word[0] = emu->segs[tmp8u];
             break;
         case 0x8D:                      /* LEA Gd,M */
             nextop = F8;
@@ -775,29 +780,44 @@ x64emurun:
         case 0x8E:                      /* MOV Seg, Ew */
             nextop = F8;
             GETED(0);
-            emu->segs[((nextop&0x38)>>3)] = ED->word[0];
-            emu->segs_serial[((nextop&0x38)>>3)] = 0;
-            if(((nextop&0x38)>>3)==_SS && tf)   // disable trace when SS is accessed
+            tmp8u = (nextop&0x38)>>3;
+            if((tmp8u>5) || (tmp8u==1)) {
+                unimp = 2;
+                goto fini;
+            }
+            emu->segs[tmp8u] = ED->word[0];
+            emu->segs_serial[tmp8u] = 0;
+            if(tmp8u==_SS && tf)   // disable trace when SS is accessed
                 no_tf = 1;
             break;
         case 0x8F:                      /* POP Ed */
             nextop = F8;
-            if(MODREG) {
-                emu->regs[(nextop&7)+(rex.b<<3)].q[0] = rex.is32bits?Pop32(emu):Pop64(emu);
-            } else {
-                if(rex.is32bits) {
-                    tmp32u = Pop32(emu);  // this order allows handling POP [ESP] and variant
-                    GETED(0);
-                    R_ESP -= 4; // to prevent issue with SEGFAULT
-                    ED->dword[0] = tmp32u;
-                    R_ESP += 4;
-                } else {
-                    tmp64u = Pop64(emu);  // this order allows handling POP [ESP] and variant
-                    GETED(0);
-                    R_RSP -= sizeof(void*); // to prevent issue with SEGFAULT
-                    ED->q[0] = tmp64u;
-                    R_RSP += sizeof(void*);
-                }
+            switch((nextop>>3)&7) {
+                case 0: 
+                    if(MODREG) {
+                        emu->regs[(nextop&7)+(rex.b<<3)].q[0] = rex.is32bits?Pop32(emu):Pop64(emu);
+                    } else {
+                        if(rex.is32bits) {
+                            tmp32u = Pop32(emu);  // this order allows handling POP [ESP] and variant
+                            GETED(0);
+                            R_ESP -= 4; // to prevent issue with SEGFAULT
+                            ED->dword[0] = tmp32u;
+                            R_ESP += 4;
+                        } else {
+                            tmp64u = Pop64(emu);  // this order allows handling POP [ESP] and variant
+                            GETED(0);
+                            R_RSP -= sizeof(void*); // to prevent issue with SEGFAULT
+                            ED->q[0] = tmp64u;
+                            R_RSP += sizeof(void*);
+                        }
+                    }
+                    break;
+                case 3:
+                    unimp = 2;
+                    goto fini;
+                default:
+                    unimp = 1;
+                    goto fini;
             }
             break;
         case 0x90:                      /* NOP or XCHG R8, RAX*/
@@ -1448,18 +1468,31 @@ x64emurun:
         case 0xC6:                      /* MOV Eb,Ib */
             nextop = F8;
             GETEB(1);
-            EB->byte[0] = F8;
+            switch((nextop>>3)&7) {
+                case 0: EB->byte[0] = F8; break;
+                case 7: unimp = 2; goto fini;
+                default:
+                    unimp = 1;
+                    goto fini;
+            }
             break;
         case 0xC7:                      /* MOV Ed,Id */
             nextop = F8;
             GETED(4);
-            if(rex.w)
-                ED->q[0] = F32S64;
-            else
-                if(MODREG)
-                    ED->q[0] = F32;
-                else
-                    ED->dword[0] = F32;
+            switch((nextop>>3)&7) {
+                case 0: 
+                    if(rex.w)
+                        ED->q[0] = F32S64;
+                    else
+                        if(MODREG)
+                            ED->q[0] = F32;
+                        else
+                            ED->dword[0] = F32;
+                    break;
+                default:
+                    unimp = 1;
+                    goto fini;
+            }
             break;
         case 0xC8:                      /* ENTER Iw,Ib */
             tmp16u = F16;
@@ -2362,8 +2395,7 @@ x64emurun:
                     }
                     break;
                 default:
-                    printf_log(LOG_NONE, "Illegal Opcode %p: (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X\n", (void*)R_RIP, PK(-6), PK(-5), PK(-4), PK(-3), opcode, nextop, PK(0), PK(1), PK(2), PK(3));
-                    EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0);
+                    unimp = 2;
                     goto fini;
             }
             break;
@@ -2389,8 +2421,9 @@ if(emu->segs[_CS]!=0x33 && emu->segs[_CS]!=0x23) printf_log(LOG_NONE, "Warning,
     printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->quit);
     if(unimp) {
         //emu->quit = 1;
-        if(unimp==1)
+        if(unimp==1 && !(emu->error&ERR_ILLEGAL))
             UnimpOpcode(emu, is32bits);
+        emu->error &= ~ERR_ILLEGAL;
         EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0);
     }
     // fork handling
diff --git a/src/emu/x64run66f0.c b/src/emu/x64run66f0.c
index 951edccd..bca6cd28 100644
--- a/src/emu/x64run66f0.c
+++ b/src/emu/x64run66f0.c
@@ -66,6 +66,10 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 
                 case 0xB1:                      /* CMPXCHG Ew,Gw */
                     nextop = F8;
+                    if(MODREG) {
+                        emu->error |= ERR_ILLEGAL;
+                        return 0;
+                    }
                     GETEW(0);
                     GETGW;
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)
@@ -94,6 +98,10 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 0xBA: /* BTS Ew, Ib */
                     CHECK_FLAGS(emu);
                     nextop = F8;
+                    if(MODREG) {
+                        emu->error |= ERR_ILLEGAL;
+                        return 0;
+                    }
                     GETEW(0);
                     tmp8u = F8;
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)
@@ -144,6 +152,10 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 
                 case 0xC1:                      /* XADD Gw,Ew */
                     nextop = F8;
+                    if(MODREG) {
+                        emu->error |= ERR_ILLEGAL;
+                        return 0;
+                    }
                     GETEW(0);
                     GETGW;
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)
@@ -179,44 +191,30 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
         #define GO(B, OP)                                           \
         case B+1:                                                   \
             nextop = F8;                                            \
+            if(MODREG) {                                            \
+                emu->error |= ERR_ILLEGAL;                          \
+                return 0;                                           \
+            }                                                       \
             GETEW(0);                                               \
             GETGW;                                                  \
             do {                                                    \
                 tmp16u = native_lock_read_h(ED);                    \
                 tmp16u = OP##16(emu, tmp16u, GW->word[0]);          \
             } while (native_lock_write_h(ED, tmp16u));              \
-            break;                                                  \
-        case B+3:                                                   \
-            nextop = F8;                                            \
-            GETEW(0);                                               \
-            GETGW;                                                  \
-            GW->word[0] = OP##16(emu, GW->word[0], EW->word[0]);    \
-            break;                                                  \
-        case B+5:                                                   \
-            R_AX = OP##16(emu, R_AX, F16);                          \
             break;
 #else
         #define GO(B, OP)                                           \
         case B+1:                                                   \
             nextop = F8;                                            \
+            if(MODREG) {                                            \
+                emu->error |= ERR_ILLEGAL;                          \
+                return 0;                                           \
+            }                                                       \
             GETEW(0);                                               \
             GETGW;                                                  \
-            pthread_mutex_lock(&my_context->mutex_lock);          \
+            pthread_mutex_lock(&my_context->mutex_lock);            \
             EW->word[0] = OP##16(emu, EW->word[0], GW->word[0]);    \
-            pthread_mutex_unlock(&my_context->mutex_lock);        \
-            break;                                                  \
-        case B+3:                                                   \
-            nextop = F8;                                            \
-            GETEW(0);                                               \
-            GETGW;                                                  \
-            pthread_mutex_lock(&my_context->mutex_lock);          \
-            GW->word[0] = OP##16(emu, GW->word[0], EW->word[0]);    \
-            pthread_mutex_unlock(&my_context->mutex_lock);        \
-            break;                                                  \
-        case B+5:                                                   \
-            pthread_mutex_lock(&my_context->mutex_lock);          \
-            R_AX = OP##16(emu, R_AX, F16);                          \
-            pthread_mutex_unlock(&my_context->mutex_lock);        \
+            pthread_mutex_unlock(&my_context->mutex_lock);          \
             break;
 #endif
         GO(0x00, add)                   /* ADD 0x00 -> 0x05 */
@@ -231,32 +229,24 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
         case 0x81:              /* GRP Ew,Iw */
         case 0x83:              /* GRP Ew,Ib */
             nextop = F8;
+            if(MODREG) {
+                emu->error |= ERR_ILLEGAL;
+                return 0;
+            }
             GETEW((opcode==0x83)?1:2);
             tmp16s = (opcode==0x83)?(F8S):(F16S);
             tmp16u = (uint16_t)tmp16s;
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)
-            if(MODREG)
-                switch((nextop>>3)&7) {
-                    case 0: EW->word[0] = add16(emu, EW->word[0], tmp16u); break;
-                    case 1: EW->word[0] =  or16(emu, EW->word[0], tmp16u); break;
-                    case 2: EW->word[0] = adc16(emu, EW->word[0], tmp16u); break;
-                    case 3: EW->word[0] = sbb16(emu, EW->word[0], tmp16u); break;
-                    case 4: EW->word[0] = and16(emu, EW->word[0], tmp16u); break;
-                    case 5: EW->word[0] = sub16(emu, EW->word[0], tmp16u); break;
-                    case 6: EW->word[0] = xor16(emu, EW->word[0], tmp16u); break;
-                    case 7:               cmp16(emu, EW->word[0], tmp16u); break;
-                }
-            else
-                switch((nextop>>3)&7) {
-                    case 0: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = add16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 1: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 =  or16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 2: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 3: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 4: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = and16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 5: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sub16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 6: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = xor16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
-                    case 7:                                                  cmp16(emu, EW->word[0], tmp16u); break;
-                }
+            switch((nextop>>3)&7) {
+                case 0: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = add16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 1: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 =  or16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 2: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 3: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 4: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = and16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 5: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sub16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 6: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = xor16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+                case 7: emu->error |= ERR_ILLEGAL; return 0;
+            }
 #else
             pthread_mutex_lock(&my_context->mutex_lock);
             switch((nextop>>3)&7) {
@@ -267,7 +257,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 4: EW->word[0] = and16(emu, EW->word[0], tmp16u); break;
                 case 5: EW->word[0] = sub16(emu, EW->word[0], tmp16u); break;
                 case 6: EW->word[0] = xor16(emu, EW->word[0], tmp16u); break;
-                case 7:               cmp16(emu, EW->word[0], tmp16u); break;
+                case 7: emu->error |= ERR_ILLEGAL; return 0;
             }
             pthread_mutex_unlock(&my_context->mutex_lock);
 #endif
@@ -275,9 +265,12 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 
         case 0xF7:                      /* GRP3 Ed(,Id) */
             nextop = F8;
-            nextop = (nextop>>3)&7;
-            GETEW((nextop<2)?2:0);
-            switch(nextop) {
+            if(MODREG) {
+                emu->error |= ERR_ILLEGAL;
+                return 0;
+            }
+            GETEW((((nextop>>3)&7)<2)?2:0);
+            switch((nextop>>3)&7) {
                 case 2:                 /* NOT Ed */
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)
                     if(rex.w)
@@ -310,6 +303,10 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 
         case 0xFF:              /* GRP 5 Ed */
             nextop = F8;
+            if(MODREG) {
+                emu->error |= ERR_ILLEGAL;
+                return 0;
+            }
             GETEW(0);
             switch((nextop>>3)&7) {
                 case 0:                 /* INC Ed */
@@ -346,10 +343,8 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 #endif
                     break;
                 default:
-                    printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
-                    emu->quit=1;
                     emu->error |= ERR_ILLEGAL;
-                    break;
+                    return 0;
             }
             break;
        default:
diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c
index 2479fc15..1d8d05b5 100644
--- a/src/emu/x64runf0.c
+++ b/src/emu/x64runf0.c
@@ -64,6 +64,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
         #define GO(B, OP, F)                                        \

         case B+0:                                                   \

             nextop = F8;                                            \

+            if(MODREG) {                                            \

+                emu->error |= ERR_ILLEGAL;                          \

+                return 0;                                           \

+            }                                                       \

             GETEB(0);                                               \

             GETGB;                                                  \

             if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;}           \

@@ -75,29 +79,31 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             break;                                                  \

         case B+1:                                                   \

             nextop = F8;                                            \

+            if(MODREG) {                                            \

+                emu->error |= ERR_ILLEGAL;                          \

+                return 0;                                           \

+            }                                                       \

             GETED(0);                                               \

             GETGD;                                                  \

             if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;}           \

             if(((uintptr_t)ED)&(3<<rex.w)) {                        \

-                if(rex.w) {                                             \

-                    do {                                                \

-                        if(F) emu->eflags = eflags;                     \

-                        tmp8u = native_lock_read_b(ED);                 \

-                        tmp64u = ED->q[0];                              \

-                        tmp64u = OP##64(emu, tmp64u, GD->q[0]);         \

-                    } while (native_lock_write_b(ED, tmp8u));           \

-                    ED->q[0] = tmp64u;                                  \

-                } else {                                                \

-                    do {                                                \

-                        if(F) emu->eflags = eflags;                     \

-                        tmp8u = native_lock_read_b(ED);                 \

-                        tmp32u = ED->dword[0];                          \

-                        tmp32u = OP##32(emu, tmp32u, GD->dword[0]);     \

-                    } while (native_lock_write_b(ED, tmp8u));           \

-                    ED->dword[0] = tmp32u;                              \

-                    if(MODREG)                                          \

-                        ED->dword[1] = 0;                               \

-                }                                                       \

+                if(rex.w) {                                         \

+                    do {                                            \

+                        if(F) emu->eflags = eflags;                 \

+                        tmp8u = native_lock_read_b(ED);             \

+                        tmp64u = ED->q[0];                          \

+                        tmp64u = OP##64(emu, tmp64u, GD->q[0]);     \

+                    } while (native_lock_write_b(ED, tmp8u));       \

+                    ED->q[0] = tmp64u;                              \

+                } else {                                            \

+                    do {                                            \

+                        if(F) emu->eflags = eflags;                 \

+                        tmp8u = native_lock_read_b(ED);             \

+                        tmp32u = ED->dword[0];                      \

+                        tmp32u = OP##32(emu, tmp32u, GD->dword[0]); \

+                    } while (native_lock_write_b(ED, tmp8u));       \

+                    ED->dword[0] = tmp32u;                          \

+                }                                                   \

             } else {                                                \

             if(rex.w) {                                             \

                 do {                                                \

@@ -115,35 +121,15 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                     ED->dword[1] = 0;                               \

             }                                                       \

             }                                                       \

-            break;                                                  \

-        case B+2:                                                   \

-            nextop = F8;                                            \

-            GETEB(0);                                               \

-            GETGB;                                                  \

-            GB = OP##8(emu, GB, EB->byte[0]);                       \

-            break;                                                  \

-        case B+3:                                                   \

-            nextop = F8;                                            \

-            GETED(0);                                               \

-            GETGD;                                                  \

-            if(rex.w)                                               \

-                GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]);         \

-            else                                                    \

-                GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \

-            break;                                                  \

-        case B+4:                                                   \

-            R_AL = OP##8(emu, R_AL, F8);                            \

-            break;                                                  \

-        case B+5:                                                   \

-            if(rex.w)                                               \

-                R_RAX = OP##64(emu, R_RAX, F32S64);                 \

-            else                                                    \

-                R_RAX = OP##32(emu, R_EAX, F32);                    \

             break;

 #else

         #define GO(B, OP, F)                                        \

         case B+0:                                                   \

             nextop = F8;                                            \

+            if(MODREG) {                                            \

+                emu->error |= ERR_ILLEGAL;                          \

+                return 0;                                           \

+            }                                                       \

             GETEB(0);                                               \

             GETGB;                                                  \

             pthread_mutex_lock(&my_context->mutex_lock);            \

@@ -152,49 +138,18 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             break;                                                  \

         case B+1:                                                   \

             nextop = F8;                                            \

+            if(MODREG) {                                            \

+                emu->error |= ERR_ILLEGAL;                          \

+                return 0;                                           \

+            }                                                       \

             GETED(0);                                               \

             GETGD;                                                  \

             pthread_mutex_lock(&my_context->mutex_lock);            \

             if(rex.w)                                               \

                 ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]);         \

             else                                                    \

-                if(MODREG)                                          \

-                    ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]);     \

-                else                                                        \

-                    ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \

-            pthread_mutex_unlock(&my_context->mutex_lock);        \

-            break;                                                  \

-        case B+2:                                                   \

-            nextop = F8;                                            \

-            GETEB(0);                                               \

-            GETGB;                                                  \

-            pthread_mutex_lock(&my_context->mutex_lock);          \

-            GB = OP##8(emu, GB, EB->byte[0]);                       \

-            pthread_mutex_unlock(&my_context->mutex_lock);        \

-            break;                                                  \

-        case B+3:                                                   \

-            nextop = F8;                                            \

-            GETED(0);                                               \

-            GETGD;                                                  \

-            pthread_mutex_lock(&my_context->mutex_lock);          \

-            if(rex.w)                                               \

-                GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]);         \

-            else                                                    \

-                GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \

-            pthread_mutex_unlock(&my_context->mutex_lock);        \

-            break;                                                  \

-        case B+4:                                                   \

-            pthread_mutex_lock(&my_context->mutex_lock);          \

-            R_AL = OP##8(emu, R_AL, F8);                            \

-            pthread_mutex_unlock(&my_context->mutex_lock);        \

-            break;                                                  \

-        case B+5:                                                   \

-            pthread_mutex_lock(&my_context->mutex_lock);          \

-            if(rex.w)                                               \

-                R_RAX = OP##64(emu, R_RAX, F32S64);                 \

-            else                                                    \

-                R_RAX = OP##32(emu, R_EAX, F32);                    \

-            pthread_mutex_unlock(&my_context->mutex_lock);        \

+                ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \

+            pthread_mutex_unlock(&my_context->mutex_lock);          \

             break;

 #endif

         GO(0x00, add, 0)                   /* ADD 0x00 -> 0x05 */

@@ -212,67 +167,51 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             case 0xAB:                      /* BTS Ed,Gd */

                 CHECK_FLAGS(emu);

                 nextop = F8;

+                if(MODREG) {

+                    emu->error |= ERR_ILLEGAL;

+                    return 0;

+                }

                 GETED(0);

                 GETGD;

                 tmp64s = rex.w?GD->sq[0]:GD->sdword[0];

                 tmp8u=tmp64s&(rex.w?63:31);

                 tmp64s >>= (rex.w?6:5);

-                if(!MODREG)

-                {

-                    #ifdef TEST_INTERPRETER

-                    test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

-                    if(rex.w)

-                        *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

-                    else

-                        *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

-                    #else

-                    ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

-                    #endif

-                }

+                #ifdef TEST_INTERPRETER

+                test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

+                if(rex.w)

+                    *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

+                else

+                    *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

+                #else

+                ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

+                #endif

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

                 if(rex.w) {

                     tmp8u&=63;

-                    if(MODREG) {

-                        if(ED->q[0] & (1LL<<tmp8u))

+                    do {

+                        tmp64u = native_lock_read_dd(ED);

+                        if(tmp64u & (1LL<<tmp8u)) {

                             SET_FLAG(F_CF);

-                        else {

-                            ED->q[0] |= (1LL<<tmp8u);

+                            tmp32s = 0;

+                        } else {

+                            tmp64u |= (1LL<<tmp8u);

                             CLEAR_FLAG(F_CF);

+                            tmp32s = native_lock_write_dd(ED, tmp64u);

                         }

-                    } else

-                        do {

-                            tmp64u = native_lock_read_dd(ED);

-                            if(tmp64u & (1LL<<tmp8u)) {

-                                SET_FLAG(F_CF);

-                                tmp32s = 0;

-                            } else {

-                                tmp64u |= (1LL<<tmp8u);

-                                CLEAR_FLAG(F_CF);

-                                tmp32s = native_lock_write_dd(ED, tmp64u);

-                            }

-                        } while(tmp32s);

+                    } while(tmp32s);

                 } else {

                     tmp8u&=31;

-                    if(MODREG) {

-                        if(ED->dword[0] & (1<<tmp8u))

+                    do {

+                        tmp32u = native_lock_read_d(ED);

+                        if(tmp32u & (1<<tmp8u)) {

                             SET_FLAG(F_CF);

-                        else {

-                            ED->dword[0] |= (1<<tmp8u);

+                            tmp32s = 0;

+                        } else {

+                            tmp32u |= (1<<tmp8u);

                             CLEAR_FLAG(F_CF);

+                            tmp32s = native_lock_write_d(ED, tmp32u);

                         }

-                        ED->dword[1] = 0;

-                    } else

-                        do {

-                            tmp32u = native_lock_read_d(ED);

-                            if(tmp32u & (1<<tmp8u)) {

-                                SET_FLAG(F_CF);

-                                tmp32s = 0;

-                            } else {

-                                tmp32u |= (1<<tmp8u);

-                                CLEAR_FLAG(F_CF);

-                                tmp32s = native_lock_write_d(ED, tmp32u);

-                            }

-                        } while(tmp32s);

+                    } while(tmp32s);

                 }

 #else

                 pthread_mutex_lock(&my_context->mutex_lock);

@@ -292,8 +231,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                         ED->dword[0] |= (1<<tmp8u);

                         CLEAR_FLAG(F_CF);

                     }

-                    if(MODREG)

-                        ED->dword[1] = 0;

                 }

                 pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -308,6 +245,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 0xB0:                      /* CMPXCHG Eb,Gb */

                     CHECK_FLAGS(emu);

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETGB;

                     GETEB(0);

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

@@ -334,10 +275,14 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                     break;

                 case 0xB1:                      /* CMPXCHG Ed,Gd */

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETED(0);

                     GETGD;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

-                    if(rex.w)

+                    if(rex.w) {

                         if(((uintptr_t)ED)&7) {

                             do {

                                 tmp64u = ED->q[0] & ~0xffLL;

@@ -363,7 +308,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                                     tmp32s = 0;

                                 }

                             } while(tmp32s);

-                    else {

+                    } else {

                         if(((uintptr_t)ED)&3) {

                             do {

                                 tmp32u = ED->q[0] & ~0xffLL;

@@ -390,8 +335,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                                 }

                             } while(tmp32s);

                         emu->regs[_AX].dword[1] = 0;

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

@@ -410,8 +353,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                             R_EAX = ED->dword[0];

                         }

                         emu->regs[_AX].dword[1] = 0;

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -420,23 +361,24 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 0xB3:                      /* BTR Ed,Gd */

                     CHECK_FLAGS(emu);

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETED(0);

                     GETGD;

                     tmp64s = rex.w?GD->sq[0]:GD->sdword[0];

                     tmp8u=tmp64s&(rex.w?63:31);

                     tmp64s >>= (rex.w?6:5);

-                    if(!MODREG)

-                    {

-                        #ifdef TEST_INTERPRETER

-                        test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

-                        if(rex.w)

-                            *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

-                        else

-                            *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

-                        #else

-                        ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

-                        #endif

-                    }

+                    #ifdef TEST_INTERPRETER

+                    test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

+                    if(rex.w)

+                        *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

+                    else

+                        *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

+                    #else

+                    ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

+                    #endif

                     tmp8u&=rex.w?63:31;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

                     if(rex.w)

@@ -463,8 +405,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                                 tmp32s = 0;

                             }

                         } while(tmp32s);

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

@@ -480,8 +420,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                             ED->dword[0] ^= (1<<tmp8u);

                         } else

                             CLEAR_FLAG(F_CF);

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -495,31 +433,14 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 

                     case 0xBA:                      

                         nextop = F8;

+                        if(MODREG) {

+                            emu->error |= ERR_ILLEGAL;

+                            return 0;

+                        }

                         switch((nextop>>3)&7) {

                             case 4:                 /* BT Ed,Ib */

-                                CHECK_FLAGS(emu);

-                                GETED(1);

-                                tmp8u = F8;

-                                if(rex.w) {

-                                    tmp8u&=63;

-                                    if(ED->q[0] & (1LL<<tmp8u))

-                                        SET_FLAG(F_CF);

-                                    else

-                                        CLEAR_FLAG(F_CF);

-                                } else {

-                                    tmp8u&=31;

-                                    if(ED->dword[0] & (1<<tmp8u))

-                                        SET_FLAG(F_CF);

-                                    else

-                                        CLEAR_FLAG(F_CF);

-                                }

-                                if(BOX64ENV(dynarec_test)) {

-                                    CLEAR_FLAG(F_OF);

-                                    CLEAR_FLAG(F_SF);

-                                    CLEAR_FLAG(F_AF);

-                                    CLEAR_FLAG(F_PF);

-                                }

-                                break;

+                                emu->error |= ERR_ILLEGAL;

+                                return 0;

                             case 5:             /* BTS Ed, Ib */

                                 CHECK_FLAGS(emu);

                                 GETED(1);

@@ -726,23 +647,24 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 0xBB:                      /* BTC Ed,Gd */

                     CHECK_FLAGS(emu);

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETED(0);

                     GETGD;

                     tmp64s = rex.w?GD->sq[0]:GD->sdword[0];

                     tmp8u=tmp64s&(rex.w?63:31);

                     tmp64s >>= (rex.w?6:5);

-                    if(!MODREG)

-                    {

-                        #ifdef TEST_INTERPRETER

-                        test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

-                        if(rex.w)

-                            *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

-                        else

-                            *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

-                        #else

-                        ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

-                        #endif

-                    }

+                    #ifdef TEST_INTERPRETER

+                    test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));

+                    if(rex.w)

+                        *(uint64_t*)test->mem = *(uint64_t*)test->memaddr;

+                    else

+                        *(uint32_t*)test->mem = *(uint32_t*)test->memaddr;

+                    #else

+                    ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));

+                    #endif

                     tmp8u&=rex.w?63:31;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

                     if(rex.w)

@@ -767,8 +689,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                             tmp32u ^= (1<<tmp8u);

                             tmp32s = native_lock_write_d(ED, tmp32u);

                         } while(tmp32s);

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

@@ -784,8 +704,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                         else

                             CLEAR_FLAG(F_CF);

                         ED->dword[0] ^= (1<<tmp8u);

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -817,6 +735,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                     break;

                 case 0xC1:                      /* XADD Gd,Ed */

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETED(0);

                     GETGD;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

@@ -841,8 +763,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                             } while(native_lock_write_d(ED, tmp32u2));

                         }

                         GD->q[0] = tmp32u;

-                        if(MODREG)

-                            ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

@@ -855,10 +775,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                         tmp32u = ED->dword[0];

                         tmp32u2 = add32(emu, tmp32u, GD->dword[0]);

                         GD->q[0] = tmp32u;

-                        if(MODREG)

-                            ED->q[0] = tmp32u2;

-                        else

-                            ED->dword[0] = tmp32u2;

+                        ED->dword[0] = tmp32u2;

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -866,6 +783,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 

                 case 0xC7:                      /* CMPXCHG8B Gq */

                     nextop = F8;

+                    if(MODREG) {

+                        emu->error |= ERR_ILLEGAL;

+                        return 0;

+                    }

                     GETE8xw(0);

                     switch((nextop>>3)&7) {

                         case 1:

@@ -1025,6 +946,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 

         case 0x80:                      /* GRP Eb,Ib */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             GETEB(1);

             tmp8u = F8;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

@@ -1036,7 +961,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 4: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = and8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break;

                 case 5: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = sub8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break;

                 case 6: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = xor8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break;

-                case 7:               cmp8(emu, EB->byte[0], tmp8u); break;

+                case 7: emu->error |= ERR_ILLEGAL; return 0;

             }

 #else

             pthread_mutex_lock(&my_context->mutex_lock);

@@ -1048,7 +973,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;

                 case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;

                 case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;

-                case 7:               cmp8(emu, EB->byte[0], tmp8u); break;

+                case 7: emu->error |= ERR_ILLEGAL; return 0;

             }

             pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -1056,6 +981,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
         case 0x81:              /* GRP Ed,Id */

         case 0x83:              /* GRP Ed,Ib */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             GETED((opcode==0x81)?4:1);

             if(opcode==0x83) {

                 tmp64s = F8S;

@@ -1063,7 +992,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             } else

                 tmp64u = F32S64;

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

-            if(rex.w) {

+            if(rex.w)

                 switch((nextop>>3)&7) {

                     case 0: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;

                     case 1: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 =  or64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;

@@ -1072,43 +1001,30 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                     case 4: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = and64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;

                     case 5: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = sub64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;

                     case 6: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = xor64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;

-                    case 7:                cmp64(emu, ED->q[0], tmp64u); break;

+                    case 7: emu->error |= ERR_ILLEGAL; return 0;

+                }

+            else

+                switch((nextop>>3)&7) {

+                    case 0: if(((uintptr_t)ED)&3) {

+                                // unaligned case

+                                do { tmp32u2 = native_lock_read_b(ED); tmp32u2=ED->dword[0]; tmp32u2 = add32(emu, tmp32u2, tmp64u);} while(native_lock_write_b(ED, tmp32u2)); ED->dword[0]=tmp32u2; break;

+                            } else {

+                            do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = add32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break; }

+                    case 1: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 =  or32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

+                    case 2: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp32u2 = native_lock_read_d(ED); tmp32u2 = adc32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

+                    case 3: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp32u2 = native_lock_read_d(ED); tmp32u2 = sbb32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

+                    case 4: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = and32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

+                    case 5: if(((uintptr_t)ED)&3) {

+                                // unaligned case

+                                do { tmp32u2 = native_lock_read_b(ED); tmp32u2=ED->dword[0]; tmp32u2 = sub32(emu, tmp32u2, tmp64u);} while(native_lock_write_b(ED, tmp32u2)); ED->dword[0]=tmp32u2; break;    

+                            } else {

+                            do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = sub32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break; }

+                    case 6: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = xor32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

+                    case 7: emu->error |= ERR_ILLEGAL; return 0;

                 }

-            } else {

-                if(MODREG)

-                    switch((nextop>>3)&7) {

-                        case 0: ED->q[0] = add32(emu, ED->dword[0], tmp64u); break;

-                        case 1: ED->q[0] =  or32(emu, ED->dword[0], tmp64u); break;

-                        case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp64u); break;

-                        case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp64u); break;

-                        case 4: ED->q[0] = and32(emu, ED->dword[0], tmp64u); break;

-                        case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp64u); break;

-                        case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp64u); break;

-                        case 7:            cmp32(emu, ED->dword[0], tmp64u); break;

-                    }

-                else

-                    switch((nextop>>3)&7) {

-                        case 0: if(((uintptr_t)ED)&3) {

-                                    // unaligned case

-                                    do { tmp32u2 = native_lock_read_b(ED); tmp32u2=ED->dword[0]; tmp32u2 = add32(emu, tmp32u2, tmp64u);} while(native_lock_write_b(ED, tmp32u2)); ED->dword[0]=tmp32u2; break;    

-                                } else {

-                                do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = add32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break; }

-                        case 1: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 =  or32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

-                        case 2: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp32u2 = native_lock_read_d(ED); tmp32u2 = adc32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

-                        case 3: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp32u2 = native_lock_read_d(ED); tmp32u2 = sbb32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

-                        case 4: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = and32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

-                        case 5: if(((uintptr_t)ED)&3) {

-                                    // unaligned case

-                                    do { tmp32u2 = native_lock_read_b(ED); tmp32u2=ED->dword[0]; tmp32u2 = sub32(emu, tmp32u2, tmp64u);} while(native_lock_write_b(ED, tmp32u2)); ED->dword[0]=tmp32u2; break;    

-                                } else {

-                                do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = sub32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break; }

-                        case 6: do { tmp32u2 = native_lock_read_d(ED); tmp32u2 = xor32(emu, tmp32u2, tmp64u);} while(native_lock_write_d(ED, tmp32u2)); break;

-                        case 7:                                                 cmp32(emu, ED->dword[0], tmp64u); break;

-                    }

-            }

 #else

             pthread_mutex_lock(&my_context->mutex_lock);

-            if(rex.w) {

+            if(rex.w)

                 switch((nextop>>3)&7) {

                     case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;

                     case 1: ED->q[0] =  or64(emu, ED->q[0], tmp64u); break;

@@ -1117,105 +1033,80 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                     case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break;

                     case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break;

                     case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break;

-                    case 7:            cmp64(emu, ED->q[0], tmp64u); break;

+                    case 7: emu->error |= ERR_ILLEGAL; return 0;

+                }

+            else

+                switch((nextop>>3)&7) {

+                    case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp64u); break;

+                    case 1: ED->dword[0] =  or32(emu, ED->dword[0], tmp64u); break;

+                    case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp64u); break;

+                    case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp64u); break;

+                    case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp64u); break;

+                    case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp64u); break;

+                    case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp64u); break;

+                    case 7: emu->error |= ERR_ILLEGAL; return 0;

                 }

-            } else {

-                if((nextop&0xC0)==0xC0)

-                    switch((nextop>>3)&7) {

-                        case 0: ED->q[0] = add32(emu, ED->dword[0], tmp64u); break;

-                        case 1: ED->q[0] =  or32(emu, ED->dword[0], tmp64u); break;

-                        case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp64u); break;

-                        case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp64u); break;

-                        case 4: ED->q[0] = and32(emu, ED->dword[0], tmp64u); break;

-                        case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp64u); break;

-                        case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp64u); break;

-                        case 7:            cmp32(emu, ED->dword[0], tmp64u); break;

-                    }

-                else

-                    switch((nextop>>3)&7) {

-                        case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp64u); break;

-                        case 1: ED->dword[0] =  or32(emu, ED->dword[0], tmp64u); break;

-                        case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp64u); break;

-                        case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp64u); break;

-                        case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp64u); break;

-                        case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp64u); break;

-                        case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp64u); break;

-                        case 7:                cmp32(emu, ED->dword[0], tmp64u); break;

-                    }

-            }

             pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

             break;

 

         case 0x86:                      /* XCHG Eb,Gb */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

             GETEB(0);

             GETGB;

-            if(MODREG) { // reg / reg: no lock

-                tmp8u = GB;

-                GB = EB->byte[0];

-                EB->byte[0] = tmp8u;

-            } else {

-                do {

-                    tmp8u = native_lock_read_b(EB);

-                } while(native_lock_write_b(EB, GB));

-                GB = tmp8u;

-            }

+            do {

+                tmp8u = native_lock_read_b(EB);

+            } while(native_lock_write_b(EB, GB));

+            GB = tmp8u;

 #else

             GETEB(0);

             GETGB;

-            if(!MODREG)

-                pthread_mutex_lock(&my_context->mutex_lock); // XCHG always LOCK (but when accessing memory only)

+            pthread_mutex_lock(&my_context->mutex_lock); // XCHG always LOCK (but when accessing memory only)

             tmp8u = GB;

             GB = EB->byte[0];

             EB->byte[0] = tmp8u;

-            if(!MODREG)

-                pthread_mutex_unlock(&my_context->mutex_lock);

+            pthread_mutex_unlock(&my_context->mutex_lock);

 #endif                

             break;

         case 0x87:                      /* XCHG Ed,Gd */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

             GETED(0);

             GETGD;

-            if(MODREG) {

-                if(rex.w) {

-                    tmp64u = GD->q[0];

-                    GD->q[0] = ED->q[0];

-                    ED->q[0] = tmp64u;

+            if(rex.w) {

+                if((uintptr_t)ED&7) {

+                    // unaligned

+                    do {

+                        tmp64u = ED->q[0] & 0xffffffffffffff00LL;

+                        tmp64u |= native_lock_read_b(ED);

+                        

+                    } while(native_lock_write_b(ED, GD->byte[0]));

+                    ED->q[0] = GD->q[0];

+                    GD->q[0] = tmp64u;

                 } else {

-                    tmp32u = GD->dword[0];

-                    GD->q[0] = ED->dword[0];

-                    ED->q[0] = tmp32u;

+                    GD->q[0] = native_lock_xchg_dd(ED, GD->q[0]);

                 }

             } else {

-                if(rex.w) {

-                    if((uintptr_t)ED&7) {

-                        // unaligned

-                        do {

-                            tmp64u = ED->q[0] & 0xffffffffffffff00LL;

-                            tmp64u |= native_lock_read_b(ED);

-                            

-                        } while(native_lock_write_b(ED, GD->byte[0]));

-                        ED->q[0] = GD->q[0];

-                        GD->q[0] = tmp64u;

-                    } else {

-                        GD->q[0] = native_lock_xchg_dd(ED, GD->q[0]);

-                    }

+                if((uintptr_t)ED&3) {

+                    // unaligned

+                    do {

+                        tmp32u = ED->dword[0] & 0xffffff00;

+                        tmp32u |= native_lock_read_b(ED);

+                        

+                    } while(native_lock_write_b(ED, GD->byte[0]));

+                    ED->dword[0] = GD->dword[0];

+                    GD->dword[0] = tmp32u;

                 } else {

-                    if((uintptr_t)ED&3) {

-                        // unaligned

-                        do {

-                            tmp32u = ED->dword[0] & 0xffffff00;

-                            tmp32u |= native_lock_read_b(ED);

-                            

-                        } while(native_lock_write_b(ED, GD->byte[0]));

-                        ED->dword[0] = GD->dword[0];

-                        GD->dword[0] = tmp32u;

-                    } else {

-                        GD->dword[0] = native_lock_xchg_d(ED, GD->dword[0]);

-                    }

+                    GD->dword[0] = native_lock_xchg_d(ED, GD->dword[0]);

                 }

             }

 #else

@@ -1229,10 +1120,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             } else {

                 tmp32u = GD->dword[0];

                 GD->q[0] = ED->dword[0];

-                if(MODREG)

-                    ED->q[0] = tmp32u;

-                else

-                    ED->dword[0] = tmp32u;

+                ED->dword[0] = tmp32u;

             }

             pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -1240,6 +1128,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 

         case 0xF6:                      /* GRP3 Eb(,Ib) */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             tmp8u = (nextop>>3)&7;

             GETEB((tmp8u<2)?1:0);

             switch(tmp8u) {

@@ -1261,6 +1153,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
             break;

             case 0xF7:                      /* GRP3 Ed(,Id) */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             tmp8u = (nextop>>3)&7;

             GETED((tmp8u<2)?4:0);

             switch(tmp8u) {

@@ -1276,7 +1172,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                             tmp32u = native_lock_read_d(ED); 

                             tmp32u = not32(emu, tmp32u);

                         } while(native_lock_write_d(ED, tmp32u));

-                        if(MODREG) ED->dword[1] = 0;

                     }

 #else

                     if(rex.w) {

@@ -1287,7 +1182,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                         pthread_mutex_lock(&my_context->mutex_lock);

                         ED->dword[0] = not32(emu, ED->dword[0]);

                         pthread_mutex_unlock(&my_context->mutex_lock);

-                        if(MODREG) ED->dword[1] = 0;

                     }

 #endif

                     break;

@@ -1298,6 +1192,10 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 

         case 0xFE:              /* GRP 5 Eb */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             GETED(0);

             switch((nextop>>3)&7) {

                 case 0:                 /* INC Eb */

@@ -1323,14 +1221,16 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 #endif

                     break;

                 default:

-                    printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFE 0x%02X 0x%02X\n", nextop, PK(0));

-                    emu->quit=1;

                     emu->error |= ERR_ILLEGAL;

-                    break;

+                    return 0;

             }

             break;

         case 0xFF:              /* GRP 5 Ed */

             nextop = F8;

+            if(MODREG) {

+                emu->error |= ERR_ILLEGAL;

+                return 0;

+            }

             GETED(0);

             switch((nextop>>3)&7) {

                 case 0:                 /* INC Ed */

@@ -1364,17 +1264,13 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                                 tmp32u = native_lock_read_d(ED);

                             } while(native_lock_write_d(ED, inc32(emu, tmp32u)));

                         }

-                        if(MODREG) ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

                     if(rex.w) {

                         ED->q[0] = inc64(emu, ED->q[0]);

                     } else {

-                        if(MODREG)

-                            ED->q[0] = inc32(emu, ED->dword[0]);

-                        else

-                            ED->dword[0] = inc32(emu, ED->dword[0]);

+                        ED->dword[0] = inc32(emu, ED->dword[0]);

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

@@ -1410,29 +1306,24 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
                                 tmp32u = native_lock_read_d(ED);

                             } while(native_lock_write_d(ED, dec32(emu, tmp32u)));

                         }

-                        if(MODREG) ED->dword[1] = 0;

                     }

 #else

                     pthread_mutex_lock(&my_context->mutex_lock);

                     if(rex.w) {

                         ED->q[0] = dec64(emu, ED->q[0]);

                     } else {

-                        if(MODREG)

-                            ED->q[0] = dec32(emu, ED->dword[0]);

-                        else

-                            ED->dword[0] = dec32(emu, ED->dword[0]);

+                        ED->dword[0] = dec32(emu, ED->dword[0]);

                     }

                     pthread_mutex_unlock(&my_context->mutex_lock);

 #endif

                     break;

                 default:

-                    printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));

-                    emu->quit=1;

                     emu->error |= ERR_ILLEGAL;

-                    break;

+                    return 0;

             }

             break;

         default:

+            emu->error |= ERR_ILLEGAL;

             return 0;

     }

     return addr;