about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorwannacu <76616478+wannacu@users.noreply.github.com>2025-02-13 20:07:36 +0800
committerGitHub <noreply@github.com>2025-02-13 13:07:36 +0100
commit639466d45aa2d322e3bc770b7562f3385814e935 (patch)
tree8c7586304068d1adc6dfe5ccd43c200c351fc670 /src
parent95bdaf6eca65f3b45422c83abcf152c7022e6a26 (diff)
downloadbox64-639466d45aa2d322e3bc770b7562f3385814e935.tar.gz
box64-639466d45aa2d322e3bc770b7562f3385814e935.zip
[ARM64_DYNAREC] Added some BMI.0F38 opcodes (#2347)
* [ARM64_DYNAREC] Fixed BMI.0F38 F5 ocpode

* [ARM64_DYNAREC] Added BMI.0F38 F3 /2,/3 ocpode

* Added BMI.0F38 F7 opcode

* Fixed emitter mistake about CSINVxw
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/arm64_emitter.h2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_0f38.c113
2 files changed, 113 insertions, 2 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index f56a68dc..0ecfa33c 100644
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -586,7 +586,7 @@ int convert_bitmask(uint64_t bitmask);
 #define CSINV_gen(sf, Rm, cond, Rn, Rd)     ((sf)<<31 | 1<<30 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (Rd))
 #define CSINVx(Rd, Rn, Rm, cond)            EMIT(CSINV_gen(1, Rm, cond, Rn, Rd))
 #define CSINVw(Rd, Rn, Rm, cond)            EMIT(CSINV_gen(0, Rm, cond, Rn, Rd))
-#define CSINVxw(Rd, Rn, Rm, cond)           EMIT(CSINV_gen(rex.w?, Rm, cond, Rn, Rd))
+#define CSINVxw(Rd, Rn, Rm, cond)           EMIT(CSINV_gen(rex.w, Rm, cond, Rn, Rd))
 #define CINVx(Rd, Rn, cond)                 CSINVx(Rd, Rn, Rn, invertCond(cond))
 #define CINVw(Rd, Rn, cond)                 CSINVw(Rd, Rn, Rn, invertCond(cond))
 #define CINVxw(Rd, Rn, cond)                CSINVxw(Rd, Rn, Rn, invertCond(cond))
diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c
index bd0a1baf..c5a9baf5 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c
@@ -137,6 +137,82 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
                         IFX(X_PF) BFCw(xFlags, F_PF, 1);
                     }
                     break;
+
+                case 2:
+                    INST_NAME("BLSMSK Vd, Ed");
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETED(0);
+                    GETVD;
+                    IFX(X_CF) {
+                        TSTxw_REG(ed, ed);
+                        CSETMw(x3, cEQ);
+                        BFIw(xFlags, x3, F_CF, 1);
+                    }
+                    SUBxw_U12(x3, ed, 1);
+                    need_tst = 0;
+                    IFX(X_ZF) need_tst = 1;
+                    IFXNATIVE(X_SF, NF_SF) need_tst = 1;
+                    IFXNATIVE(X_OF, NF_VF) need_tst = 1;
+                    EORxw_REG(vd, ed, x3);
+                    if(need_tst)
+                        TSTxw_REG(vd, vd);
+                    IFX(X_ZF) {
+                        IFNATIVE(NF_EQ) {} else {
+                            CSETMw(x3, cEQ);
+                            BFIw(xFlags, x3, F_ZF, 1);
+                        }
+                    }
+                    IFX(X_SF) {
+                        IFNATIVE(NF_SF) {} else {
+                            LSRxw(x3, vd, rex.w?63:31);
+                            BFIw(xFlags, x3, F_SF, 1);
+                        }
+                    }
+                    IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
+                    if (BOX64ENV(dynarec_test)) {
+                        IFX(X_AF) BFCw(xFlags, F_AF, 1);
+                        IFX(X_PF) BFCw(xFlags, F_PF, 1);
+                    }
+                    break;
+
+                case 3:
+                    INST_NAME("BLSI Vd, Ed");
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETED(0);
+                    GETVD;
+                    IFX(X_CF) {
+                        TSTxw_REG(ed, ed);
+                        CSETMw(x3, cEQ);
+                        BFIw(xFlags, x3, F_CF, 1);
+                    }
+                    NEGxw_REG(x3, ed);
+                    need_tst = 0;
+                    IFX(X_ZF) need_tst = 1;
+                    IFXNATIVE(X_SF, NF_SF) need_tst = 1;
+                    IFXNATIVE(X_OF, NF_VF) need_tst = 1;
+                    if(need_tst)
+                        ANDSxw_REG(vd, ed, x3);
+                    else
+                        ANDxw_REG(vd, ed, x3);
+                    IFX(X_ZF) {
+                        IFNATIVE(NF_EQ) {} else {
+                            CSETMw(x3, cEQ);
+                            BFIw(xFlags, x3, F_ZF, 1);
+                        }
+                    }
+                    IFX(X_SF) {
+                        IFNATIVE(NF_SF) {} else {
+                            LSRxw(x3, vd, rex.w?63:31);
+                            BFIw(xFlags, x3, F_SF, 1);
+                        }
+                    }
+                    IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
+                    if (BOX64ENV(dynarec_test)) {
+                        IFX(X_AF) BFCw(xFlags, F_AF, 1);
+                        IFX(X_PF) BFCw(xFlags, F_PF, 1);
+                    }
+                    break;
+
                 default:
                     DEFAULT;
             }
@@ -151,7 +227,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
             GETVD;
             UXTBw(x1, vd);
             CMPSw_U12(x1, rex.w?64:32);
-            CSETxw(x2, cPL);
+            CSETMxw(x2, cPL);
             IFX(F_CF) {
                 BFIw(xFlags, x2, F_CF, 1);
             }
@@ -184,6 +260,41 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
             IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
             break;
 
+        case 0xF7:
+            INST_NAME("BEXTR Gd, Ed, Vd");
+            nextop = F8;
+            SETFLAGS(X_ALL, SF_SET);
+            GETGD;
+            GETED(0);
+            GETVD;
+            MOV64xw(x1, 0);
+            UXTBw(x2, vd);          // start
+            BFXILw(x3, vd, 8, 8);   // length
+            TSTw_REG(x3, x3);
+            B_MARK(cEQ);
+            LSRxw_REG(x1, ed, x2);
+            CMPSw_U12(x3, rex.w?64:32);
+            B_MARK(cGE);
+            MOV32w(x2, rex.w?64:32);
+            SUBw_REG(x2, x2, x3);
+            LSLxw_REG(x1, x1, x2);
+            LSRxw_REG(x1, x1, x2);
+            TSTxw_REG(x1, x1);
+            MARK;
+            MOVxw_REG(gd, x1);
+            IFX(X_ZF) {
+                IFNATIVE(NF_EQ) {} else {
+                    CSETw(x3, cEQ);
+                    BFIw(xFlags, x3, F_ZF, 1);
+                }
+            }
+            IFX(X_AF) BFCw(xFlags, F_AF, 1);
+            IFX(X_PF) BFCw(xFlags, F_PF, 1);
+            IFX(X_CF) BFCw(xFlags, F_CF, 1);
+            IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
+            IFX(X_SF) IFNATIVE(NF_SF) {} else {BFCw(xFlags, F_SF, 1);}
+            break;
+
         default:
             DEFAULT;
     }