about summary refs log tree commit diff stats
path: root/src/emu/x64run64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/x64run64.c')
-rw-r--r--src/emu/x64run64.c1094
1 files changed, 0 insertions, 1094 deletions
diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c
deleted file mode 100644
index 40cf5eb9..00000000
--- a/src/emu/x64run64.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-#define _GNU_SOURCE

-#include <stdint.h>

-#include <stdio.h>

-#include <stdlib.h>

-#include <math.h>

-#include <string.h>

-#include <signal.h>

-#include <sys/types.h>

-#include <unistd.h>

-

-#include "debug.h"

-#include "box64stack.h"

-#include "box64cpu_util.h"

-#include "x64emu.h"

-#include "x64emu_private.h"

-#include "x64run_private.h"

-#include "x64primop.h"

-#include "x64trace.h"

-#include "x87emu_private.h"

-#include "box64context.h"

-#include "alternate.h"

-#include "emit_signals.h"

-

-#include "modrm.h"

-

-#ifdef TEST_INTERPRETER

-uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr)

-#else

-uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)

-#endif

-{

-    uint8_t opcode;

-    uint8_t nextop;

-    uint8_t tmp8u;   (void)tmp8u;

-    int16_t tmp16s;  (void)tmp16s;

-    uint16_t tmp16u; (void)tmp16u;

-    int32_t tmp32s;

-    uint32_t tmp32u;

-    uint64_t tmp64u;

-    reg64_t *oped, *opgd;

-    sse_regs_t *opex, *opgx;

-    int rep;

-    #ifdef TEST_INTERPRETER

-    x64emu_t* emu = test->emu;

-    #endif

-    int is_nan;

-    uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);

-

-    opcode = F8;

-    // REX prefix before the F0 are ignored

-    rex.rex = 0;

-    if(!rex.is32bits)

-        while(opcode>=0x40 && opcode<=0x4f) {

-            rex.rex = opcode;

-            opcode = F8;

-        }

-    rep = 0;

-    while((opcode==0xF2) || (opcode==0xF3)) {

-        rep = opcode-0xF1;

-        opcode = F8;

-    }

-    if(!rex.is32bits)

-        while(opcode>=0x40 && opcode<=0x4f) {

-            rex.rex = opcode;

-            opcode = F8;

-        }

-

-    switch(opcode) {

-        #define GO(B, OP)                                   \

-        case B+0:                                           \

-            nextop = F8;                                    \

-            GETEB_OFFS(0, tlsdata);                         \

-            GETGB;                                          \

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

-            break;                                          \

-        case B+1:                                           \

-            nextop = F8;                                    \

-            GETED_OFFS(0, tlsdata);                         \

-            GETGD;                                          \

-            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]); \

-            }                                               \

-            break;                                          \

-        case B+2:                                           \

-            nextop = F8;                                    \

-            GETEB_OFFS(0, tlsdata);                         \

-            GETGB;                                          \

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

-            break;                                          \

-        case B+3:                                           \

-            nextop = F8;                                    \

-            GETED_OFFS(0, tlsdata);                         \

-            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;

-

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

-        GO(0x08, or)                    /*  OR 0x08 -> 0x0D */

-        GO(0x10, adc)                   /* ADC 0x10 -> 0x15 */

-        GO(0x18, sbb)                   /* SBB 0x18 -> 0x1D */

-        GO(0x20, and)                   /* AND 0x20 -> 0x25 */

-        GO(0x28, sub)                   /* SUB 0x28 -> 0x2D */

-        GO(0x30, xor)                   /* XOR 0x30 -> 0x35 */

-        #undef GO

-        case 0x0F:

-            opcode = F8;

