about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-11-13 18:46:47 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-11-13 18:46:47 +0100
commit1dbb676f38417024ca6764d5888a40e58b82ae70 (patch)
tree7fc809fbab04d1be1d06d0d10a8a23f511dd20cb /src
parent331866bd1d72588fb6121989fc7c6c07271e0d8a (diff)
downloadbox64-1dbb676f38417024ca6764d5888a40e58b82ae70.tar.gz
box64-1dbb676f38417024ca6764d5888a40e58b82ae70.zip
[ARM64_DYNAREC] Reworked 8/16/32/64bits XOR opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c6
-rw-r--r--src/dynarec/arm64/dynarec_arm64_6664.c3
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66f0.c26
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c3
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_logic.c107
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
6 files changed, 63 insertions, 84 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index 16701d0f..eab26e25 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -281,8 +281,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SETFLAGS(X_ALL, SF_SET_PENDING);

             i32 = F16;

             UXTHw(x1, xRAX);

-            MOV32w(x2, i32);

-            emit_xor16(dyn, ninst, x1, x2, x3, x4);

+            emit_xor16c(dyn, ninst, x1, i32, x3, x4);

             BFIz(xRAX, x1, 0, 16);

             break;

 

@@ -537,8 +536,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     SETFLAGS(X_ALL, SF_SET_PENDING);

                     GETEW(x1, (opcode==0x81)?2:1);

                     if(opcode==0x81) i16 = F16S; else i16 = F8S;

-                    MOVZw(x5, i16);

-                    emit_xor16(dyn, ninst, x1, x5, x2, x4);

+                    emit_xor16c(dyn, ninst, x1, i16, x2, x4);

                     EWBACK;

                     break;

                 case 7: //CMP

diff --git a/src/dynarec/arm64/dynarec_arm64_6664.c b/src/dynarec/arm64/dynarec_arm64_6664.c
index ba86644b..5e9a9a5a 100644
--- a/src/dynarec/arm64/dynarec_arm64_6664.c
+++ b/src/dynarec/arm64/dynarec_arm64_6664.c
@@ -201,8 +201,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     grab_segdata(dyn, addr, ninst, x1, seg);
                     GETEWO(x1, (opcode==0x81)?2:1);
                     if(opcode==0x81) i16 = F16S; else i16 = F8S;
-                    MOVZw(x5, i16);
-                    emit_xor16(dyn, ninst, x1, x5, x2, x4);
+                    emit_xor16c(dyn, ninst, x1, i16, x2, x4);
                     EWBACK;
                     break;
                 case 7: //CMP
