about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-03-21 02:24:53 +0800
committerGitHub <noreply@github.com>2023-03-20 19:24:53 +0100
commit70f91204b1345e08a7cf39e0622b4b94f158de66 (patch)
tree306cb716f5f228d13cf56145feeb04923e79bcd9 /src
parentf4739ae147c1d8c34c3a9f21174e6ff0769197d6 (diff)
downloadbox64-70f91204b1345e08a7cf39e0622b4b94f158de66.tar.gz
box64-70f91204b1345e08a7cf39e0622b4b94f158de66.zip
[RV64_DYNAREC] Added F0 0F C1 LOCK XADD opcode (#604)
* [RV64_DYNAREC] Added F0 0F C1 LOCK XADD opcode

* [RV64_DYNAREC] Added lr/sc support for printer
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c3
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c102
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h6
-rw-r--r--src/dynarec/rv64/rv64_emitter.h17
-rw-r--r--src/dynarec/rv64/rv64_printer.c30
5 files changed, 155 insertions, 3 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 9250455d..3a4d087c 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -1107,6 +1107,9 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             *need_epilog = 0;
             *ok = 0;
             break;
+        case 0xF0:
+            addr = dynarec64_F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
         case 0xF6:
             nextop = F8;
             switch((nextop>>3)&7) {
diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
new file mode 100644
index 00000000..b867e34d
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -0,0 +1,102 @@
+#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 "rv64_printer.h"
+#include "dynarec_rv64_private.h"
+#include "dynarec_rv64_helper.h"
+#include "dynarec_rv64_functions.h"
+
+
+uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
+{
+    (void)ip; (void)rep; (void)need_epilog;
+
+    uint8_t opcode = F8;
+    uint8_t nextop;
+    uint8_t gd, ed, u8;
+    uint8_t wback, wb1, wb2, eb1, eb2, gb1, gb2;
+    int32_t i32;
+    int64_t i64, j64;
+    int64_t fixedaddress;
+    int unscaled;
+    MAYUSE(eb1);
+    MAYUSE(eb2);
+    MAYUSE(gb1);
+    MAYUSE(gb2);
+    MAYUSE(wb1);
+    MAYUSE(wb2);
+    MAYUSE(j64);
+
+    while((opcode==0xF2) || (opcode==0xF3)) {
+        rep = opcode-0xF1;
+        opcode = F8;
+    }
+    // REX prefix before the F0 are ignored
+    rex.rex = 0;
+    while(opcode>=0x40 && opcode<=0x4f) {
+        rex.rex = opcode;
+        opcode = F8;
+    }
+
+    switch(opcode) {
+        case 0x0F:
+            nextop = F8;
+            switch(nextop) {
+                case 0xC1:
+                    switch(rep) {
+                        case 0:
+                            INST_NAME("LOCK XADD Gd, Ed");
+                            SETFLAGS(X_ALL, SF_SET_PENDING);
+                            nextop = F8;
+                            GETGD;
+                            SMDMB();
+                            if(MODREG) {
+                                ed = xRAX+(nextop&7)+(rex.b<<3);
+                                MOV64xw(x1, ed);
+                                MOV64xw(ed, gd);
+                                MOV64xw(gd, x1);
+                                emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
+                            } else {
+                                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                                MARKLOCK;
+                                LRxw(x1, wback, 1, 1);
+                                ADDxw(x4, x1, gd);
+                                SCxw(x3, x4, wback, 1, 1);
+                                BNEZ_MARKLOCK(x3);
+                                IFX(X_ALL|X_PEND) {
+                                    MV(x2, x1);
+                                    emit_add32(dyn, ninst, rex, x2, gd, x3, x4, x5);
+                                }
+                                MV(gd, x1);
+                            }
+                            SMDMB();
+                            break;
+                        default:
+                            DEFAULT;
+                    }
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
+        default:
+            DEFAULT;
+    }
+    return addr;
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 20916c88..e5a21853 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -275,6 +275,10 @@
 #define BEQ_MARK3(reg1, reg2) Bxx_gen(EQ, MARK3, reg1, reg2)
 // Branch to MARK3 if reg1!=reg2 (use j64)
 #define BNE_MARK3(reg1, reg2) Bxx_gen(NE, MARK3, reg1, reg2)
+// Branch to MARKLOCK if reg1!=reg2 (use j64)
+#define BNE_MARKLOCK(reg1, reg2) Bxx_gen(NE, MARKLOCK, reg1, reg2)
+// Branch to MARKLOCK if reg1!=0 (use j64)
+#define BNEZ_MARKLOCK(reg) BNE_MARKLOCK(reg, xZR)
 
 // Branch to NEXT if reg1==0 (use j64)
 #define CBZ_NEXT(reg1)                 \
@@ -824,7 +828,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 //uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 //uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 //uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
-//uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
 //uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
 //uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index f926eaba..ca8b0891 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -130,9 +130,9 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define AUIPC(rd, imm20)               EMIT(U_type((imm20)<<12, rd, 0b0010111))
 
 #define JAL_gen(rd, imm21)             J_type(imm21, rd, 0b1101111)
-// Unconditionnal branch, no return address set
+// Unconditional branch, no return address set
 #define B(imm21)                       EMIT(JAL_gen(xZR, imm21))
-// Uncondiftionnal branch, return set to xRA
+// Unconditional branch, return set to xRA
 #define JAL(imm21)                     EMIT(JAL_gen(xRA, imm21))
 
 #define JALR_gen(rd, rs1, imm12)       I_type(imm12, rs1, 0b000, rd, 0b1100111)
@@ -337,4 +337,17 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define REMUW(rd, rs1, rs2)         EMIT(R_type(0b0000001, rs2, rs1, 0b111, rd, 0b0111011))
 #define REMUxw(rd, rs1, rs2)        EMIT(R_type(0b0000001, rs2, rs1, 0b111, rd, rex.w?0b0110011:0b0111011))
 
+#define AQ_RL(f5, aq, rl) ((f5 << 2) | ((aq&1) << 1) | (rl&1))
+
+// RV32A
+#define LR_W(rd, rs1, aq, rl)       EMIT(R_type(AQ_RL(0b00010, aq, rl), 0, rs1, 0b010, rd, 0b0101111))
+#define SC_W(rd, rs2, rs1, aq, rl)  EMIT(R_type(AQ_RL(0b00011, aq, rl), rs2, rs1, 0b010, rd, 0b0101111))
+
+// RV64A
+#define LR_D(rd, rs1, aq, rl)       EMIT(R_type(AQ_RL(0b00010, aq, rl), 0, rs1, 0b011, rd, 0b0101111))
+#define SC_D(rd, rs2, rs1, aq, rl)  EMIT(R_type(AQ_RL(0b00011, aq, rl), rs2, rs1, 0b011, rd, 0b0101111))
+
+#define LRxw(rd, rs1, aq, rl)       EMIT(R_type(AQ_RL(0b00010, aq, rl), 0, rs1, 0b010|rex.w, rd, 0b0101111))
+#define SCxw(rd, rs2, rs1, aq, rl)  EMIT(R_type(AQ_RL(0b00011, aq, rl), rs2, rs1, 0b010|rex.w, rd, 0b0101111))
+
 #endif //__RV64_EMITTER_H__
diff --git a/src/dynarec/rv64/rv64_printer.c b/src/dynarec/rv64/rv64_printer.c
index 0e054e35..554ebd02 100644
--- a/src/dynarec/rv64/rv64_printer.c
+++ b/src/dynarec/rv64/rv64_printer.c
@@ -46,6 +46,8 @@ static const char fpnames[32][5] = {
 #define FUNCT3(data) (((data) >> 12) & 0x7 )
 #define FUNCT7(data) (((data) >> 25) & 0x7f)
 #define IMM116(data) (((data) >> 26) & 0x3f)
+#define AQ(data)     (((data) >> 26) & 0x1)
+#define RL(data)     (((data) >> 25) & 0x1)
 
 static inline insn_t insn_utype_read(uint32_t data)
 {
@@ -418,6 +420,8 @@ static inline insn_t insn_ciwtype_read(uint16_t data)
 #define PRINT_fd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], fpnames[insn.rs1]); return buff
 #define PRINT_xd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, gpnames[insn.rd], fpnames[insn.rs1]); return buff
 #define PRINT_fd_xs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], gpnames[insn.rs1]); return buff
+#define PRINT_rd_rs1_aqrl() snprintf(buff, sizeof(buff), "%s%s%s\t%s, (%s)", insn.name, aq?".aq":"", rl?".rl":"", gpnames[insn.rd], gpnames[insn.rs1]); return buff
+#define PRINT_rd_rs1_rs2_aqrl() snprintf(buff, sizeof(buff), "%s%s%s\t%s, %s, (%s)", insn.name, aq?".aq":"", rl?".rl":"", gpnames[insn.rd], gpnames[insn.rs1], gpnames[insn.rs2]); return buff
 
 // TODO: display csr name
 #define PRINT_rd_csr_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %d, %s", insn.name, RN(rd), insn.csr, RN(rs1)); return buff
@@ -845,6 +849,32 @@ const char* rv64_print(uint32_t data, uintptr_t addr)
             }
             PRINT_rs2_imm_rs1();
         }
+        case 0xb: {
+            uint32_t funct3 = FUNCT3(data);
+            uint32_t rs1 = RS3(data);
+            bool aq = AQ(data), rl = RL(data);
+            insn =  insn_rtype_read(data);
+            switch(funct3) {
+            case 0x2:
+                switch (rs1) {
+                case 0x2: /* LR.W */
+                    insn.name = "lr.w";
+                    PRINT_rd_rs1_aqrl();
+                case 0x3: /* SC.W */
+                    insn.name = "sc.w";
+                    PRINT_rd_rs1_rs2_aqrl();
+                }
+            case 0x3:
+                switch (rs1) {
+                case 0x2: /* LR.D */
+                    insn.name = "lr.w";
+                    PRINT_rd_rs1_aqrl();
+                case 0x3: /* SC.D */
+                    insn.name = "sc.w";
+                    PRINT_rd_rs1_rs2_aqrl();
+                }
+            }
+        }
         case 0xc: {
             insn =  insn_rtype_read(data);