about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-04-11 23:20:55 +0800
committerGitHub <noreply@github.com>2023-04-11 17:20:55 +0200
commit4330b61217e80d127644e849c52124bde5c6e711 (patch)
treeb716eb16805356473bed979b0596630809758364 /src
parent97410042bd24205ef8b4201746df611737e248b4 (diff)
downloadbox64-4330b61217e80d127644e849c52124bde5c6e711.tar.gz
box64-4330b61217e80d127644e849c52124bde5c6e711.zip
[RV64_DYNAREC] Added more opcodes for SV (#687)
* [RV64_DYNAREC] Added F9 STC opcode

* [RV64_DYNAREC] Fixed F0 09 LOCK OR opcode

* [RV64_DYNAREC] Added C1 /0 ROL opcode

* [RV64_DYNAREC] Fixed F0 09 LOCK OR opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c15
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c45
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c8
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
4 files changed, 65 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 97defd9a..3adc4646 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -1189,6 +1189,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xC1:
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("ROL Ed, Ib");
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
+                    GETED(1);
+                    u8 = (F8)&(rex.w?0x3f:0x1f);
+                    emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
+                    if(u8) { WBACK; }
+                    break;
                 case 4:
                 case 6:
                     INST_NAME("SHL Ed, Ib");
@@ -1880,6 +1888,13 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             };
             break;
 
+        case 0xF9:
+            INST_NAME("STC");
+            SETFLAGS(X_CF, SF_SUBSET);
+            SET_DFNONE();
+            ORI(xFlags, xFlags, 1 << F_CF);
+            break;
+
         case 0xFF:
             nextop = F8;
             switch((nextop>>3)&7) {
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index 6af7aad7..ae7e6ebe 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -307,6 +307,51 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
     }
 }
 
+// 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_PEND) {
+        MOV32w(s3, c);
+        SDxw(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, rex.w?d_rol64:d_rol32);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+    if(!c) {
+        IFX(X_PEND) {
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    SLLI(s3, s1, c);
+    if (!rex.w) {
+        AND(s3, xMASK, s3);
+    }
+    SRLI(s1, s1, (rex.w?64:32)-c);
+    OR(s1, s3, s1);
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_CF) {
+        // F_CF=0
+        ANDI(s4, s1, 1);
+        OR(xFlags, xFlags, s4);
+    }
+    IFX(X_OF) {
+        if(c==1) {
+            SRLIxw(s3, s1, rex.w?63:31);
+            XOR(s3, s3, s1);
+            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_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
index ef46e9eb..e78756e5 100644
--- a/src/dynarec/rv64/dynarec_rv64_f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -70,15 +70,15 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
                 MARKLOCK;
                 LRxw(x1, wback, 1, 1);
-                OR(x1, x1, gd);
-                SCxw(x3, x1, wback, 1, 1);
+                OR(x4, x1, gd);
+                SCxw(x3, x4, wback, 1, 1);
                 BNEZ_MARKLOCK(x3);
-                IFX(X_ALL|X_PEND) {
+                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/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 40985d8c..a1bfbc8a 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -954,7 +954,7 @@ void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
 void emit_shr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, 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_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_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);