about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-03-18 08:55:51 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-03-18 08:55:51 +0000
commit4b74a1be58d940ae58a4d7325bac64994bd0f35c (patch)
treeb671d78e5513246a672157c5f7c475c87ed3ef70 /src
parent2aeb77736f07bdc3bd259093c02aadfd20d69e7f (diff)
downloadbox64-4b74a1be58d940ae58a4d7325bac64994bd0f35c.tar.gz
box64-4b74a1be58d940ae58a4d7325bac64994bd0f35c.zip
[RV64_DYNAREC] Added D3 /4 /5 SHL opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c17
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c48
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
3 files changed, 61 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 8f71c229..ffe95ade 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -670,14 +670,21 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xD3:
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 4:
+                case 6:
+                    INST_NAME("SHL Ed, CL");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    ANDI(x3, xRCX, rex.w?0x3f:0x1f);
+                    GETED(0);
+                    if(!rex.w && MODREG) {ZEROUP(ed);}
+                    CBZ_NEXT(x3);
+                    emit_shl32(dyn, ninst, rex, ed, x3, x5, x4, x6);
+                    WBACK;
+                    break;
                 case 7:
                     INST_NAME("SAR Ed, CL");
                     SETFLAGS(X_ALL, SF_PENDING);
-                    if(rex.w) {
-                        ANDI(x3, xRCX, 0x3f);
-                    } else {
-                        ANDI(x3, xRCX, 0x1f);
-                    }
+                    ANDI(x3, xRCX, rex.w?0x3f:0x1f);
                     GETED(0);
                     if(!rex.w && MODREG) {ZEROUP(ed);}
                     CBZ_NEXT(x3);
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index eccf668b..015ea2f5 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -23,6 +23,54 @@
 #include "dynarec_rv64_functions.h"
 #include "dynarec_rv64_helper.h"
 
+// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
+void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
+{
+    // s2 is not 0 here and is 1..1f/3f
+    CLEAR_FLAGS();
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, op1));
+        SDxw(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, rex.w?d_shl64:d_shl32);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+
+    IFX(X_CF) {
+        SUBI(s5, s2, rex.w?64:32);
+        NEG(s5, s5);
+        SRL(s3, s1, s5);
+        ANDI(s5, s3, 1); // LSB
+        BEQZ(s5, 8);
+        ORI(xFlags, xFlags, 1 << F_CF);
+    }
+
+    SLL(s1, s1, s2);
+
+    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 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)
 {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index ba7f675f..eedded89 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -583,7 +583,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
 //void emit_neg32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
 //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_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
 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);