about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-04 12:18:40 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-04 12:18:40 +0100
commitc24149e40f5fe1ab3f7edbd6c73af91c36fd5468 (patch)
tree9848365a13d31b36ae80f405b7b916f067ced245
parent2101c52e2d14878a793622b712e8be8c6b2eb530 (diff)
downloadbox64-c24149e40f5fe1ab3f7edbd6c73af91c36fd5468.tar.gz
box64-c24149e40f5fe1ab3f7edbd6c73af91c36fd5468.zip
Added REX FF opcodes
-rwxr-xr-xsrc/emu/x64run.c72
-rwxr-xr-xsrc/emu/x64run_private.h2
2 files changed, 69 insertions, 5 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index d25ba332..c53028b5 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -42,9 +42,6 @@ int Run(x64emu_t *emu, int step)
     int64_t tmp64s, tmp64s2;
     double d;
     float f;
-    int64_t ll;
-    sse_regs_t *opex, eax1;
-    mmx_regs_t *opem, eam1;
     rex_t rex;
     int unimp = 0;
 
@@ -250,9 +247,76 @@ x64emurun:
             if(rex.w)
                 GD->q[0] = (uint64_t)ED;
             else
-                GD->dword[0] = (uint32_t)ED;
+                GD->dword[0] = (uint32_t)(uintptr_t)ED;
             break;
 
+        case 0xFF:                      /* GRP 5 Ed */
+            nextop = F8;
+            GETED;
+            switch((nextop>>3)&7) {
+                case 0:                 /* INC Ed */
+                    if(rex.w)
+                        ED->q[0] = inc64(emu, ED->q[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
+                        ED->dword[0] = dec32(emu, ED->dword[0]);
+                    break;
+                case 2:                 /* CALL NEAR Ed */
+                    tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
+                    Push(emu, R_RIP);
+                    R_RIP = tmp64u;
+                    STEP
+                    break;
+                case 3:                 /* CALL FAR Ed */
+                    if(nextop>0xC0) {
+                        R_RIP = emu->old_ip;
+                        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;
+                        goto fini;
+                    } else {
+                        Push16(emu, R_CS);
+                        Push(emu, R_RIP);
+                        R_RIP = ED->dword[0];
+                        R_CS = (ED+1)->word[0];
+                        goto fini;  // exit loop to recompute new CS...
+                    }
+                    break;
+                case 4:                 /* JMP NEAR Ed */
+                    R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]);
+                    STEP
+                    break;
+                case 5:                 /* JMP FAR Ed */
+                    if(nextop>0xc0) {
+                        R_RIP = emu->old_ip;
+                        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;
+                        goto fini;
+                    } else {
+                        R_RIP = ED->q[0];
+                        R_CS = (ED+1)->word[0];
+                        STEP
+                        goto fini;  // exit loop to recompute CS...
+                    }
+                    break;
+                case 6:                 /* Push Ed */
+                    tmp64u = ED->q[0];  // rex.w ignored
+                    Push(emu, tmp64u);  // avoid potential issue with push [esp+...]
+                    break;
+                default:
+                    R_RIP = emu->old_ip;
+                    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;
+                    goto fini;
+            }
+            break;
         default:
             unimp = 1;
             goto fini;
diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index 57a100bd..3700147d 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -82,7 +82,7 @@ static inline reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m)
             base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
             return (reg64_t*)base;
         } else if (m==0x5) { //disp32
-            uintptr_t base = Fetch32(emu);
+            int32_t base = Fetch32s(emu);
             return (reg64_t*)(base+R_RIP);
         }
         return (reg64_t*)(emu->regs[m].q[0]+(rex.b<<3));