about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-22 16:44:11 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-22 16:44:11 +0100
commit0878acf04c60772493599fa59a3eeada7fcf37c1 (patch)
treeed9046dc99c05ef2b4d3298f4c788e51d28d5c3c
parent735d9c107d5054019ef89367256a6df1a01edda7 (diff)
downloadbox64-0878acf04c60772493599fa59a3eeada7fcf37c1.tar.gz
box64-0878acf04c60772493599fa59a3eeada7fcf37c1.zip
[DYNAREC] Added (F2/F3) A5 opcode
-rwxr-xr-xsrc/dynarec/arm64_emitter.h8
-rwxr-xr-xsrc/dynarec/arm64_printer.c7
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c25
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h8
4 files changed, 44 insertions, 4 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 4d39a2d3..ecf35d50 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -344,6 +344,14 @@
 #define CSELw(Rd, Rn, Rm, cond)             EMIT(CSEL_gen(0, Rm, cond, Rn, Rd))
 #define CSELxw(Rd, Rn, Rm, cond)            EMIT(CSEL_gen(rex.w, Rm, cond, Rn, Rd))
 
+#define CSNEG_gen(sf, Rm, cond, Rn, Rd)     ((sf)<<31 | 1<<30 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | 1<<10 | (Rn)<<5 | (Rd))
+#define CSNEGx(Rd, Rn, Rm, cond)            EMIT(CSNEG_gen(1, Rm, cond, Rn, Rd))
+#define CSNEGw(Rd, Rn, Rm, cond)            EMIT(CSNEG_gen(0, Rm, cond, Rn, Rd))
+#define CSNEGxw(Rd, Rn, Rm, cond)           EMIT(CSNEG_gen(rex.w, Rm, cond, Rn, Rd))
+#define CNEGx(Rd, Rn, cond)                 CSNEGx(Rn, Rn, Rn, invCond(cond))
+#define CNEGw(Rd, Rn, cond)                 CSNEGw(Rn, Rn, Rn, invCond(cond))
+#define CNEGxw(Rd, Rn, cond)                CSNEGxw(Rn, Rn, Rn, invCond(cond))
+
 // AND / ORR
 #define LOGIC_gen(sf, opc, N, immr, imms, Rn, Rd)  ((sf)<<31 | (opc)<<29 | 0b100100<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn)<<5 | Rd)
 // logic to get the mask is ... convoluted... list of possible value there: https://gist.github.com/dinfuehr/51a01ac58c0b23e4de9aac313ed6a06a
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index 4a4e8247..c5c09e62 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -680,6 +680,13 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

+    if(isMask(opcode, "f1011010100mmmmmcccc01nnnnnddddd", &a)) {

+        if((cond&0b1110)!=0b1110 && Rn==Rm)

+            snprintf(buff, sizeof(buff), "CNEG %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], conds[cond^1]);    

+        else

+            snprintf(buff, sizeof(buff), "CSNEG %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]);

+        return buff;

+    }

     // MISC Bits

     if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {

         snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);

diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 4c8e3e6d..714bb92d 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -970,6 +970,31 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SET_DFNONE(x1);
             break;
 
+        case 0xA5:
+            if(rep) {
+                INST_NAME("REP MOVSD");
+                TSTw_REG(xRCX, xRCX);
+                B_NEXT(cEQ);    // end of loop
+                GETDIR(x3, rex.w?8:4);
+                MARK;
+                LDRxw_U12(x1, xRSI, 0);
+                STRxw_U12(x1, xRDI, 0);
+                ADDx_REG(xRSI, xRSI, x3);
+                ADDx_REG(xRDI, xRDI, x3);
+                SUBSx_U12(xRCX, xRCX, 1);
+                B_MARK(cNE);
+                // done
+            } else {
+                INST_NAME("MOVSD");
+                GETDIR(x3, rex.w?8:4);
+                LDRxw_U12(x1, xRSI, 0);
+                STRxw_U12(x1, xRDI, 0);
+                ADDx_REG(xRSI, xRSI, x3);
+                ADDx_REG(xRDI, xRDI, x3);
+                SUBSx_U12(xRCX, xRCX, 1);
+            }
+            break;
+
         case 0xA8:
             INST_NAME("TEST AL, Ib");
             SETFLAGS(X_ALL, SF_SET);
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 6fe1bd24..7c1d4ca7 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -225,10 +225,10 @@
 
 // Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
 // F_DF is 1<<10, so 1 ROR 11*2 (so F_OF)
-#define GETDIR(r, A)    \
-    TSTS_IMM8_ROR(xFlags, 1, 0x0b);         \
-    MOVW(r, A);                             \
-    RSB_COND_IMM8(cNE, r, r, 0)
+#define GETDIR(r, A)                \
+    MOV32w(r, A); /* mask=1<<10 */  \
+    TSTw_mask(xFlags, 0b010110, 0); \
+    CNEGx(r, r, cNE)
 
 // CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1)
 // R0 will not be pushed/popd if ret is -2