about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c9
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c40
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_shift.c41
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.c6
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h2
5 files changed, 55 insertions, 43 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index b2ceb004..c6145cf4 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -1664,16 +1664,17 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 case 5:
                     if (opcode == 0xD0) {
                         INST_NAME("SHR Eb, 1");
+                        GETEB(x1, 0);
                         MOV32w(x2, 1);
                     } else {
                         INST_NAME("SHR Eb, CL");
+                        GETEB(x1, 0);
                         ANDI(x2, xRCX, 0x1F);
                         BEQ_NEXT(x2, xZR);
                     }
                     SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
                     if (box64_dynarec_safeflags > 1)
                         MAYSETFLAGS();
-                    GETEB(x1, 0);
                     emit_shr8(dyn, ninst, x1, x2, x5, x4, x6);
                     EBBACK();
                     break;
@@ -1733,7 +1734,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     INST_NAME("ROL Ed, CL");
                     SETFLAGS(X_OF | X_CF, SF_SUBSET);
                     GETED(0);
-                    emit_rol32(dyn, ninst, rex, ed, xRCX, x3, x4);
+                    ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f);
+                    emit_rol32(dyn, ninst, rex, ed, x6, x3, x4);
                     WBACK;
                     if (!wback && !rex.w) ZEROUP(ed);
                     break;
@@ -1741,7 +1743,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     INST_NAME("ROR Ed, CL");
                     SETFLAGS(X_OF | X_CF, SF_SUBSET);
                     GETED(0);
-                    emit_ror32(dyn, ninst, rex, ed, xRCX, x3, x4);
+                    ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f);
+                    emit_ror32(dyn, ninst, rex, ed, x6, x3, x4);
                     WBACK;
                     if (!wback && !rex.w) ZEROUP(ed);
                     break;
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 0f795e61..7a0fbf7e 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -669,12 +669,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xA4:
             nextop = F8;
             INST_NAME("SHLD Ed, Gd, Ib");
-            SETFLAGS(X_ALL, SF_SET_PENDING);
-            GETED(1);
-            GETGD;
-            u8 = F8;
-            emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
-            WBACK;
+            if (geted_ib(dyn, addr, ninst, nextop)) {
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                GETED(1);
+                GETGD;
+                u8 = F8;
+                emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
+                WBACK;
+            } else {
+                FAKEED;
+                F8;
+            }
             break;
         case 0xAB:
             INST_NAME("BTS Ed, Gd");
@@ -716,13 +721,18 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xAC:
             nextop = F8;
             INST_NAME("SHRD Ed, Gd, Ib");
-            SETFLAGS(X_ALL, SF_SET_PENDING);
-            GETED(1);
-            GETGD;
-            u8 = F8;
-            u8 &= (rex.w ? 0x3f : 0x1f);
-            emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
-            WBACK;
+            if (geted_ib(dyn, addr, ninst, nextop)) {
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                GETED(1);
+                GETGD;
+                u8 = F8;
+                u8 &= (rex.w ? 0x3f : 0x1f);
+                emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
+                WBACK;
+            } else {
+                FAKEED;
+                F8;
+            }
             break;
         case 0xAE:
             nextop = F8;
@@ -916,6 +926,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     if (wback) {
                         SDxw(ed, wback, fixedaddress);
                         SMWRITE();
+                    } else if (!rex.w) {
+                        ZEROUP(ed);
                     }
                     MARK;
                     break;
@@ -935,6 +947,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     if (wback) {
                         SDxw(ed, wback, fixedaddress);
                         SMWRITE();
+                    } else if (!rex.w) {
+                        ZEROUP(ed);
                     }
                     MARK;
                     break;
diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c
index 291674eb..2b83ccba 100644
--- a/src/dynarec/la64/dynarec_la64_emit_shift.c
+++ b/src/dynarec/la64/dynarec_la64_emit_shift.c
@@ -514,7 +514,7 @@ void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
     IFX (X_PEND) {
         ST_H(s2, xEmu, offsetof(x64emu_t, op2));
         ST_H(s1, xEmu, offsetof(x64emu_t, op1));
-        SET_DF(s4, d_sar8);
+        SET_DF(s4, d_sar16);
     } else IFX (X_ALL) {
         SET_DFNONE();
     }
@@ -612,6 +612,8 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
         }
         OR(xFlags, xFlags, s3);
     }
+    // For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
+    // OF nop
 
     if (rex.w) {
         SRAI_D(s1, s1, c);
@@ -714,17 +716,11 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
             X64_ROTL_W(s1, s2);
     }
 
-    if (rex.w) {
-        ANDI(s4, s2, 0x3f);
-    } else {
-        ANDI(s4, s2, 0x1f);
-    }
-
     if (!rex.w) ZEROUP(s1);
