about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-09-01 15:03:29 +0200
committerptitSeb <sebastien.chev@gmail.com>2025-09-01 15:03:29 +0200
commitcb3cfa991f5cf20ce7f781cc9b824541b0549fdc (patch)
treeac8d1760b6c8eae03ec9c4af49a0883d0c9765ff /src
parent4b6766c84bfe4a9101e59696527b37d594fbe3f5 (diff)
downloadbox64-cb3cfa991f5cf20ce7f781cc9b824541b0549fdc.tar.gz
box64-cb3cfa991f5cf20ce7f781cc9b824541b0549fdc.zip
[INTERP] Fixed and improved 67 prefixed 32bits opcodes
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64run.c33
-rw-r--r--src/emu/x64run_private.c26
2 files changed, 28 insertions, 31 deletions
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index fc9e8270..34bd0368 100644
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -864,15 +864,25 @@ x64emurun:
             R_AH = (uint8_t)emu->eflags.x64;
             break;
         case 0xA0:                      /* MOV AL,Ob */
-            if(rex.is32bits)
+            if(rex.is32bits && rex.is67)
+                R_AL = *(uint8_t*)(uintptr_t)(ptr_t)(rex.offset+F16S);
+            else if(rex.is32bits || rex.is67)
                 R_AL = *(uint8_t*)(uintptr_t)(ptr_t)(F32+rex.offset);
             else
                 R_AL = *(uint8_t*)(F64+rex.offset);
             break;
         case 0xA1:                      /* MOV EAX,Od */
-            if(rex.is32bits)
-                R_EAX = *(int32_t*)(uintptr_t)(ptr_t)(F32+rex.offset);
-            else {
+            if(rex.is32bits && rex.is67)
+                R_EAX = *(uint32_t*)(uintptr_t)(ptr_t)(rex.offset+F16S);
+            else if(rex.is32bits || rex.is67) {
+                if(rex.w)
+                    R_RAX = *(int64_t*)(uintptr_t)(ptr_t)(F32+rex.offset);
+                else {
+                    R_EAX = *(int32_t*)(uintptr_t)(ptr_t)(F32+rex.offset);
+                    if(!rex.is32bits)
+                        R_RAX = R_EAX;
+                }
+            } else {
                 if(rex.w)
                     R_RAX = *(uint64_t*)(F64+rex.offset);
                 else
@@ -880,15 +890,22 @@ x64emurun:
             }
             break;
         case 0xA2:                      /* MOV Ob,AL */
-            if(rex.is32bits)
+            if(rex.is32bits && rex.is67)
+                *(uint8_t*)(uintptr_t)(ptr_t)(rex.offset+F16S) = R_AL;
+            else if(rex.is32bits || rex.is67)
                 *(uint8_t*)(uintptr_t)(ptr_t)(F32+rex.offset) = R_AL;
             else
                 *(uint8_t*)(F64+rex.offset) = R_AL;
             break;
         case 0xA3:                      /* MOV Od,EAX */
-            if(rex.is32bits)
-                *(uint32_t*)(uintptr_t)(ptr_t)(F32+rex.offset) = R_EAX;
-            else {
+            if(rex.is32bits && rex.is67)
+                *(uint32_t*)(uintptr_t)(ptr_t)(rex.offset+F16S) = R_EAX;
+            else if(rex.is32bits || rex.is67) {
+                if(rex.w)
+                    *(uint64_t*)(uintptr_t)(ptr_t)(F32+rex.offset) = R_RAX;
+                else
+                    *(uint32_t*)(uintptr_t)(ptr_t)(F32+rex.offset) = R_EAX;
+            } else {
                 if(rex.w)
                     *(uint64_t*)(F64+rex.offset) = R_RAX;
                 else
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index be268d4d..9fcd0b46 100644
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -233,7 +233,7 @@ reg64_t* GetECommon_32(x64emu_t* emu, uintptr_t* addr, uint8_t m, uint32_t base)
         return (reg64_t*)(uintptr_t)base;
     }
 }
-reg64_t* GetECommon_16(x64emu_t *emu, uintptr_t* addr, uint8_t m, uint32_t base)
+reg64_t* GetECommon_16(x64emu_t *emu, uintptr_t* addr, uint8_t m, uint64_t base)
 {
     switch(m&7) {
         case 0: base+= R_BX+R_SI; break;
@@ -242,13 +242,13 @@ reg64_t* GetECommon_16(x64emu_t *emu, uintptr_t* addr, uint8_t m, uint32_t base)
         case 3: base+= R_BP+R_DI; break;
         case 4: base+=      R_SI; break;
         case 5: base+=      R_DI; break;
-        case 6: base+=      R_BP; break;
+        case 6: if((m>>6)&3) base += R_BP; else base += F16S(addr); break;
         case 7: base+=      R_BX; break;
     }
     switch((m>>6)&3) {
-        case 0: if((m&7)==6) base= F16S(addr); break;
         case 1: base += F8S(addr); break;
         case 2: base += F16S(addr); break;
+        // case 0 is already dealt with on case 6
         // case 3 is C0..C7, already dealt with
     }
     return (reg64_t*)(uintptr_t)base;
@@ -344,11 +344,6 @@ reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_
 
 reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
 {
-    if(rex.is67 && rex.is32bits) {
-        printf_log(LOG_NONE, "Need 32bits 67 prefix GetEb\n");
-        emu->quit = 1;
-        return NULL;
-    }
     uint8_t m = v&0xC7;    // filter Eb
     if(m>=0xC0) {
         if(rex.rex) {
@@ -362,11 +357,6 @@ reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del
 
 reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
 {
-    if(rex.is67 && rex.is32bits) {
-        printf_log(LOG_NONE, "Need 32bits 67 prefix TestEb\n");
-        test->emu->quit = 1;
-        return NULL;
-    }
     uint8_t m = v&0xC7;    // filter Eb
     if(m>=0xC0) {
         if(rex.rex) {
@@ -386,11 +376,6 @@ reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t
 
 reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
 {
-    if(rex.is67 && rex.is32bits) {
-        printf_log(LOG_NONE, "Need 32bits 67 prefix GetEd\n");
-        emu->quit = 1;
-        return NULL;
-    }
     uint8_t m = v&0xC7;    // filter Ed
     if(m>=0xC0) {
          return &emu->regs[(m&0x07)+(rex.b<<3)];
@@ -399,11 +384,6 @@ reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del
 
 reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
 {
-    if(rex.is67 && rex.is32bits) {
-        printf_log(LOG_NONE, "Need 32bits 67 prefix TestEd\n");
-        test->emu->quit = 1;
-        return NULL;
-    }
     uint8_t m = v&0xC7;    // filter Ed
     if(m>=0xC0) {
         return &test->emu->regs[(m&0x07)+(rex.b<<3)];