-            switch(opcode) {

-

-                case 0x10:

-                    switch(rep) {

-                        case 0: /* MOVUPS Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            GX->u128 = EX->u128;

-                            break;

-                        case 1: /* MOVSD Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            GX->q[0] = EX->q[0];

-                            if(!MODREG) {

-                                // EX is not a register

-                                GX->q[1] = 0;

-                            }

-                            break;

-                        case 2: /* MOVSS Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            GX->ud[0] = EX->ud[0];

-                            if(!MODREG) {

-                                // EX is not a register (reg to reg only move 31:0)

-                                GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;

-                            }

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-                case 0x11:

-                    switch(rep) {

-                        case 0: /* MOVUPS FS:Ex, Gx */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            EX->u128 = GX->u128;

-                            break;

-                        case 1: /* MOVSD Ex, Gx */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            EX->q[0] = GX->q[0];

-                            break;

-                        case 2: /* MOVSS FS:Ex, Gx */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            EX->ud[0] = GX->ud[0];

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0x18:

-                case 0x19:

-                case 0x1F: /* NOP (multi-byte) */

-                    nextop = F8;

-                    FAKEED(0);

-                    break;

-                case 0x28:

-                    switch(rep) {

-                        case 0: /* MOVAPS Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            GX->u128 = EX->u128;

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-                case 0x29:                      /* MOVAPS FS:Ex,Gx */

-                    switch(rep) {

-                        case 0:

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            EX->q[0] = GX->q[0];

-                            EX->q[1] = GX->q[1];

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0x58:

-                    switch(rep) {

-                        case 2: /* ADDSS Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            is_nan = isnanf(GX->f[0]) || isnanf(EX->f[0]);

-                            NAN_PROPAGATION(GX->f[0], EX->f[0], break);

-                            GX->f[0] += EX->f[0];

-                            if(!is_nan && isnanf(GX->f[0])) GX->f[0] = -NAN;

-                            break;

-

-                        default:

-                            return 0;

-                    }

-                    break;

-                case 0x59:

-                    switch(rep) {

-                        case 2: /* MULSS Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            NAN_PROPAGATION(GX->f[0], EX->f[0], break);

-                            GX->f[0] *= EX->f[0];

-                            break;

-

-                        default:

-                            return 0;

-                    }

-                    break;

-                case 0x5A:

-                    switch(rep) {

-                        case 2:  /* CVTSS2SD Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            GX->d[0] = EX->f[0];

-                            break;

-

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0x6F:

-                    switch(rep) {

-                        case 2: /* MOVDQU Gx, FS:Ex */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            memcpy(GX, EX, 16);    // unaligned...

-                            break;

-                            

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0x7F:  

-                    switch(rep) {

-                        case 2: /* MOVDQU FS:Ex, Gx */

-                            nextop = F8;

-                            GETEX_OFFS(0, tlsdata);

-                            GETGX;

-                            memcpy(EX, GX, 16);    // unaligned...

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0xAF:

-                    switch(rep) {

-                        case 0: /* IMUL Gd, FS:Ed */

-                            nextop = F8;

-                            GETED_OFFS(0, tlsdata);

-                            GETGD;

-                            if(rex.w)

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

-                            else

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

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0xB6:

-                    switch(rep) {

-                        case 0: /* MOVZX Gd, FS:Eb */

-                            nextop = F8;

-                            GETEB_OFFS(0, tlsdata);

-                            GETGD;

-                            GD->q[0] = EB->byte[0];

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-                case 0xB7:

-                    switch(rep) {

-                        case 0: /* MOVZX Gd, FS:Ew */

-                            nextop = F8;

-                            GETEW_OFFS(0, tlsdata);

-                            GETGD;

-                            GD->q[0] = EW->word[0];

-                            break;

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0xBA:                      

-                    nextop = F8;

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

-                        case 4:                 /* BT Ed,Ib */

-                            CHECK_FLAGS(emu);

-                            GETED_OFFS(1, tlsdata);

-                            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;

-                        case 5:             /* BTS Ed, Ib */

-                            CHECK_FLAGS(emu);

-                            GETED_OFFS(1, tlsdata);

-                            tmp8u = F8;

-                            if(rex.w) {

-                                tmp8u&=63;

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

-                                    SET_FLAG(F_CF);

-                                } else {

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

-                                    CLEAR_FLAG(F_CF);

-                                }

-                            } else {

-                                tmp8u&=31;

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

-                                    SET_FLAG(F_CF);

-                                } else {

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

-                                    CLEAR_FLAG(F_CF);

-                                }

-                                if(MODREG)

-                                    ED->dword[1] = 0;

-                            }

-                            if (BOX64ENV(dynarec_test)) {

-                                CLEAR_FLAG(F_OF);

-                                CLEAR_FLAG(F_SF);

-                                CLEAR_FLAG(F_AF);

-                                CLEAR_FLAG(F_PF);

-                            }

-                            break;

-                        case 6:             /* BTR Ed, Ib */

-                            CHECK_FLAGS(emu);

-                            GETED_OFFS(1, tlsdata);

-                            tmp8u = F8;

-                            if(rex.w) {

-                                tmp8u&=63;

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

-                                    SET_FLAG(F_CF);

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

-                                } else

-                                    CLEAR_FLAG(F_CF);

-                            } else {

-                                tmp8u&=31;

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

-                                    SET_FLAG(F_CF);

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

-                                } else

-                                    CLEAR_FLAG(F_CF);

-                                if(MODREG)

-                                    ED->dword[1] = 0;

-                            }

-                            if (BOX64ENV(dynarec_test)) {

-                                CLEAR_FLAG(F_OF);

-                                CLEAR_FLAG(F_SF);

-                                CLEAR_FLAG(F_AF);

-                                CLEAR_FLAG(F_PF);

-                            }

-                            break;

-                        case 7:             /* BTC Ed, Ib */

-                            CHECK_FLAGS(emu);

-                            GETED_OFFS(1, tlsdata);

-                            tmp8u = F8;

-                            if(rex.w) {

-                                tmp8u&=63;

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

-                                    SET_FLAG(F_CF);

-                                else

-                                    CLEAR_FLAG(F_CF);

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

-                            } else {

-                                tmp8u&=31;

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

-                                    SET_FLAG(F_CF);

-                                else

-                                    CLEAR_FLAG(F_CF);

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

-                                if(MODREG)

-                                    ED->dword[1] = 0;

-                            }

-                            if (BOX64ENV(dynarec_test)) {

-                                CLEAR_FLAG(F_OF);

-                                CLEAR_FLAG(F_SF);

-                                CLEAR_FLAG(F_AF);

-                                CLEAR_FLAG(F_PF);

-                            }

-                            break;

-

-                        default:

-                            return 0;

-                    }

-                    break;

-

-                case 0xBF:                      

-                    switch(rep) {

-                        case 0: /* MOVSX Gd,FS:Ew */

-                            nextop = F8;

-                            GETEW_OFFS(0, tlsdata);

-                            GETGD;

-                            if(rex.w)

-                                GD->sq[0] = EW->sword[0];

-                            else {

-                                GD->sdword[0] = EW->sword[0];

-                                GD->dword[1] = 0;

-                            }

-                            break;

-                        default:

-                            return 0;

-                        }

-                        break;

-

-                default:

-                    return 0;

-            }

-            break;

-

-        case 0x38:

-            nextop = F8;

-            GETEB_OFFS(0, tlsdata);

-            GETGB;

-            cmp8(emu, EB->byte[0], GB);

-            break;

-        case 0x39:

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.w)

-                cmp64(emu, ED->q[0], GD->q[0]);

-            else

-                cmp32(emu, ED->dword[0], GD->dword[0]);

-            break;

-

-        case 0x3B:

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.w)

-                cmp64(emu, GD->q[0], ED->q[0]);

-            else

-                cmp32(emu, GD->dword[0], ED->dword[0]);

-            break;

-

-

-        case 0x63:                      /* MOVSXD Gd, FS:Ed */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.is32bits) {

-                // ARPL here

-                // faking to always happy...

-                SET_FLAG(F_ZF);

-            } else {

-                if(rex.w)

-                    GD->sq[0] = ED->sdword[0];

-                else

-                    if(MODREG)

-                        GD->q[0] = ED->dword[0];    // not really a sign extension

-                    else

-                        GD->sdword[0] = ED->sdword[0];  // meh?

-            }