-    BEQ_NEXT(s4, xZR);
+    BEQ_NEXT(s2, xZR);
 
-    SLLxw(s3, s1, s4);
-    NEG_D(s4, s4);
+    SLLxw(s3, s1, s2);
+    NEG_D(s4, s2);
     ADDI_D(s4, s4, rex.w ? 64 : 32);
     SRLxw(s1, s1, s4);
     OR(s1, s3, s1);
@@ -745,12 +741,13 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     }
     IFX (X_OF) {
         // the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result.
-        ADDI_D(s3, xZR, 1);
-        BNE_NEXT(s2, s3);
+        ADDI_D(s3, s2, -1);
+        BNEZ_MARK(s3);
         SRLIxw(s3, s1, rex.w ? 63 : 31);
         XOR(s3, s3, s4); // s3: MSB, s4: CF bit
         SLLI_D(s3, s3, F_OF);
         OR(xFlags, xFlags, s3);
+        MARK;
     }
 }
 
@@ -759,13 +756,10 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 {
     int64_t j64;
 
-    if (rex.w) {
-        ANDI(s4, s2, 0x3f);
-    } else {
-        ANDI(s4, s2, 0x1f);
+    if (!rex.w) {
         ZEROUP(s1);
     }
-    BEQ_NEXT(s4, xZR);
+    BEQ_NEXT(s2, xZR);
     IFX (X_PEND) {
         SDxw(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, rex.w ? d_ror64 : d_ror32);
@@ -775,15 +769,15 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 
     IFXA ((X_CF | X_OF), la64_lbt) {
         if (rex.w)
-            X64_ROTR_D(s1, s4);
+            X64_ROTR_D(s1, s2);
         else
-            X64_ROTR_W(s1, s4);
+            X64_ROTR_W(s1, s2);
     }
 
     if (rex.w) {
-        ROTR_D(s1, s1, s4);
+        ROTR_D(s1, s1, s2);
     } else {
-        ROTR_W(s1, s1, s4);
+        ROTR_W(s1, s1, s2);
     }
 
     IFX (X_PEND) {
@@ -802,14 +796,15 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     }
     IFX (X_OF) {
         // the OF flag is set to the exclusive OR of the two most-significant bits of the result
-        ADDI_D(s3, xZR, 1);
-        BNE_NEXT(s2, s3);
+        ADDI_D(s3, s2, -1);
+        BNEZ_MARK(s3);
         SRLIxw(s3, s1, rex.w ? 63 : 31);
         SRLIxw(s4, s1, rex.w ? 62 : 30);
         XOR(s3, s3, s4);
         ANDI(s3, s3, 1);
         SLLI_D(s3, s3, F_OF);
         OR(xFlags, xFlags, s3);
+        MARK;
     }
 }
 
diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c
index b5b721fe..b597cfa6 100644
--- a/src/dynarec/la64/dynarec_la64_helper.c
+++ b/src/dynarec/la64/dynarec_la64_helper.c
@@ -133,7 +133,7 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
             i64 = F32S;
         else
             i64 = F8S;
-        if (i64 == 0 || ((i64 >= -2048) && (i64 <= 2047) && i12)) {
+        if (i64 == 0 || ((i64 >= -2048) && (i64 <= maxval) && i12)) {
             *fixaddress = i64;
             if ((nextop & 7) == 4) {
                 if (sib_reg != 4) {
@@ -265,7 +265,7 @@ static uintptr_t geted_32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_
             i32 = F32S;
         else
             i32 = F8S;
-        if (i32 == 0 || ((i32 >= -2048) && (i32 <= 2047) && i12)) {
+        if (i32 == 0 || ((i32 >= -2048) && (i32 <= maxval) && i12)) {
             *fixaddress = i32;
             if ((nextop & 7) == 4) {
                 if (sib_reg != 4) {
@@ -413,7 +413,7 @@ uintptr_t geted32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
             i64 = F32S;
         else
             i64 = F8S;
-        if (i64 == 0 || ((i64 >= -2048) && (i64 <= 2047) && i12)) {
+        if (i64 == 0 || ((i64 >= -2048) && (i64 <= maxval) && i12)) {
             *fixaddress = i64;
             if ((nextop & 7) == 4) {
                 if (sib_reg != 4) {
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 4e2d8653..9c1f6aa5 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -279,7 +279,7 @@
         ed = i;                                                                                 \
     } else {                                                                                    \
         SMREAD();                                                                               \
-        addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, D); \
+        addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, D); \
         LD_B(i, wback, fixedaddress);                                                           \
         wb1 = 1;                                                                                \
         ed = i;                                                                                 \