about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-04-01 15:35:34 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-04-01 15:35:34 +0200
commitdfbdd81d41f2efc2a219defe6874395aa44c6e38 (patch)
tree91048c1329908ca4cdab950acb14cf63874d5934 /src
parentb474a9061b08dedcbf06032e1ab52e18ab69e496 (diff)
downloadbox64-dfbdd81d41f2efc2a219defe6874395aa44c6e38.tar.gz
box64-dfbdd81d41f2efc2a219defe6874395aa44c6e38.zip
[DYNAREC] Fixed 67 8D opcde, and remove hack for 67 REX.W, it was wrong
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h1
-rwxr-xr-xsrc/dynarec/dynarec_arm64_67.c9
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.c115
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h4
4 files changed, 123 insertions, 6 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 5da1b06d..95a44679 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -137,6 +137,7 @@
 #define ADDx_REG_LSL(Rd, Rn, Rm, lsl)       EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
 #define ADDw_REG(Rd, Rn, Rm)                EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
 #define ADDSw_REG(Rd, Rn, Rm)               EMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
+#define ADDw_REG_LSL(Rd, Rn, Rm, lsl)       EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
 #define ADDxw_REG(Rd, Rn, Rm)               EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
 #define ADDSxw_REG(Rd, Rn, Rm)              EMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
 #define ADDxw_REG_LSR(Rd, Rn, Rm, lsr)      EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
diff --git a/src/dynarec/dynarec_arm64_67.c b/src/dynarec/dynarec_arm64_67.c
index ce275bc9..fe381f95 100755
--- a/src/dynarec/dynarec_arm64_67.c
+++ b/src/dynarec/dynarec_arm64_67.c
@@ -41,9 +41,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         opcode = F8;

     }

 

-    if(rex.w)   // rex.w cancels "67"

-        return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);

-

     switch(opcode) {

 

         case 0x8D:

@@ -54,9 +51,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 DEFAULT;

             } else {                    // mem <= reg

                 // should a geted32 be created, to use 32bits regs instead of 64bits?

-                addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);

-                if(ed>=xRAX && !rex.w) {

-                    MOVw_REG(gd, gd);   //truncate the higher 32bits as asked

+                addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);

+                if(ed!=gd) {

+                    MOVw_REG(gd, ed);

                 }

             }

             break;

diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c
index 3d616bfb..7b0cdc90 100755
--- a/src/dynarec/dynarec_arm64_helper.c
+++ b/src/dynarec/dynarec_arm64_helper.c
@@ -140,6 +140,121 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
     return addr;
 }
 
+/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
+uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
+{
+    uint8_t ret = x2;
+    uint8_t scratch = x2;
+    *fixaddress = 0;
+    if(hint>0) ret = hint;
+    if(hint>0 && hint<xRAX) scratch = hint;
+    int absmin = 0;
+    if(s) absmin=-absmax;
+    MAYUSE(scratch);
+    if(!(nextop&0xC0)) {
+        if((nextop&7)==4) {
+            uint8_t sib = F8;
+            int sib_reg = ((sib>>3)&7)+(rex.x<<3);
+            if((sib&0x7)==5) {
+                uint32_t tmp = F32;
+                if (sib_reg!=4) {
+                    if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
+                        MOV32w(scratch, tmp);
+                        ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
+                    } else {
+                        LSLw(ret, xRAX+sib_reg, (sib>>6));
+                        *fixaddress = tmp;
+                    }
+                } else {
+                    MOV32w(ret, tmp);
+                }
+            } else {
+                if (sib_reg!=4) {
+                    ADDw_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
+                } else {
+                    ret = xRAX+(sib&0x7)+(rex.b<<3);
+                }
+            }
+        } else if((nextop&7)==5) {
+            uint32_t tmp = F32;
+            MOV32w(ret, tmp);
+            GETIP(addr+delta);
+            ADDw_REG(ret, ret, xRIP);
+        } else {
+            ret = xRAX+(nextop&7)+(rex.b<<3);
+        }
+    } else {
+        int64_t i64;
+        uint8_t sib = 0;
+        int sib_reg = 0;
+        if((nextop&7)==4) {
+            sib = F8;
+            sib_reg = ((sib>>3)&7)+(rex.x<<3);
+        }
+        if(nextop&0x80)
+            i64 = F32S;
+        else 
+            i64 = F8S;
+        if(i64==0 || ((i64>=absmin) && (i64<=absmax)  && !(i64&mask))) {
+            *fixaddress = i64;
+            if((nextop&7)==4) {
+                if (sib_reg!=4) {
+                    ADDw_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
+                } else {
+                    ret = xRAX+(sib&0x07)+(rex.b<<3);
+                }
+            } else
+                ret = xRAX+(nextop&0x07)+(rex.b<<3);
+        } else {
+            int64_t sub = (i64<0)?1:0;
+            if(sub) i64 = -i64;
+            if(i64<0x1000) {
+                if((nextop&7)==4) {
+                    if (sib_reg!=4) {
+                        ADDw_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
+                    } else {
+                        scratch = xRAX+(sib&0x07)+(rex.b<<3);
+                    }
+                } else
+                    scratch = xRAX+(nextop&0x07)+(rex.b<<3);
+                if(sub) {
+                    SUBw_U12(ret, scratch, i64);
+                } else {
+                    ADDw_U12(ret, scratch, i64);
+                }
+            } else {
+                MOV32w(scratch, i64);
+                if((nextop&7)==4) {
+                    if (sib_reg!=4) {
+                        if(sub) {
+                            SUBw_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
+                        } else {
+                            ADDw_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
+                        }
+                        ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
+                    } else {
+                        PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
+                        if(sub) {
+                            SUBw_REG(ret, tmp, scratch);
+                        } else {
+                            ADDw_REG(ret, tmp, scratch);
+                        }
+                    }
+                } else {
+                    PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
+                    if(sub) {
+                        SUBw_REG(ret, tmp, scratch);
+                    } else {
+                        ADDw_REG(ret, tmp, scratch);
+                    }
+                }
+            }
+        }
+    }
+    *ed = ret;
+    return addr;
+}
+
 /* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
 uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s)
 {
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 2acbdc1d..b356e0d4 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -575,6 +575,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define dynarec64_F30F     STEPNAME(dynarec64_F30F)
 
 #define geted           STEPNAME(geted_)
+#define geted32         STEPNAME(geted32_)
 #define geted16         STEPNAME(geted16_)
 #define jump_to_epilog  STEPNAME(jump_to_epilog_)
 #define jump_to_next    STEPNAME(jump_to_next_)
@@ -685,6 +686,9 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
 
 /* setup r2 to address pointed by */
+uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
+
+/* setup r2 to address pointed by */
 uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s);