mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 12:35:36 +00:00
target/riscv: Convert quadrant 2 of RVXC insns to decodetree
Backports commit 97b0be81f6f20bfd53725cb2500b47c6786be532 from qemu
This commit is contained in:
parent
b4854e3340
commit
580457a1d2
|
@ -20,6 +20,7 @@
|
|||
%rd 7:5
|
||||
%rs1_3 7:3 !function=ex_rvc_register
|
||||
%rs2_3 2:3 !function=ex_rvc_register
|
||||
%rs2_5 2:5
|
||||
|
||||
# Immediates:
|
||||
%imm_ci 12:s1 2:5
|
||||
|
@ -30,6 +31,10 @@
|
|||
%imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
|
||||
|
||||
%nzuimm_6bit 12:1 2:5
|
||||
%uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3
|
||||
%uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2
|
||||
%uimm_6bit_sd 7:3 10:3 !function=ex_shift_3
|
||||
%uimm_6bit_sw 7:2 9:4 !function=ex_shift_2
|
||||
|
||||
%imm_addi16sp 12:s1 3:2 5:1 2:1 6:1 !function=ex_shift_4
|
||||
%imm_lui 12:s1 2:5 !function=ex_shift_12
|
||||
|
@ -47,10 +52,15 @@
|
|||
&cj imm
|
||||
&c_shift shamt rd
|
||||
|
||||
&c_ld uimm rd
|
||||
&c_sd uimm rs2
|
||||
|
||||
&caddi16sp_lui imm_lui imm_addi16sp rd
|
||||
&cflwsp_ldsp uimm_flwsp uimm_ldsp rd
|
||||
&cfswsp_sdsp uimm_fswsp uimm_sdsp rs2
|
||||
|
||||
# Formats 16:
|
||||
@cr .... ..... ..... .. &cr rs2=%rs2_5 %rd
|
||||
@ci ... . ..... ..... .. &ci imm=%imm_ci %rd
|
||||
@ciw ... ........ ... .. &ciw nzuimm=%nzuimm_ciw rd=%rs2_3
|
||||
@cl_d ... ... ... .. ... .. &cl_dw uimm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3
|
||||
|
@ -63,9 +73,19 @@
|
|||
@cb ... ... ... .. ... .. &cb imm=%imm_cb rs1=%rs1_3
|
||||
@cj ... ........... .. &cj imm=%imm_cj
|
||||
|
||||
@c_ld ... . ..... ..... .. &c_ld uimm=%uimm_6bit_ld %rd
|
||||
@c_lw ... . ..... ..... .. &c_ld uimm=%uimm_6bit_lw %rd
|
||||
@c_sd ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sd rs2=%rs2_5
|
||||
@c_sw ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sw rs2=%rs2_5
|
||||
|
||||
@c_addi16sp_lui ... . ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
|
||||
@c_flwsp_ldsp ... . ..... ..... .. &cflwsp_ldsp uimm_flwsp=%uimm_6bit_lw \
|
||||
uimm_ldsp=%uimm_6bit_ld %rd
|
||||
@c_fswsp_sdsp ... . ..... ..... .. &cfswsp_sdsp uimm_fswsp=%uimm_6bit_sw \
|
||||
uimm_sdsp=%uimm_6bit_sd rs2=%rs2_5
|
||||
|
||||
@c_shift ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
|
||||
@c_shift2 ... . .. ... ..... .. &c_shift rd=%rd shamt=%nzuimm_6bit
|
||||
|
||||
@c_andi ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
|
||||
|
||||
|
@ -96,3 +116,14 @@ c_addw 100 1 11 ... 01 ... 01 @cs_2
|
|||
c_j 101 ........... 01 @cj
|
||||
c_beqz 110 ... ... ..... 01 @cb
|
||||
c_bnez 111 ... ... ..... 01 @cb
|
||||
|
||||
# *** RV64C Standard Extension (Quadrant 2) ***
|
||||
c_slli 000 . ..... ..... 10 @c_shift2
|
||||
c_fldsp 001 . ..... ..... 10 @c_ld
|
||||
c_lwsp 010 . ..... ..... 10 @c_lw
|
||||
c_flwsp_ldsp 011 . ..... ..... 10 @c_flwsp_ldsp #C.LDSP:RV64;C.FLWSP:RV32
|
||||
c_jr_mv 100 0 ..... ..... 10 @cr
|
||||
c_ebreak_jalr_add 100 1 ..... ..... 10 @cr
|
||||
c_fsdsp 101 ...... ..... 10 @c_sd
|
||||
c_swsp 110 . ..... ..... 10 @c_sw
|
||||
c_fswsp_sdsp 111 . ..... ..... 10 @c_fswsp_sdsp #C.SDSP:RV64;C.FSWSP:RV32
|
||||
|
|
|
@ -223,4 +223,105 @@ static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
|
|||
{
|
||||
arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
|
||||
return trans_bne(ctx, &arg);
|
||||
}
|
||||
}
|
||||
|
||||
static bool trans_c_slli(DisasContext *ctx, arg_c_slli *a)
|
||||
{
|
||||
int shamt = a->shamt;
|
||||
if (shamt == 0) {
|
||||
/* For RV128 a shamt of 0 means a shift by 64 */
|
||||
shamt = 64;
|
||||
}
|
||||
/* Ensure, that shamt[5] is zero for RV32 */
|
||||
if (shamt >= TARGET_LONG_BITS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
arg_slli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
|
||||
return trans_slli(ctx, &arg);
|
||||
}
|
||||
|
||||
static bool trans_c_fldsp(DisasContext *ctx, arg_c_fldsp *a)
|
||||
{
|
||||
arg_fld arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm };
|
||||
return trans_fld(ctx, &arg);
|
||||
}
|
||||
|
||||
static bool trans_c_lwsp(DisasContext *ctx, arg_c_lwsp *a)
|
||||
{
|
||||
arg_lw arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm };
|
||||
return trans_lw(ctx, &arg);
|
||||
}
|
||||
|
||||
static bool trans_c_flwsp_ldsp(DisasContext *ctx, arg_c_flwsp_ldsp *a)
|
||||
{
|
||||
#ifdef TARGET_RISCV32
|
||||
/* C.FLWSP */
|
||||
arg_flw arg_flw = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_flwsp };
|
||||
return trans_flw(ctx, &arg_flw);
|
||||
#else
|
||||
/* C.LDSP */
|
||||
arg_ld arg_ld = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_ldsp };
|
||||
return trans_ld(ctx, &arg_ld);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool trans_c_jr_mv(DisasContext *ctx, arg_c_jr_mv *a)
|
||||
{
|
||||
if (a->rd != 0 && a->rs2 == 0) {
|
||||
/* C.JR */
|
||||
arg_jalr arg = { .rd = 0, .rs1 = a->rd, .imm = 0 };
|
||||
return trans_jalr(ctx, &arg);
|
||||
} else if (a->rd != 0 && a->rs2 != 0) {
|
||||
/* C.MV */
|
||||
arg_add arg = { .rd = a->rd, .rs1 = 0, .rs2 = a->rs2 };
|
||||
return trans_add(ctx, &arg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool trans_c_ebreak_jalr_add(DisasContext *ctx, arg_c_ebreak_jalr_add *a)
|
||||
{
|
||||
if (a->rd == 0 && a->rs2 == 0) {
|
||||
/* C.EBREAK */
|
||||
arg_ebreak arg = { };
|
||||
return trans_ebreak(ctx, &arg);
|
||||
} else if (a->rd != 0) {
|
||||
if (a->rs2 == 0) {
|
||||
/* C.JALR */
|
||||
arg_jalr arg = { .rd = 1, .rs1 = a->rd, .imm = 0 };
|
||||
return trans_jalr(ctx, &arg);
|
||||
} else {
|
||||
/* C.ADD */
|
||||
arg_add arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
|
||||
return trans_add(ctx, &arg);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool trans_c_fsdsp(DisasContext *ctx, arg_c_fsdsp *a)
|
||||
{
|
||||
arg_fsd arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm };
|
||||
return trans_fsd(ctx, &arg);
|
||||
}
|
||||
|
||||
static bool trans_c_swsp(DisasContext *ctx, arg_c_swsp *a)
|
||||
{
|
||||
arg_sw arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm };
|
||||
return trans_sw(ctx, &arg);
|
||||
}
|
||||
|
||||
static bool trans_c_fswsp_sdsp(DisasContext *ctx, arg_c_fswsp_sdsp *a)
|
||||
{
|
||||
#ifdef TARGET_RISCV32
|
||||
/* C.FSWSP */
|
||||
arg_fsw a_fsw = { .rs1 = a->rs2, .rs2 = 2, .imm = a->uimm_fswsp };
|
||||
return trans_fsw(ctx, &a_fsw);
|
||||
#else
|
||||
/* C.SDSP */
|
||||
arg_sd a_sd = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_sdsp };
|
||||
return trans_sd(ctx, &a_sd);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -703,6 +703,7 @@ static void mark_fs_dirty(DisasContext *ctx)
|
|||
static inline void mark_fs_dirty(DisasContext *ctx) { }
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_RISCV64)
|
||||
static void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd,
|
||||
int rs1, target_long imm)
|
||||
{
|
||||
|
@ -779,6 +780,7 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1,
|
|||
|
||||
tcg_temp_free(tcg_ctx, t0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gen_set_rm(DisasContext *ctx, int rm)
|
||||
{
|
||||
|
@ -855,84 +857,6 @@ static void decode_RV32_64C0(DisasContext *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void decode_RV32_64C2(DisasContext *ctx)
|
||||
{
|
||||
uint8_t rd, rs2;
|
||||
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
||||
|
||||
|
||||
rd = GET_RD(ctx->opcode);
|
||||
|
||||
switch (funct3) {
|
||||
case 0: /* C.SLLI -> slli rd, rd, shamt[5:0]
|
||||
C.SLLI64 -> */
|
||||
gen_arith_imm(ctx, OPC_RISC_SLLI, rd, rd, GET_C_ZIMM(ctx->opcode));
|
||||
break;
|
||||
case 1: /* C.FLDSP(RV32/64DC) -> fld rd, offset[8:3](x2) */
|
||||
gen_fp_load(ctx, OPC_RISC_FLD, rd, 2, GET_C_LDSP_IMM(ctx->opcode));
|
||||
break;
|
||||
case 2: /* C.LWSP -> lw rd, offset[7:2](x2) */
|
||||
gen_load(ctx, OPC_RISC_LW, rd, 2, GET_C_LWSP_IMM(ctx->opcode));
|
||||
break;
|
||||
case 3:
|
||||
#if defined(TARGET_RISCV64)
|
||||
/* C.LDSP(RVC64) -> ld rd, offset[8:3](x2) */
|
||||
gen_load(ctx, OPC_RISC_LD, rd, 2, GET_C_LDSP_IMM(ctx->opcode));
|
||||
#else
|
||||
/* C.FLWSP(RV32FC) -> flw rd, offset[7:2](x2) */
|
||||
gen_fp_load(ctx, OPC_RISC_FLW, rd, 2, GET_C_LWSP_IMM(ctx->opcode));
|
||||
#endif
|
||||
break;
|
||||
case 4:
|
||||
rs2 = GET_C_RS2(ctx->opcode);
|
||||
|
||||
if (extract32(ctx->opcode, 12, 1) == 0) {
|
||||
if (rs2 == 0) {
|
||||
/* C.JR -> jalr x0, rs1, 0*/
|
||||
gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0);
|
||||
} else {
|
||||
/* C.MV -> add rd, x0, rs2 */
|
||||
gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
|
||||
}
|
||||
} else {
|
||||
if (rd == 0) {
|
||||
/* C.EBREAK -> ebreak*/
|
||||
gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
|
||||
} else {
|
||||
if (rs2 == 0) {
|
||||
/* C.JALR -> jalr x1, rs1, 0*/
|
||||
gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0);
|
||||
} else {
|
||||
/* C.ADD -> add rd, rd, rs2 */
|
||||
gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* C.FSDSP -> fsd rs2, offset[8:3](x2)*/
|
||||
gen_fp_store(ctx, OPC_RISC_FSD, 2, GET_C_RS2(ctx->opcode),
|
||||
GET_C_SDSP_IMM(ctx->opcode));
|
||||
/* C.SQSP */
|
||||
break;
|
||||
case 6: /* C.SWSP -> sw rs2, offset[7:2](x2)*/
|
||||
gen_store(ctx, OPC_RISC_SW, 2, GET_C_RS2(ctx->opcode),
|
||||
GET_C_SWSP_IMM(ctx->opcode));
|
||||
break;
|
||||
case 7:
|
||||
#if defined(TARGET_RISCV64)
|
||||
/* C.SDSP(Rv64/128) -> sd rs2, offset[8:3](x2)*/
|
||||
gen_store(ctx, OPC_RISC_SD, 2, GET_C_RS2(ctx->opcode),
|
||||
GET_C_SDSP_IMM(ctx->opcode));
|
||||
#else
|
||||
/* C.FSWSP(RV32) -> fsw rs2, offset[7:2](x2) */
|
||||
gen_fp_store(ctx, OPC_RISC_FSW, 2, GET_C_RS2(ctx->opcode),
|
||||
GET_C_SWSP_IMM(ctx->opcode));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_RV32_64C(DisasContext *ctx)
|
||||
{
|
||||
uint8_t op = extract32(ctx->opcode, 0, 2);
|
||||
|
@ -941,9 +865,6 @@ static void decode_RV32_64C(DisasContext *ctx)
|
|||
case 0:
|
||||
decode_RV32_64C0(ctx);
|
||||
break;
|
||||
case 2:
|
||||
decode_RV32_64C2(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue