about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-17 14:55:14 +0800
committerGitHub <noreply@github.com>2023-03-17 07:55:14 +0100
commit9e05a02bbf182f7f9554d00e2aa6c0cc6810f0d0 (patch)
treee4847036c4c1f039aa1a84d5dd99c371b535818f
parentb63dcabca4195fece96f469383c6c3baefae2b9b (diff)
downloadbox64-9e05a02bbf182f7f9554d00e2aa6c0cc6810f0d0.tar.gz
box64-9e05a02bbf182f7f9554d00e2aa6c0cc6810f0d0.zip
[RV64_DYNAREC] Added C1 /(4/6) SHL opcode (#577)
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c9
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c73
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_emitter.h2
4 files changed, 80 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 90025fb4..a7d776aa 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -355,6 +355,15 @@ 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 4:
+                case 6:
+                    INST_NAME("SHL Ed, Ib");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    GETED(1);
+                    u8 = (F8)&(rex.w?0x3f:0x1f);
+                    emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5);
+                    if(u8) WBACK;
+                    break;
                 case 5:
                     INST_NAME("SHR Ed, Ib");
                     SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index db038011..eccf668b 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -23,15 +23,76 @@
 #include "dynarec_rv64_functions.h"
 #include "dynarec_rv64_helper.h"
 
+// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch
+void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5)
+{
+    CLEAR_FLAGS();
+    IFX(X_PEND) {
+        if (c) {
+            MOV64x(s3, c);
+            SDxw(s3, xEmu, offsetof(x64emu_t, op2));
+        } else SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
+        SDxw(s1, xEmu, offsetof(x64emu_t, op1));
+        SET_DF(s4, rex.w?d_shl64:d_shl32);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+
+    if(!c) {
+        IFX(X_PEND) {
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    IFX(X_CF) {
+        if (c > 0) {
+            SRLI(s3, s1, (rex.w?64:32)-c);
+            ANDI(s5, s3, 1); // LSB
+            BEQZ(s5, 8);
+            ORI(xFlags, xFlags, 1 << F_CF);
+        } else {
+            IFX(X_OF) MOV64x(s5, 0);
+        }
+    }
+
+    SLLIxw(s1, s1, c);
+
+    IFX(X_SF) {
+        BGE(s1, xZR, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    if (!rex.w) {
+        ZEROUP(s1);
+    }
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_OF) {
+        SRLIxw(s3, s1, rex.w?63:31);
+        XOR(s3, s3, s5);
+        BEQZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_OF2);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
 {
     CLEAR_FLAGS();
 
     IFX(X_PEND) {
-        MOV64x(s3, c);
+        if (c) {
+            MOV64x(s3, c);
+            SDxw(s3, xEmu, offsetof(x64emu_t, op2));
+        } else SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
-        SDxw(s3, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, rex.w?d_shr64:d_shr32);
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
@@ -92,9 +153,11 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
     CLEAR_FLAGS();
 
     IFX(X_PEND) {
-        MOV64x(s3, c);
+        if (c) {
+            MOV64x(s3, c);
+            SDxw(s3, xEmu, offsetof(x64emu_t, op2));
+        } else SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
-        SDxw(s3, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s4, rex.w?d_sar64:d_sar32);
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
@@ -138,4 +201,4 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
     IFX(X_PF) {
         emit_pf(dyn, ninst, s1, s3, s4);
     }
-}
\ No newline at end of file
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 741577d0..c917fda0 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -584,7 +584,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
 //void emit_neg16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 //void emit_neg8(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 //void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
-//void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
+void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5);
 //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);
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index e920a9f9..4601bee6 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -279,6 +279,8 @@ f28–31  ft8–11  FP temporaries                  Caller
 
 // Shift Left Immediate, 32-bit, sign-extended
 #define SLLIW(rd, rs1, imm5)        EMIT(I_type(imm5, rs1, 0b001, rd, 0b0011011))
+// Shift Left Immediate
+#define SLLIxw(rd, rs1, imm)        if (rex.w) { SLLI(rd, rs1, imm); } else { SLLIW(rd, rs1, imm); }
 // Shift Right Logical Immediate, 32-bit, sign-extended
 #define SRLIW(rd, rs1, imm5)        EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011))
 // Shift Right Logical Immediate