mirror of https://gitee.com/openkylin/qemu.git
RISC-V: Add misa to DisasContext
gen methods should access state from DisasContext. Add misa field to the DisasContext struct and remove CPURISCVState argument from all gen methods. Signed-off-by: Michael Clark <mjc@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
d75377bf7b
commit
db9f3fd69d
|
@ -46,6 +46,7 @@ typedef struct DisasContext {
|
||||||
target_ulong priv_ver;
|
target_ulong priv_ver;
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t mstatus_fs;
|
uint32_t mstatus_fs;
|
||||||
|
uint32_t misa;
|
||||||
uint32_t mem_idx;
|
uint32_t mem_idx;
|
||||||
/* Remember the rounding mode encoded in the previous fp instruction,
|
/* Remember the rounding mode encoded in the previous fp instruction,
|
||||||
which we have already installed into env->fp_status. Or -1 for
|
which we have already installed into env->fp_status. Or -1 for
|
||||||
|
@ -75,6 +76,11 @@ static const int tcg_memop_lookup[8] = {
|
||||||
#define CASE_OP_32_64(X) case X
|
#define CASE_OP_32_64(X) case X
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
|
||||||
|
{
|
||||||
|
return ctx->misa & ext;
|
||||||
|
}
|
||||||
|
|
||||||
static void generate_exception(DisasContext *ctx, int excp)
|
static void generate_exception(DisasContext *ctx, int excp)
|
||||||
{
|
{
|
||||||
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
|
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
|
||||||
|
@ -506,14 +512,13 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd,
|
||||||
tcg_temp_free(source1);
|
tcg_temp_free(source1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
|
static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
|
||||||
target_ulong imm)
|
|
||||||
{
|
{
|
||||||
target_ulong next_pc;
|
target_ulong next_pc;
|
||||||
|
|
||||||
/* check misaligned: */
|
/* check misaligned: */
|
||||||
next_pc = ctx->base.pc_next + imm;
|
next_pc = ctx->base.pc_next + imm;
|
||||||
if (!riscv_has_ext(env, RVC)) {
|
if (!has_ext(ctx, RVC)) {
|
||||||
if ((next_pc & 0x3) != 0) {
|
if ((next_pc & 0x3) != 0) {
|
||||||
gen_exception_inst_addr_mis(ctx);
|
gen_exception_inst_addr_mis(ctx);
|
||||||
return;
|
return;
|
||||||
|
@ -527,8 +532,8 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
|
||||||
ctx->base.is_jmp = DISAS_NORETURN;
|
ctx->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1,
|
||||||
int rd, int rs1, target_long imm)
|
target_long imm)
|
||||||
{
|
{
|
||||||
/* no chaining with JALR */
|
/* no chaining with JALR */
|
||||||
TCGLabel *misaligned = NULL;
|
TCGLabel *misaligned = NULL;
|
||||||
|
@ -540,7 +545,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
|
tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
|
||||||
tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
|
tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
|
||||||
|
|
||||||
if (!riscv_has_ext(env, RVC)) {
|
if (!has_ext(ctx, RVC)) {
|
||||||
misaligned = gen_new_label();
|
misaligned = gen_new_label();
|
||||||
tcg_gen_andi_tl(t0, cpu_pc, 0x2);
|
tcg_gen_andi_tl(t0, cpu_pc, 0x2);
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
|
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
|
||||||
|
@ -565,8 +570,8 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
||||||
tcg_temp_free(t0);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
|
||||||
int rs1, int rs2, target_long bimm)
|
target_long bimm)
|
||||||
{
|
{
|
||||||
TCGLabel *l = gen_new_label();
|
TCGLabel *l = gen_new_label();
|
||||||
TCGv source1, source2;
|
TCGv source1, source2;
|
||||||
|
@ -603,7 +608,7 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
||||||
|
|
||||||
gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
|
gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
|
||||||
gen_set_label(l); /* branch taken */
|
gen_set_label(l); /* branch taken */
|
||||||
if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
|
if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
|
||||||
/* misaligned */
|
/* misaligned */
|
||||||
gen_exception_inst_addr_mis(ctx);
|
gen_exception_inst_addr_mis(ctx);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1314,8 +1319,8 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
|
||||||
int rd, int rs1, int csr)
|
int csr)
|
||||||
{
|
{
|
||||||
TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
|
TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
|
||||||
source1 = tcg_temp_new();
|
source1 = tcg_temp_new();
|
||||||
|
@ -1361,7 +1366,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
|
||||||
gen_exception_illegal(ctx);
|
gen_exception_illegal(ctx);
|
||||||
break;
|
break;
|
||||||
case 0x102: /* SRET */
|
case 0x102: /* SRET */
|
||||||
if (riscv_has_ext(env, RVS)) {
|
if (has_ext(ctx, RVS)) {
|
||||||
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
|
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
|
||||||
tcg_gen_exit_tb(NULL, 0); /* no chaining */
|
tcg_gen_exit_tb(NULL, 0); /* no chaining */
|
||||||
ctx->base.is_jmp = DISAS_NORETURN;
|
ctx->base.is_jmp = DISAS_NORETURN;
|
||||||
|
@ -1506,7 +1511,7 @@ static void decode_RV32_64C0(DisasContext *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
|
static void decode_RV32_64C1(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
||||||
uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
|
uint8_t rd_rs1 = GET_C_RS1(ctx->opcode);
|
||||||
|
@ -1526,7 +1531,7 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
|
||||||
GET_C_IMM(ctx->opcode));
|
GET_C_IMM(ctx->opcode));
|
||||||
#else
|
#else
|
||||||
/* C.JAL(RV32) -> jal x1, offset[11:1] */
|
/* C.JAL(RV32) -> jal x1, offset[11:1] */
|
||||||
gen_jal(env, ctx, 1, GET_C_J_IMM(ctx->opcode));
|
gen_jal(ctx, 1, GET_C_J_IMM(ctx->opcode));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -1605,22 +1610,22 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* C.J -> jal x0, offset[11:1]*/
|
/* C.J -> jal x0, offset[11:1]*/
|
||||||
gen_jal(env, ctx, 0, GET_C_J_IMM(ctx->opcode));
|
gen_jal(ctx, 0, GET_C_J_IMM(ctx->opcode));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
/* C.BEQZ -> beq rs1', x0, offset[8:1]*/
|
/* C.BEQZ -> beq rs1', x0, offset[8:1]*/
|
||||||
rs1s = GET_C_RS1S(ctx->opcode);
|
rs1s = GET_C_RS1S(ctx->opcode);
|
||||||
gen_branch(env, ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
|
gen_branch(ctx, OPC_RISC_BEQ, rs1s, 0, GET_C_B_IMM(ctx->opcode));
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* C.BNEZ -> bne rs1', x0, offset[8:1]*/
|
/* C.BNEZ -> bne rs1', x0, offset[8:1]*/
|
||||||
rs1s = GET_C_RS1S(ctx->opcode);
|
rs1s = GET_C_RS1S(ctx->opcode);
|
||||||
gen_branch(env, ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
|
gen_branch(ctx, OPC_RISC_BNE, rs1s, 0, GET_C_B_IMM(ctx->opcode));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
|
static void decode_RV32_64C2(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
uint8_t rd, rs2;
|
uint8_t rd, rs2;
|
||||||
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
||||||
|
@ -1654,7 +1659,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
|
||||||
if (extract32(ctx->opcode, 12, 1) == 0) {
|
if (extract32(ctx->opcode, 12, 1) == 0) {
|
||||||
if (rs2 == 0) {
|
if (rs2 == 0) {
|
||||||
/* C.JR -> jalr x0, rs1, 0*/
|
/* C.JR -> jalr x0, rs1, 0*/
|
||||||
gen_jalr(env, ctx, OPC_RISC_JALR, 0, rd, 0);
|
gen_jalr(ctx, OPC_RISC_JALR, 0, rd, 0);
|
||||||
} else {
|
} else {
|
||||||
/* C.MV -> add rd, x0, rs2 */
|
/* C.MV -> add rd, x0, rs2 */
|
||||||
gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
|
gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
|
||||||
|
@ -1662,11 +1667,11 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
|
||||||
} else {
|
} else {
|
||||||
if (rd == 0) {
|
if (rd == 0) {
|
||||||
/* C.EBREAK -> ebreak*/
|
/* C.EBREAK -> ebreak*/
|
||||||
gen_system(env, ctx, OPC_RISC_ECALL, 0, 0, 0x1);
|
gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
|
||||||
} else {
|
} else {
|
||||||
if (rs2 == 0) {
|
if (rs2 == 0) {
|
||||||
/* C.JALR -> jalr x1, rs1, 0*/
|
/* C.JALR -> jalr x1, rs1, 0*/
|
||||||
gen_jalr(env, ctx, OPC_RISC_JALR, 1, rd, 0);
|
gen_jalr(ctx, OPC_RISC_JALR, 1, rd, 0);
|
||||||
} else {
|
} else {
|
||||||
/* C.ADD -> add rd, rd, rs2 */
|
/* C.ADD -> add rd, rd, rs2 */
|
||||||
gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
|
gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
|
||||||
|
@ -1698,7 +1703,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
|
static void decode_RV32_64C(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
uint8_t op = extract32(ctx->opcode, 0, 2);
|
uint8_t op = extract32(ctx->opcode, 0, 2);
|
||||||
|
|
||||||
|
@ -1707,15 +1712,15 @@ static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
|
||||||
decode_RV32_64C0(ctx);
|
decode_RV32_64C0(ctx);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
decode_RV32_64C1(env, ctx);
|
decode_RV32_64C1(ctx);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
decode_RV32_64C2(env, ctx);
|
decode_RV32_64C2(ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
|
static void decode_RV32_64G(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int rs1;
|
int rs1;
|
||||||
int rs2;
|
int rs2;
|
||||||
|
@ -1750,13 +1755,13 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
|
||||||
break;
|
break;
|
||||||
case OPC_RISC_JAL:
|
case OPC_RISC_JAL:
|
||||||
imm = GET_JAL_IMM(ctx->opcode);
|
imm = GET_JAL_IMM(ctx->opcode);
|
||||||
gen_jal(env, ctx, rd, imm);
|
gen_jal(ctx, rd, imm);
|
||||||
break;
|
break;
|
||||||
case OPC_RISC_JALR:
|
case OPC_RISC_JALR:
|
||||||
gen_jalr(env, ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
|
gen_jalr(ctx, MASK_OP_JALR(ctx->opcode), rd, rs1, imm);
|
||||||
break;
|
break;
|
||||||
case OPC_RISC_BRANCH:
|
case OPC_RISC_BRANCH:
|
||||||
gen_branch(env, ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
|
gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2,
|
||||||
GET_B_IMM(ctx->opcode));
|
GET_B_IMM(ctx->opcode));
|
||||||
break;
|
break;
|
||||||
case OPC_RISC_LOAD:
|
case OPC_RISC_LOAD:
|
||||||
|
@ -1827,7 +1832,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_RISC_SYSTEM:
|
case OPC_RISC_SYSTEM:
|
||||||
gen_system(env, ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
|
gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1,
|
||||||
(ctx->opcode & 0xFFF00000) >> 20);
|
(ctx->opcode & 0xFFF00000) >> 20);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1836,19 +1841,19 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_opc(CPURISCVState *env, DisasContext *ctx)
|
static void decode_opc(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
/* check for compressed insn */
|
/* check for compressed insn */
|
||||||
if (extract32(ctx->opcode, 0, 2) != 3) {
|
if (extract32(ctx->opcode, 0, 2) != 3) {
|
||||||
if (!riscv_has_ext(env, RVC)) {
|
if (!has_ext(ctx, RVC)) {
|
||||||
gen_exception_illegal(ctx);
|
gen_exception_illegal(ctx);
|
||||||
} else {
|
} else {
|
||||||
ctx->pc_succ_insn = ctx->base.pc_next + 2;
|
ctx->pc_succ_insn = ctx->base.pc_next + 2;
|
||||||
decode_RV32_64C(env, ctx);
|
decode_RV32_64C(ctx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx->pc_succ_insn = ctx->base.pc_next + 4;
|
ctx->pc_succ_insn = ctx->base.pc_next + 4;
|
||||||
decode_RV32_64G(env, ctx);
|
decode_RV32_64G(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1861,6 +1866,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||||
ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
|
ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
|
||||||
ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
|
ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
|
||||||
ctx->priv_ver = env->priv_ver;
|
ctx->priv_ver = env->priv_ver;
|
||||||
|
ctx->misa = env->misa;
|
||||||
ctx->frm = -1; /* unknown rounding mode */
|
ctx->frm = -1; /* unknown rounding mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1891,14 +1897,13 @@ static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||||
CPURISCVState *env = cpu->env_ptr;
|
CPURISCVState *env = cpu->env_ptr;
|
||||||
|
|
||||||
ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
|
ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
|
||||||
decode_opc(env, ctx);
|
decode_opc(ctx);
|
||||||
ctx->base.pc_next = ctx->pc_succ_insn;
|
ctx->base.pc_next = ctx->pc_succ_insn;
|
||||||
|
|
||||||
if (ctx->base.is_jmp == DISAS_NEXT) {
|
if (ctx->base.is_jmp == DISAS_NEXT) {
|
||||||
|
|
Loading…
Reference in New Issue