about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-03-14 16:16:59 +0800
committerGitHub <noreply@github.com>2023-03-14 09:16:59 +0100
commitc48a2252d0e7d364bf3e45c2afb37810a70bc64d (patch)
tree4966e354f7b3ad70fa8e0d885d2d202b0bae9293 /src
parent978cd2ec51fe74e0e64a0caa565d36ef6b85bb08 (diff)
downloadbox64-c48a2252d0e7d364bf3e45c2afb37810a70bc64d.tar.gz
box64-c48a2252d0e7d364bf3e45c2afb37810a70bc64d.zip
[RV64_DYNAREC] Added C1 /7 SAR opcode (#559)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c78
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_emitter.h15
4 files changed, 107 insertions, 4 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 1cf10f31..a574ce4c 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -162,6 +162,22 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             break;
 
+        case 0xC1:
+            nextop = F8;
+            switch((nextop>>3)&7) {
+                case 7:
+                    INST_NAME("SAR Ed, Ib");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    GETED(1);
+                    u8 = (F8)&(rex.w?0x3f:0x1f);
+                    emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);
+                    if(u8) { WBACK; }
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
+
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
new file mode 100644
index 00000000..c4eb103a
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "dynarec_native.h"
+#include "../tools/bridge_private.h"
+
+#include "rv64_printer.h"
+#include "dynarec_rv64_private.h"
+#include "dynarec_rv64_functions.h"
+#include "dynarec_rv64_helper.h"
+
+// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_sar32c(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);
+        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);
+    }
+    if(!c) {
+        IFX(X_PEND) {
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    IFX(X_CF) {
+        if (c > 1) {
+            SRAI(s3, s1, c-1);
+            ANDI(s3, s3, 1); // LSB
+            BEQZ(s3, 4);
+        } else {
+            // no need to shift
+            ANDI(s3, s1, 1);
+            BEQZ(s3, 4);
+        }
+        ORI(xFlags, xFlags, F_CF);
+    }
+
+    SRAIxw(s1, s1, c);
+
+    // SRAIW sign-extends, so test sign bit before clearing upper bits
+    IFX(X_SF) {
+        BGE(s1, xZR, 4);
+        ORI(xFlags, xFlags, F_SF);
+    }
+    if (!rex.w) {
+        ZEROUP(s1);
+    }
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        BNEZ(s1, 4);
+        ORI(xFlags, xFlags, F_ZF);
+    }
+    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 5d9f2140..84eaa0df 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -392,7 +392,7 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 //void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 //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_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_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);
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index 10cf325b..b95f7278 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -168,7 +168,7 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define XORxw(rd, rs1, rs2)         do{ XOR(rd, rs1, rs2); if (!rex.w) ZEROUP(rd); }while(0)
 // rd = rs1>>rs2 logical
 #define SRL(rd, rs1, rs2)           EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0110011))
-// rd = rs1>>rs2 aritmetic
+// rd = rs1>>rs2 arithmetic
 #define SRA(rd, rs1, rs2)           EMIT(R_type(0b0100000, rs2, rs1, 0b101, rd, 0b0110011))
 // rd = rs1 | rs2
 #define OR(rd, rs1, rs2)            EMIT(R_type(0b0000000, rs2, rs1, 0b110, rd, 0b0110011))
@@ -235,7 +235,7 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define SLLI(rd, rs1, imm6)         EMIT(I_type(imm6, rs1, 0b001, rd, 0b0010011))
 // Shift Right Logical Immediate
 #define SRLI(rd, rs1, imm6)         EMIT(I_type(imm6, rs1, 0b101, rd, 0b0010011))
-// Shift Right Aritmetic Immediate
+// Shift Right Arithmetic Immediate
 #define SRAI(rd, rs1, imm6)         EMIT(I_type((imm6)|(0b010000<<6), rs1, 0b101, rd, 0b0010011))
 
 // rd = rs1 + imm12
@@ -247,7 +247,16 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define SLLW(rd, rs1, rs2)           EMIT(R_type(0b0000000, rs2, rs1, 0b001, rd, 0b0111011))
 // rd = rs1>>rs2 logical
 #define SRLW(rd, rs1, rs2)           EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0111011))
-// rd = rs1>>rs2 aritmetic
+// rd = rs1>>rs2 arithmetic
 #define SRAW(rd, rs1, rs2)           EMIT(R_type(0b0100000, rs2, rs1, 0b101, rd, 0b0111011))
 
+// Shift Left Immediate, 32-bit, sign-extended
+#define SLLIW(rd, rs1, imm5)        EMIT(I_type(imm5, rs1, 0b001, rd, 0b0011011))
+// Shift Right Logical Immediate, 32-bit, sign-extended
+#define SRLIW(rd, rs1, imm5)        EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011))
+// Shift Right Arithmetic Immediate, 32-bit, sign-extended
+#define SRAIW(rd, rs1, imm5)        EMIT(I_type((imm5)|(0b0100000<<5), rs1, 0b101, rd, 0b0011011))
+// Shift Right Arithmetic Immediate
+#define SRAIxw(rd, rs1, imm)        if (rex.w) { SRAI(rd, rs1, imm); } else { SRAIW(rd, rs1, imm); }
+
 #endif //__RV64_EMITTER_H__