about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-04-14 14:44:59 +0800
committerGitHub <noreply@github.com>2023-04-14 08:44:59 +0200
commit9413d5deb4ef1223dedc9b650885abb47e7077b1 (patch)
tree7a9aaaafd52a2b0dc8736c79ffc20ec96f1c4f40 /src
parent8a903f1e2cfe16634c60ade801410303d2d08723 (diff)
downloadbox64-9413d5deb4ef1223dedc9b650885abb47e7077b1.tar.gz
box64-9413d5deb4ef1223dedc9b650885abb47e7077b1.zip
[RV64_DYNAREC] Added more opcodes for SV (#699)
* [RV64_DYNAREC] Added D1 /0 ROL opcode

* [RV64_DYNAREC] Added D1 /1 ROR opcode

* [RV64_DYNAREC] Added {D0,D2} /1 ROR opcode

* [RV64_DYNAREC] Added C1 /1 ROR opcode

* [RV64_DYNAREC] Fixed ROR/ROL flags
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c43
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c50
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
3 files changed, 90 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 3259f231..2b25db74 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -141,6 +141,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     if(u8) { WBACK; }
                     if(!wback && !rex.w) ZEROUP(ed);
                     break;
+                case 1:
+                    INST_NAME("ROR Ed, Ib");
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
+                    GETED(1);
+                    u8 = (F8)&(rex.w?0x3f:0x1f);
+                    emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
+                    if(u8) { WBACK; }
+                    break;
                 case 4:
                 case 6:
                     INST_NAME("SHL Ed, Ib");
@@ -331,6 +339,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xD2:  // TODO: Jump if CL is 0
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 1:
+                    if(opcode==0xD0) {
+                        INST_NAME("ROR Eb, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("ROR Eb, CL");
+                        ANDI(x2, xRCX, 7);
+                    }
+                    SETFLAGS(X_OF|X_CF, SF_PENDING);
+                    GETEB(x1, 0);
+                    UFLAG_OP12(ed, x2);
+                    SRL(x3, ed, x2);
+                    SLLI(x4, ed, 8);
+                    SRL(x4, x4, x2);
+                    OR(ed, x3, x4);
+                    EBBACK(x5, 1);
+                    UFLAG_RES(ed);
+                    UFLAG_DF(x3, d_ror8);
+                    break;
                 case 5:
                     if(opcode==0xD0) {
                         INST_NAME("SHR Eb, 1");
@@ -370,6 +397,22 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xD1:
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("ROL Ed, 1");
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
+                    GETED(0);
+                    emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4);
+                    WBACK;
+                    if(!wback && !rex.w) ZEROUP(ed);
+                    break;
+                case 1:
+                    INST_NAME("ROR Ed, 1");
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
+                    GETED(0);
+                    emit_rol32c(dyn, ninst, rex, ed, rex.w?63:31, x3, x4);
+                    WBACK;
+                    if(!wback && !rex.w) ZEROUP(ed);
+                    break;
                 case 4:
                 case 6:
                     INST_NAME("SHL Ed, 1");
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index 04d73f10..be84894c 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -312,8 +312,8 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
 void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
 {
     int64_t j64;
-    IFX(X_CF) {
-        ANDI(xFlags, xFlags, ~(1UL<<F_CF));
+    IFX(X_CF | X_OF) {
+        ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2));
     }
 
     IFX(X_PEND) {
@@ -355,8 +355,8 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 // emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
 {
-    IFX(X_CF) {
-        ANDI(xFlags, xFlags, ~(1UL<<F_CF));
+    IFX(X_CF | X_OF) {
+        ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2));
     }
 
     IFX(X_PEND) {
@@ -394,6 +394,48 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
     }
 }
 
+// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
+{
+    IFX(X_CF | X_OF) {
+        ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2));
+    }
+
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        SDxw(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, rex.w?d_ror64:d_ror32);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+    if(!c) {
+        IFX(X_PEND) {
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    SRLIxw(s3, s1, c);
+    SLLIxw(s1, s1, (rex.w?64:32)-c);
+    OR(s1, s3, s1);
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_CF) {
+        SRLI(s3, s1, rex.w?63:31);
+        AND(xFlags, xFlags, s3);
+    }
+    IFX(X_OF) {
+        if(c==1) {
+            SRLI(s3, s1, rex.w?62:30);
+            SRLI(s4, s3, 1);
+            XOR(s3, s3, s4);
+            ANDI(s3, s3, 1);
+            SLLI(s3, s3, F_OF2);
+            OR(xFlags, xFlags, s3);
+        }
+    }
+}
+
 // emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
 {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index d80d52b3..18e425e3 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -968,7 +968,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
 void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
-//void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
+void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
 void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5);