diff --git a/src/dynarec/arm64/dynarec_arm64_66f0.c b/src/dynarec/arm64/dynarec_arm64_66f0.c
index c83bf4db..58f3af4d 100644
--- a/src/dynarec/arm64/dynarec_arm64_66f0.c
+++ b/src/dynarec/arm64/dynarec_arm64_66f0.c
@@ -334,20 +334,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     } else {
                         addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
                         if(opcode==0x81) i16 = F16S; else i16 = F8S;
-                        i64 = convert_bitmask_w(i16);
                         if(!i64) {MOV32w(x5, i16);}
                         if(arm64_atomics) {
                             UFLAG_IF {
                                 LDSETALH(x5, x1, wback);
-                                if(i64) {
-                                    emit_or16c(dyn, ninst, x1, i16, x3, x4);
-                                } else {
-                                    emit_or16(dyn, ninst, x1, x5, x3, x4);
-                                }
+                                emit_or16c(dyn, ninst, x1, i16, x3, x4);
                             } else {
                                 STSETLH(x5, wback);
                             }
                         } else {
+                            i64 = convert_bitmask_w(i16);
+                            if(!i64) {MOV32w(x5, i32);}
                             MARKLOCK;
                             LDAXRH(x1, wback);
                             if(i64) {
@@ -506,27 +503,30 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
                     SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(MODREG) {
-                        if(opcode==0x81) i32 = F16S; else i32 = F8S;
+                        if(opcode==0x81) i16 = F16S; else i16 = F8S;
                         ed = xRAX+(nextop&7)+(rex.b<<3);
-                        MOV32w(x5, i32);
                         UXTHw(x6, ed);
-                        emit_xor16(dyn, ninst, x6, x5, x3, x4);
+                        emit_xor16c(dyn, ninst, x6, i16, x3, x4);
                         BFIx(ed, x6, 0, 16);
                     } else {
                         addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
-                        if(opcode==0x81) i32 = F16S; else i32 = F8S;
-                        MOV32w(x5, i32);
+                        if(opcode==0x81) i16 = F16S; else i16 = F8S;
+                        i64 = convert_bitmask_w(i16);
                         if(arm64_atomics) {
                             UFLAG_IF {
                                 LDEORALH(x5, x1, wback);
-                                emit_xor16(dyn, ninst, x1, x5, x3, x4);
+                                emit_xor16c(dyn, ninst, x1, i16, x3, x4);
                             } else {
                                 STEORLH(x5, wback);
                             }
                         } else {
+                            if(!i64) {MOV32w(x5, i16);}
                             MARKLOCK;
                             LDAXRH(x1, wback);
-                            emit_xor16(dyn, ninst, x1, x5, x3, x4);
+                            if(i64)
+                                emit_xor16c(dyn, ninst, x1, i16, x3, x4);
+                            else
+                                emit_xor16(dyn, ninst, x1, x5, x3, x4);
                             STLXRH(x3, x1, wback);
                             CBNZx_MARKLOCK(x3);
                             SMDMB();
diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c
index d9f6f70b..58f40363 100644
--- a/src/dynarec/arm64/dynarec_arm64_67.c
+++ b/src/dynarec/arm64/dynarec_arm64_67.c
@@ -863,8 +863,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 SETFLAGS(X_ALL, SF_SET_PENDING);

                                 GETEW32(x1, (opcode==0x81)?2:1);

                                 if(opcode==0x81) i16 = F16S; else i16 = F8S;

-                                MOVZw(x5, i16);

-                                emit_xor16(dyn, ninst, x1, x5, x2, x4);

+                                emit_xor16c(dyn, ninst, x1, i16, x2, x4);

                                 EWBACK;

                                 break;

                             case 7: //CMP

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_logic.c b/src/dynarec/arm64/dynarec_arm64_emit_logic.c
index 45d5645e..50791333 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_logic.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_logic.c
@@ -176,18 +176,18 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
 // emit XOR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
 {
+    int mask = convert_bitmask_xw(c);
+    if(!mask) {
+        MOV64xw(s3, c);
+        emit_xor32(dyn, ninst, rex, s1, s3, s3, s4);
+        return;
+    }
     IFX(X_PEND) {
         SET_DF(s4, rex.w?d_xor64:d_xor32);
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    int mask = convert_bitmask_xw(c);
-    if(mask) {
-        EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
-    } else {
-        MOV64xw(s3, c);
-        EORxw_REG(s1, s1, s3);
-    }
+    EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
     IFX(X_PEND) {
         STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
@@ -382,9 +382,9 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 {
     MAYUSE(s2);
     IFX(X_PEND) {
-        SET_DF(s3, d_xor8);
+        SET_DF(s4, d_xor8);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE(s4);
     }
     EORx_REG(s1, s1, s2);
     IFX(X_PEND) {
@@ -403,18 +403,18 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 // emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int8_t c, int s3, int s4)
 {
+    int mask = convert_bitmask_w(c);
+    if(!mask) {
+        MOV32w(s3, c&0xff);
+        emit_xor8(dyn, ninst, s1, s3, s3, s4);
+        return;
+    }
     IFX(X_PEND) {
         SET_DF(s4, d_xor8);
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    int mask = convert_bitmask_w(c);
-    if(mask) {
-        EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
-    } else {
-        MOV32w(s3, c&0xff);
-        EORw_REG(s1, s1, s3);
-    }
+    EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
     IFX(X_PEND) {
         STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
@@ -569,9 +569,9 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 {
     MAYUSE(s2);
     IFX(X_PEND) {
-        SET_DF(s3, d_xor16);
+        SET_DF(s4, d_xor16);
     } else IFX(X_ALL) {
-        SET_DFNONE(s3);
+        SET_DFNONE(s4);
     }
     EORw_REG(s1, s1, s2);
     IFX(X_PEND) {
@@ -588,50 +588,33 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 }
 
 // emit XOR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
-//void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
-//{
-//    IFX(X_PEND) {
-//        MOVW(s3, c);
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
-//        STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
-//        SET_DF(s4, d_xor16);
-//    } else IFX(X_ALL) {
-//        SET_DFNONE(s4);
-//    }
-//    if(c>=0 && c<256) {
-//        IFX(X_ALL) {
-//            XORS_IMM8(s1, s1, c);
-//        } else {
-//            XOR_IMM8(s1, s1, c);
-//        }
-//    } else {
-//        IFX(X_PEND) {} else {MOVW(s3, c);}
-//        IFX(X_ALL) {
-//            XORS_REG_LSL_IMM5(s1, s1, s3, 0);
-//        } else {
-//            XOR_REG_LSL_IMM5(s1, s1, s3, 0);
-//        }
-//    }
-//    IFX(X_PEND) {
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
-//    }
-//    IFX(X_CF | X_AF | X_ZF) {
-//        BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
-//    }
-//    IFX(X_OF) {
-//        BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
-//    }
-//    IFX(X_ZF) {
-//        ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
-//    }
-//    IFX(X_SF) {
-//        MOV_REG_LSR_IMM5(s3, s1, 15);
-//        BFI(xFlags, s3, F_SF, 1);
-//    }
-//    IFX(X_PF) {
-//        emit_pf(dyn, ninst, s1, s4);
-//    }
-//}
+void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
+{
+    int mask = convert_bitmask_w(c);
+    if(!mask) {
+        MOV32w(s3, c);
+        emit_xor16(dyn, ninst, s1, s3, s3, s4);
+        return;
+    }
+    IFX(X_PEND) {
+        SET_DF(s4, d_xor16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_CF | X_AF | X_OF) {
+        MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
+        BICw(xFlags, xFlags, s3);
+    }
+    COMP_ZFSF(s1, 16)
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s4);
+    }
+}
+
 
 // emit AND16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
 void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 67b73671..79b2760d 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1462,7 +1462,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4);
 void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
-//void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
+void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4);
 void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4);
 void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);