-            break;

-        case 0x64:                      /* FS: prefix */

-            #ifdef TEST_INTERPRETER

-            return Test64(test, rex, _FS, addr);

-            #else

-            return Run64(emu, rex, _FS, addr);

-            #endif

-            break;

-        case 0x65:                      /* GS: prefix */

-            #ifdef TEST_INTERPRETER

-            return Test64(test, rex, _GS, addr);

-            #else

-            return Run64(emu, rex, _GS, addr);

-            #endif

-            break;

-        case 0x66:

-            return Run6664(emu, rex, seg, addr);

-        case 0x67:

-            if(rex.is32bits)

-                return Run6764_32(emu, rex, seg, seg, addr);

-            else

-                return Run6764(emu, rex, seg, seg, addr);

-

-        case 0x69:                      /* IMUL Gd,Ed,Id */

-            nextop = F8;

-            GETED_OFFS(4, tlsdata);

-            GETGD;

-            tmp64u = F32S64;

-            if(rex.w)

-                GD->q[0] = imul64(emu, ED->q[0], tmp64u);

-            else

-                GD->q[0] = imul32(emu, ED->dword[0], tmp64u);

-            break;

-

-        case 0x6C:                      /* INSB DX */

-        case 0x6D:                      /* INSD DX */

-        case 0x6E:                      /* OUTSB DX */

