about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-07-20 16:04:07 +0800
committerGitHub <noreply@github.com>2024-07-20 10:04:07 +0200
commit052bba4578730f82bbf26486dcacd276f135c44d (patch)
tree0ecc0b4a0cab8752966d9d72634a1d71bc21eb1b
parentd1eb01e535b324e23e85535fce5ee4516161c47e (diff)
downloadbox64-052bba4578730f82bbf26486dcacd276f135c44d.tar.gz
box64-052bba4578730f82bbf26486dcacd276f135c44d.zip
[LA64_DYNAREC] Added more opcodes (#1700)
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c37
-rw-r--r--src/dynarec/la64/dynarec_la64_64.c9
-rw-r--r--src/dynarec/la64/dynarec_la64_660f.c54
-rw-r--r--src/dynarec/la64/dynarec_la64_f0.c21
-rw-r--r--src/dynarec/la64/la64_emitter.h10
5 files changed, 131 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 3124e7ae..0f795e61 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -676,6 +676,43 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
             WBACK;
             break;
+        case 0xAB:
+            INST_NAME("BTS Ed, Gd");
+            SETFLAGS(X_CF, SF_SUBSET);
+            SET_DFNONE();
+            nextop = F8;
+            GETGD;
+            if (MODREG) {
+                ed = TO_LA64((nextop & 7) + (rex.b << 3));
+                wback = 0;
+            } else {
+                SMREAD();
+                addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
+                SRAI_D(x1, gd, 5 + rex.w);
+                ALSL_D(x3, x1, wback, 2 + rex.w);
+                LDxw(x1, x3, fixedaddress);
+                ed = x1;
+                wback = x3;
+            }
+            ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
+            IFX (X_CF) {
+                SRL_D(x4, ed, x2);
+                if (la64_lbt) {
+                    X64_SET_EFLAGS(x4, X_CF);
+                } else {
+                    BSTRINS_D(xFlags, x4, F_CF, F_CF);
+                }
+            }
+            ADDI_D(x4, xZR, 1);
+            SLL_D(x4, x4, x2);
+            OR(ed, ed, x4);
+            if (wback) {
+                SDxw(ed, wback, fixedaddress);
+                SMWRITE();
+            } else if (!rex.w) {
+                ZEROUP(ed);
+            }
+            break;
         case 0xAC:
             nextop = F8;
             INST_NAME("SHRD Ed, Gd, Ib");
diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c
index 95d6566e..ae23ab2e 100644
--- a/src/dynarec/la64/dynarec_la64_64.c
+++ b/src/dynarec/la64/dynarec_la64_64.c
@@ -70,6 +70,15 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             GETEDO(x4, 0);
             emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
             break;
+        case 0x2B:
+            INST_NAME("SUB Gd, Seg:Ed");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            grab_segdata(dyn, addr, ninst, x4, seg);
+            nextop = F8;
+            GETGD;
+            GETEDO(x4, 0);
+            emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
+            break;
         case 0x33:
             INST_NAME("XOR Gd, Seg:Ed");
             SETFLAGS(X_ALL, SF_SET_PENDING);
diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c
index 9404ae20..095512d5 100644
--- a/src/dynarec/la64/dynarec_la64_660f.c
+++ b/src/dynarec/la64/dynarec_la64_660f.c
@@ -1075,6 +1075,36 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             u8 = F8;
             VSHUF4I_D(v0, v1, 0x8 | (u8 & 1) | ((u8 & 2) << 1));
             break;
+        case 0xD2:
+            INST_NAME("PSRLD Gx, Ex");
+            nextop = F8;
+            GETGX(q0, 1);
+            GETEX(q1, 0, 0);
+            v0 = fpu_get_scratch(dyn);
+            v1 = fpu_get_scratch(dyn);
+            VSAT_DU(v0, q1, 31);
+            VREPLVEI_W(v0, v0, 0);
+            VLDI(v1, 0b1000000011111); // broadcast 31 as uint32
+            VSLT_WU(v1, v1, v0);
+            VMINI_WU(v0, v0, 31);
+            VSRL_W(q0, q0, v0);
+            VSRL_W(q0, q0, v1);
+            break;
+        case 0xD3:
+            INST_NAME("PSRLQ Gx,Ex");
+            nextop = F8;
+            GETGX(q0, 1);
+            GETEX(q1, 0, 0);
+            v0 = fpu_get_scratch(dyn);
+            v1 = fpu_get_scratch(dyn);
+            d0 = fpu_get_scratch(dyn);
+            VREPLVEI_D(v0, q1, 0);
+            VLDI(v1, 0b0110000111111); // broadcast 63 as uint64
+            VMIN_DU(d0, v0, v1);
+            VSLT_DU(v1, v1, v0);
+            VSRL_D(q0, q0, d0);
+            VSRL_D(q0, q0, v1);
+            break;
         case 0xD4:
             INST_NAME("PADDQ Gx, Ex");
             nextop = F8;
@@ -1121,6 +1151,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             MOVFR2GR_D(x1, v0);
             BSTRPICK_D(gd, x1, 15, 0);
             break;
+        case 0xD9:
+            INST_NAME("PSUBUSW Gx, Ex");
+            nextop = F8;
+            GETGX(q0, 1);
+            GETEX(q1, 0, 0);
+            VSSUB_HU(q0, q0, q1);
+            break;
         case 0xDB:
             INST_NAME("PAND Gx,Ex");
             nextop = F8;
@@ -1149,6 +1186,23 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETEX(v1, 0, 0);
             VAVGR_BU(v0, v0, v1);
             break;
+        case 0xE1:
+            INST_NAME("PSRAW Gx, Ex");
+            nextop = F8;
+            GETGX(q0, 1);
+            GETEX(q1, 0, 0);
+            v0 = fpu_get_scratch(dyn);
+            VMINI_HU(v0, q1, 15);
+            VREPLVEI_H(v0, v0, 0);
+            VSRA_H(q0, q0, v0);
+            break;
+        case 0xE3:
+            INST_NAME("PAVGW Gx,Ex");
+            nextop = F8;
+            GETGX(v0, 1);
+            GETEX(v1, 0, 0);
+            VAVGR_HU(v0, v0, v1);
+            break;
         case 0xE4:
             INST_NAME("PMULHUW Gx,Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c
index 0f7a48d8..bfc918e8 100644
--- a/src/dynarec/la64/dynarec_la64_f0.c
+++ b/src/dynarec/la64/dynarec_la64_f0.c
@@ -75,6 +75,27 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             SMDMB();
             break;
+        case 0x09:
+            INST_NAME("LOCK OR Ed, Gd");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGD;
+            SMDMB();
+            if (MODREG) {
+                ed = TO_LA64((nextop & 7) + (rex.b << 3));
+                emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                MARKLOCK;
+                LLxw(x1, wback, 0);
+                OR(x4, x1, gd);
+                SCxw(x4, wback, 0);
+                BEQZ_MARKLOCK(x4);
+                IFX (X_ALL | X_PEND)
+                    emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
+            }
+            SMDMB();
+            break;
         case 0x0F:
             nextop = F8;
             switch (nextop) {
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index c243d026..dc06d2a3 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -176,6 +176,8 @@ f24-f31  fs0-fs7   Static registers                Callee
 
 // Made-up formats not found in the spec.
 #define type_1RI13(opc, imm13, rd)       ((opc) << 18 | ((imm13) & 0x1FFFF) << 5 | (rd))
+#define type_2RI1(opc, imm1, rj, rd)     ((opc) << 11 | ((imm1) & 0x1) << 10 | (rj) << 5 | (rd))
+#define type_2RI2(opc, imm2, rj, rd)     ((opc) << 12 | ((imm2) & 0x3) << 10 | (rj) << 5 | (rd))
 #define type_2RI3(opc, imm3, rj, rd)     ((opc) << 13 | ((imm3)  & 0x7 )  << 10 | (rj) << 5 | (rd))
 #define type_2RI4(opc, imm4, rj, rd)     ((opc) << 14 | ((imm4)  & 0xF )  << 10 | (rj) << 5 | (rd))
 #define type_2RI5(opc, imm5, rj, rd)     ((opc) << 15 | ((imm5)  & 0x1F)  << 10 | (rj) << 5 | (rd))
@@ -1380,6 +1382,14 @@ LSX instruction starts with V, LASX instruction starts with XV.
 #define VSLT_HU(vd, vj, vk)         EMIT(type_3R(0b01110000000010001, vk, vj, vd))
 #define VSLT_WU(vd, vj, vk)         EMIT(type_3R(0b01110000000010010, vk, vj, vd))
 #define VSLT_DU(vd, vj, vk)         EMIT(type_3R(0b01110000000010011, vk, vj, vd))
+#define VREPLVE_B(vd, vj, rk)          EMIT(type_3R(0b01110001001000100, rk, vj, vd))
+#define VREPLVE_H(vd, vj, rk)          EMIT(type_3R(0b01110001001000101, rk, vj, vd))
+#define VREPLVE_W(vd, vj, rk)          EMIT(type_3R(0b01110001001000110, rk, vj, vd))
+#define VREPLVE_D(vd, vj, rk)          EMIT(type_3R(0b01110001001000111, rk, vj, vd))
+#define VREPLVEI_B(vd, vk, imm4)       EMIT(type_2RI4(0b011100101111011110, imm4, vk, vd))
+#define VREPLVEI_H(vd, vk, imm3)       EMIT(type_2RI3(0b0111001011110111110, imm3, vk, vd))
+#define VREPLVEI_W(vd, vk, imm2)       EMIT(type_2RI2(0b01110010111101111110, imm2, vk, vd))
+#define VREPLVEI_D(vd, vk, imm1)       EMIT(type_2RI1(0b011100101111011111110, imm1, vk, vd))
 #define VBSLL_V(vd, vj, imm5)       EMIT(type_2RI5(0b01110010100011100, imm5, vj, vd))
 #define VBSRL_V(vd, vj, imm5)       EMIT(type_2RI5(0b01110010100011101, imm5, vj, vd))
 #define VPACKEV_B(vd, vj, vk)       EMIT(type_3R(0b01110001000101100, vk, vj, vd))