diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-21 02:24:53 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-20 19:24:53 +0100 |
| commit | 70f91204b1345e08a7cf39e0622b4b94f158de66 (patch) | |
| tree | 306cb716f5f228d13cf56145feeb04923e79bcd9 /src | |
| parent | f4739ae147c1d8c34c3a9f21174e6ff0769197d6 (diff) | |
| download | box64-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.c | 3 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f0.c | 102 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 17 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_printer.c | 30 |
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); |