-        case 0x6F:                      /* OUTSD DX */

-            return addr-1;  // skip 64/65 prefix and resume normal execution

-

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

-            nextop = F8;

-            GETEB_OFFS(1, tlsdata);

-            tmp8u = F8;

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

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

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

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

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

-                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;

-            }

-            break;

-        case 0x81:                      /* GRP Ed,Id */

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

-            nextop = F8;

-            GETED_OFFS((opcode==0x81)?4:1, tlsdata);

-            if(opcode==0x81) {

-                tmp32s = F32S;

-            } else {

-                tmp32s = F8S;

-            }

-            if(rex.w) {

-                tmp64u = (uint64_t)(int64_t)tmp32s;

-                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;

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

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

-                    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;

-                }

-            } else {

-                tmp32u = (uint32_t)tmp32s;

-                if(MODREG)

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

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

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

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

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

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

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

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

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

-                    }

-                else

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

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

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

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

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

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

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

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

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

-                    }

-            }

-            break;

-

-        case 0x85:                      /* TEST Ed,Gd */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.w)

-                test64(emu, ED->q[0], GD->q[0]);

-            else

-                test32(emu, ED->dword[0], GD->dword[0]);

-            break;

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

-            nextop = F8;

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

-            GETEB_OFFS(0, tlsdata);

-            GETGB;

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

-                tmp8u = GB;

-                GB = EB->byte[0];

-                EB->byte[0] = tmp8u;

-            } else {

-                GB = native_lock_xchg_b(EB, GB);

-            }

-            // dynarec use need it's own mecanism

-#else

-            GETEB_OFFS(0, tlsdata);

-            GETGB;

-            if(!MODREG)

-                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);

-#endif                

-            break;

-

-        case 0x88:                      /* MOV FS:Eb,Gb */

-            nextop = F8;

-            GETEB_OFFS(0, tlsdata);

-            GETGB;

-            EB->byte[0] = GB;

-            break;

-        case 0x89:                    /* MOV FS:Ed,Gd */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.w) {

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

-            } else {

-                if(MODREG)

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

-                else

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

-            }

-            break;

-        case 0x8A:                      /* MOV Gb, FS:Eb */

-            nextop = F8;

-            GETEB_OFFS(0, tlsdata);

-            GETGB;

-            GB = EB->byte[0];

-            break;

-        case 0x8B:                      /* MOV Gd, FS:Ed */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            GETGD;

-            if(rex.w)

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

-            else

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

-            break;

-

-        case 0x8D:                      /* LEA Gd,M */

-            nextop = F8;

-            GETGD;

-            tmp64u = GETEA(0);

-            if(rex.w)

-                GD->q[0] = tmp64u;

-            else

-                GD->q[0] = tmp64u&0xffffffff;

-            break;

-        case 0x8E:                      /* MOV Seg, Seg:Ew */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            emu->segs[((nextop&0x38)>>3)] = ED->word[0];

-            emu->segs_serial[((nextop&0x38)>>3)] = 0;

-            break;

-        case 0x8F:                      /* POP FS:Ed */

-            nextop = F8;

-            if(MODREG) {

-                emu->regs[(nextop&7)+(rex.b<<3)].q[0] = Pop64(emu);

-            } else {

-                if(rex.is32bits) {

-                    tmp32u = Pop32(emu);  // this order allows handling POP [ESP] and variant

-                    GETED_OFFS(0, tlsdata);

-                    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_OFFS(0, tlsdata);

-                    R_RSP -= sizeof(void*); // to prevent issue with SEGFAULT

-                    ED->q[0] = tmp64u;

-                    R_RSP += sizeof(void*);

-                }

-            }

-            break;

-        case 0x90:                      /* NOP */

-            break;

-

-        case 0x9D:                      /* POPF */

-            return addr-1;  // skip 64/65 prefix and resume normal execution

-

-        case 0xA1:                      /* MOV EAX,FS:Od */

-            if(rex.is32bits) {

-                tmp32s = F32S;

-                R_EAX = *(uint32_t*)(tlsdata+tmp32s);

-            } else {

-                tmp64u = F64;

-                if(rex.w)

-                    R_RAX = *(uint64_t*)(tlsdata+tmp64u);

-                else

-                    R_RAX = *(uint32_t*)(tlsdata+tmp64u);

-            }

-            break;

-        case 0xA2:                      /* MOV Ob,AL */

-            if(rex.is32bits) {

-                tmp32s = F32S;

-                *(uint8_t*)(uintptr_t)(tlsdata+tmp32s) = R_AL;

-            } else {

-                tmp64u = F64;

-                *(uint8_t*)(tlsdata+tmp64u) = R_AL;

-            }

-            break;

-        case 0xA3:                      /* MOV FS:Od,EAX */

-            if(rex.is32bits) {

-                tmp32s = F32S;

-                *(uint32_t*)(uintptr_t)(tlsdata+tmp32s) = R_EAX;

-            } else {

-                tmp64u = F64;

-                if(rex.w)

-                    *(uint64_t*)(tlsdata+tmp64u) = R_RAX;

-                else

-                    *(uint32_t*)(tlsdata+tmp64u) = R_EAX;

-            }

-            break;

-        case 0xC4:                      /* LES Gd,Ed */

-            nextop = F8;

-            if(rex.is32bits && !(MODREG)) {

-                GETED(0);

-                GETGD;

-                emu->segs[_ES] = *(uint16_t*)(((char*)ED) + 4);

-                emu->segs_serial[_ES] = 0;

-                GD->dword[0] = *(uint32_t*)ED;

-            } else {

-                vex_t vex = {0};

-                vex.rex = rex;

-                tmp8u = nextop;

-                vex.m = tmp8u&0b00011111;

-                vex.rex.b = (tmp8u&0b00100000)?0:1;

-                vex.rex.x = (tmp8u&0b01000000)?0:1;

-                vex.rex.r = (tmp8u&0b10000000)?0:1;

-                tmp8u = F8;

-                vex.p = tmp8u&0b00000011;

-                vex.l = (tmp8u>>2)&1;

-                vex.v = ((~tmp8u)>>3)&0b1111;

-                vex.rex.w = (tmp8u>>7)&1;

-                #ifdef TEST_INTERPRETER 

-                addr = Test64AVX(test, vex, addr, tlsdata);

-                #else

-                addr = Run64AVX(emu, vex, addr, tlsdata);

-                #endif

-            }

-            break;

-        case 0xC5:                      /* LDS Gd,Ed */

-            nextop = F8;

-            if(rex.is32bits && !(MODREG)) {

-                GETED(0);

-                GETGD;

-                emu->segs[_DS] = *(uint16_t*)(((char*)ED) + 4);

-                emu->segs_serial[_DS] = 0;

-                GD->dword[0] = *(uint32_t*)ED;

-            } else {

-                vex_t vex = {0};

-                vex.rex = rex;

-                tmp8u = nextop;

-                vex.p = tmp8u&0b00000011;

-                vex.l = (tmp8u>>2)&1;

-                vex.v = ((~tmp8u)>>3)&0b1111;

-                vex.rex.r = (tmp8u&0b10000000)?0:1;

-                vex.rex.b = 0;

-                vex.rex.x = 0;

-                vex.rex.w = 0;

-                vex.m = VEX_M_0F;

-                #ifdef TEST_INTERPRETER 

-                addr = Test64AVX(test, vex, addr, tlsdata);

-                #else

-                addr = Run64AVX(emu, vex, addr, tlsdata);

-                #endif

-            }

-            break;

-        case 0xC6:                      /* MOV FS:Eb, Ib */

-            nextop = F8;

-            GETEB_OFFS(1, tlsdata);

-            EB->byte[0] = F8;

-            break;

-        case 0xC7:                      /* MOV FS:Ed, Id */

-            nextop = F8;

-            GETED_OFFS(4, tlsdata);

-            if(rex.w)

-                ED->q[0] = F32S64;

-            else

-                if(MODREG)

-                    ED->q[0] = F32;

-                else

-                    ED->dword[0] = F32;

-            break;

-

-        case 0xD1:                      /* GRP2 Ed,1 */

-        case 0xD3:                      /* GRP2 Ed,CL */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

-            tmp8u = (opcode==0xD1)?1:R_CL;

-            if(rex.w) {

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

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

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

-                    case 2: ED->q[0] = rcl64(emu, ED->q[0], tmp8u); break;

-                    case 3: ED->q[0] = rcr64(emu, ED->q[0], tmp8u); break;

-                    case 4: 

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

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

-                    case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break;

-                }

-            } else {

-                if(MODREG)

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

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

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

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

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

-                        case 4: 

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

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

-                        case 7: ED->q[0] = sar32(emu, ED->dword[0], tmp8u); break;

-                    }

-                else

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

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

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

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

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

-                        case 4: 

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

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

-                        case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;

-                    }

-            }

-            break;

-

-        case 0xD8:                      /* x87 opcodes */

-            #ifdef TEST_INTERPRETER

-            return TestD8(test, rex, addr, tlsdata);

-            #else

-            return RunD8(emu, rex, addr, tlsdata);

-            #endif

-            break;

-        case 0xD9:                      /* x87 opcodes */

-            #ifdef TEST_INTERPRETER

-            return TestD9(test, rex, addr, tlsdata);

-            #else

-            return RunD9(emu, rex, addr, tlsdata);

-            #endif

-            break;

-

-        case 0xEB:                      /* JMP Ib */

-            return addr-1;  // skip 64/65 prefix and resume normal execution

-

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

-            nextop = F8;

-            tmp8u = (nextop>>3)&7;

-            GETEB_OFFS((tmp8u<2)?1:0, tlsdata);

-            switch(tmp8u) {

-                case 0: 

-                case 1:                 /* TEST Eb,Ib */

-                    tmp8u = F8;

-                    test8(emu, EB->byte[0], tmp8u);

-                    break;

-                case 2:                 /* NOT Eb */

-                    EB->byte[0] = not8(emu, EB->byte[0]);

-                    break;

-                case 3:                 /* NEG Eb */

-                    EB->byte[0] = neg8(emu, EB->byte[0]);

-                    break;

-                case 4:                 /* MUL AL,Eb */

-                    mul8(emu, EB->byte[0]);

-                    break;

-                case 5:                 /* IMUL AL,Eb */

-                    imul8(emu, EB->byte[0]);

-                    break;

-                case 6:                 /* DIV Eb */

-                    if(!EB->byte[0])

-                        EmitDiv0(emu, (void*)R_RIP, 1);

-                    div8(emu, EB->byte[0]);

-                    break;

-                case 7:                 /* IDIV Eb */

-                    if(!EB->byte[0])

-                        EmitDiv0(emu, (void*)R_RIP, 1);

-                    idiv8(emu, EB->byte[0]);

-                    break;

-            }

-            break;

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

-            nextop = F8;

-            tmp8u = (nextop>>3)&7;

-            GETED_OFFS((tmp8u<2)?4:0, tlsdata);

-            if(rex.w) {

-                switch(tmp8u) {

-                    case 0: 

-                    case 1:                 /* TEST Ed,Id */

-                        tmp64u = F32S64;

-                        test64(emu, ED->q[0], tmp64u);

-                        break;

-                    case 2:                 /* NOT Ed */

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

-                        break;

-                    case 3:                 /* NEG Ed */

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

-                        break;

-                    case 4:                 /* MUL RAX,Ed */

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

-                        break;

-                    case 5:                 /* IMUL RAX,Ed */

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

-                        break;

-                    case 6:                 /* DIV Ed */

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

-                        break;

-                    case 7:                 /* IDIV Ed */

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

-                        break;

-                }

-            } else {

-                switch(tmp8u) {

-                    case 0: 

-                    case 1:                 /* TEST Ed,Id */

-                        tmp32u = F32;

-                        test32(emu, ED->dword[0], tmp32u);

-                        break;

-                    case 2:                 /* NOT Ed */

-                        if(MODREG)

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

-                        else

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

-                        break;

-                    case 3:                 /* NEG Ed */

-                        if(MODREG)

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

-                        else

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

-                        break;

-                    case 4:                 /* MUL EAX,Ed */

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

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

-                        break;

-                    case 5:                 /* IMUL EAX,Ed */

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

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

-                        break;

-                    case 6:                 /* DIV Ed */

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

-                        //emu->regs[_AX].dword[1] = 0;  // already put high regs to 0

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

-                        break;

-                    case 7:                 /* IDIV Ed */

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

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

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

-                        break;

-                }

-            }

-            break;

-            

-        case 0xFF:                      /* GRP 5 Ed */

-            nextop = F8;

-            GETED_OFFS(0, tlsdata);

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

-                case 0:                 /* INC Ed */

-                    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]);

-                    }

-                    break;

-                case 1:                 /* DEC Ed */

-                    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]);

-                    }

-                    break;

-                case 2:                 /* CALL NEAR Ed */

-                    if(rex.is32bits) {

-                        tmp64u = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);

-                        Push32(emu, addr);

-                    } else {

-                        tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);

-                        Push64(emu, addr);

-                    }

-                    addr = tmp64u;

-                    break;

-                case 3:                 /* CALL FAR Ed */

-                    if(MODREG) {

-                        printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));

-                        emu->quit=1;

-                        emu->error |= ERR_ILLEGAL;

-                        return 0;

-                    } else {

-                        if(rex.is32bits || !rex.w) {

-                            Push32(emu, R_CS);

-                            Push32(emu, addr);

-                            R_RIP = addr = ED->dword[0];

-                            R_CS = ED->word[2];

-                        } else {

-                            Push64(emu, R_CS);

-                            Push64(emu, addr);

-                            R_RIP = addr = ED->q[0];

-                            R_CS = (ED+1)->word[0];

-                        }

-                        return 0;  // exit loop to recompute new CS...

-                    }

-                    break;

-                case 4:                 /* JMP NEAR Ed */

-                    if(rex.is32bits)

-                        addr = (uintptr_t)getAlternate((void*)(uintptr_t)ED->dword[0]);

-                    else

-                        addr = (uintptr_t)getAlternate((void*)ED->q[0]);

-                    break;

-                case 5:                 /* JMP FAR Ed */

-                    if(MODREG) {

-                        printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));

-                        emu->quit=1;

-                        emu->error |= ERR_ILLEGAL;

-                        return 0;

-                    } else {

-                        if(rex.is32bits || !rex.w) {

-                            R_RIP = addr = ED->dword[0];

-                            R_CS = ED->word[2];

-                        } else {

-                            R_RIP = addr = ED->q[0];

-                            R_CS = (ED+1)->word[0];

-                        }

-                    }

-                    break;

-                case 6:                 /* Push Ed */

-                    if(rex.is32bits) {

-                        tmp32u = ED->dword[0];

-                        Push32(emu, tmp32u);  // avoid potential issue with push [esp+...]

-                    } else {

-                        tmp64u = ED->q[0];  // rex.w ignored

-                        Push64(emu, tmp64u);  // avoid potential issue with push [esp+...]

-                    }

-                    break;

-                default:

-                    printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));

-                    emu->quit=1;

-                    emu->error |= ERR_ILLEGAL;

-                    return 0;

-            }

-            break;

-        default:

-            return 0;

-    }

-    return addr;

-}