* [Qemu-devel] [PATCH v1 1/6] target/riscv: avoid integer overflow in next_page PC check
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 2/6] translator: merge max_insns into DisasContextBase Michael Clark
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel
Cc: patches, Emilio G. Cota, Michael Clark, Palmer Dabbelt,
Sagar Karandikar, Bastian Koppelmann
From: "Emilio G. Cota" <cota@braap.org>
If the PC is in the last page of the address space, next_page_start
overflows to 0. Fix it.
Reported-by: Richard Henderson <richard.henderson@linaro.org>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Michael Clark <mjc@sifive.com>
Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Michael Clark <mjc@sifive.com>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
target/riscv/translate.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c0e6a044d383..a98033ca77ca 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1850,11 +1850,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
CPURISCVState *env = cs->env_ptr;
DisasContext ctx;
target_ulong pc_start;
- target_ulong next_page_start;
+ target_ulong page_start;
int num_insns;
int max_insns;
pc_start = tb->pc;
- next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ page_start = pc_start & TARGET_PAGE_MASK;
ctx.pc = pc_start;
/* once we have GDB, the rest of the translate.c implementation should be
@@ -1904,7 +1904,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
if (cs->singlestep_enabled) {
break;
}
- if (ctx.pc >= next_page_start) {
+ if (ctx.pc - page_start >= TARGET_PAGE_SIZE) {
break;
}
if (tcg_op_buf_full()) {
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v1 2/6] translator: merge max_insns into DisasContextBase
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 1/6] target/riscv: avoid integer overflow in next_page PC check Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 3/6] target/riscv: convert to DisasJumpType Michael Clark
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel; +Cc: patches, Emilio G. Cota
From: "Emilio G. Cota" <cota@braap.org>
While at it, use int for both num_insns and max_insns to make
sure we have same-type comparisons.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
accel/tcg/translator.c | 21 ++++++++++-----------
include/exec/translator.h | 8 ++++----
target/alpha/translate.c | 6 ++----
target/arm/translate-a64.c | 8 +++-----
target/arm/translate.c | 11 ++++-------
target/hppa/translate.c | 7 ++-----
target/i386/translate.c | 5 +----
target/ppc/translate.c | 5 ++---
8 files changed, 28 insertions(+), 43 deletions(-)
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 23c6602cd921..0f9dca911399 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -34,8 +34,6 @@ void translator_loop_temp_check(DisasContextBase *db)
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
CPUState *cpu, TranslationBlock *tb)
{
- int max_insns;
-
/* Initialize DisasContext */
db->tb = tb;
db->pc_first = tb->pc;
@@ -45,18 +43,18 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
db->singlestep_enabled = cpu->singlestep_enabled;
/* Instruction counting */
- max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
- if (max_insns == 0) {
- max_insns = CF_COUNT_MASK;
+ db->max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
+ if (db->max_insns == 0) {
+ db->max_insns = CF_COUNT_MASK;
}
- if (max_insns > TCG_MAX_INSNS) {
- max_insns = TCG_MAX_INSNS;
+ if (db->max_insns > TCG_MAX_INSNS) {
+ db->max_insns = TCG_MAX_INSNS;
}
if (db->singlestep_enabled || singlestep) {
- max_insns = 1;
+ db->max_insns = 1;
}
- max_insns = ops->init_disas_context(db, cpu, max_insns);
+ ops->init_disas_context(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
/* Reset the temp count so that we can identify leaks */
@@ -95,7 +93,8 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
update db->pc_next and db->is_jmp to indicate what should be
done next -- either exiting this loop or locate the start of
the next instruction. */
- if (db->num_insns == max_insns && (tb_cflags(db->tb) & CF_LAST_IO)) {
+ if (db->num_insns == db->max_insns
+ && (tb_cflags(db->tb) & CF_LAST_IO)) {
/* Accept I/O on the last instruction. */
gen_io_start();
ops->translate_insn(db, cpu);
@@ -111,7 +110,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
/* Stop translation if the output buffer is full,
or we have executed all of the allowed instructions. */
- if (tcg_op_buf_full() || db->num_insns >= max_insns) {
+ if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
db->is_jmp = DISAS_TOO_MANY;
break;
}
diff --git a/include/exec/translator.h b/include/exec/translator.h
index e2dc2a04ae37..71e7b2c34714 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -58,6 +58,7 @@ typedef enum DisasJumpType {
* disassembly).
* @is_jmp: What instruction to disassemble next.
* @num_insns: Number of translated instructions (including current).
+ * @max_insns: Maximum number of instructions to be translated in this TB.
* @singlestep_enabled: "Hardware" single stepping enabled.
*
* Architecture-agnostic disassembly context.
@@ -67,7 +68,8 @@ typedef struct DisasContextBase {
target_ulong pc_first;
target_ulong pc_next;
DisasJumpType is_jmp;
- unsigned int num_insns;
+ int num_insns;
+ int max_insns;
bool singlestep_enabled;
} DisasContextBase;
@@ -76,7 +78,6 @@ typedef struct DisasContextBase {
* @init_disas_context:
* Initialize the target-specific portions of DisasContext struct.
* The generic DisasContextBase has already been initialized.
- * Return max_insns, modified as necessary by db->tb->flags.
*
* @tb_start:
* Emit any code required before the start of the main loop,
@@ -106,8 +107,7 @@ typedef struct DisasContextBase {
* Print instruction disassembly to log.
*/
typedef struct TranslatorOps {
- int (*init_disas_context)(DisasContextBase *db, CPUState *cpu,
- int max_insns);
+ void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
void (*tb_start)(DisasContextBase *db, CPUState *cpu);
void (*insn_start)(DisasContextBase *db, CPUState *cpu);
bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 73a1b5e63ed1..15eca71d49f7 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2919,8 +2919,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
return ret;
}
-static int alpha_tr_init_disas_context(DisasContextBase *dcbase,
- CPUState *cpu, int max_insns)
+static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
CPUAlphaState *env = cpu->env_ptr;
@@ -2959,8 +2958,7 @@ static int alpha_tr_init_disas_context(DisasContextBase *dcbase,
mask = TARGET_PAGE_MASK;
}
bound = -(ctx->base.pc_first | mask) / 4;
-
- return MIN(max_insns, bound);
+ ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
}
static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6d49f30b4a4e..1e7c150514ca 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -13224,8 +13224,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
free_tmp_a64(s);
}
-static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
- CPUState *cpu, int max_insns)
+static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
+ CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
CPUARMState *env = cpu->env_ptr;
@@ -13288,11 +13288,9 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
if (dc->ss_active) {
bound = 1;
}
- max_insns = MIN(max_insns, bound);
+ dc->base.max_insns = MIN(dc->base.max_insns, bound);
init_tmp_a64_array(dc);
-
- return max_insns;
}
static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index ad208867a79f..47f990cc0d01 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12243,8 +12243,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
return !thumb_insn_is_16bit(s, insn);
}
-static int arm_tr_init_disas_context(DisasContextBase *dcbase,
- CPUState *cs, int max_insns)
+static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
CPUARMState *env = cs->env_ptr;
@@ -12306,14 +12305,14 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
/* If architectural single step active, limit to 1. */
if (is_singlestepping(dc)) {
- max_insns = 1;
+ dc->base.max_insns = 1;
}
/* ARM is a fixed-length ISA. Bound the number of insns to execute
to those left on the page. */
if (!dc->thumb) {
- int bound = (dc->next_page_start - dc->base.pc_first) / 4;
- max_insns = MIN(max_insns, bound);
+ int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
+ dc->base.max_insns = MIN(dc->base.max_insns, bound);
}
cpu_F0s = tcg_temp_new_i32();
@@ -12324,8 +12323,6 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
cpu_V1 = cpu_F1d;
/* FIXME: cpu_M0 can probably be the same as cpu_V0. */
cpu_M0 = tcg_temp_new_i64();
-
- return max_insns;
}
static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index cdc397308b9f..5320b217deb0 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4669,8 +4669,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
return gen_illegal(ctx);
}
-static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
- CPUState *cs, int max_insns)
+static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
int bound;
@@ -4700,14 +4699,12 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
/* Bound the number of instructions by those left on the page. */
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
- bound = MIN(max_insns, bound);
+ ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
ctx->ntempr = 0;
ctx->ntempl = 0;
memset(ctx->tempr, 0, sizeof(ctx->tempr));
memset(ctx->templ, 0, sizeof(ctx->templ));
-
- return bound;
}
static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index c9ed8dc70978..b0f69838f24b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8402,8 +8402,7 @@ void tcg_x86_init(void)
}
}
-static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
- int max_insns)
+static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
CPUX86State *env = cpu->env_ptr;
@@ -8470,8 +8469,6 @@ static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
cpu_ptr0 = tcg_temp_new_ptr();
cpu_ptr1 = tcg_temp_new_ptr();
cpu_cc_srcT = tcg_temp_local_new();
-
- return max_insns;
}
static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 2a4140f42062..7972e6b4101e 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7215,8 +7215,7 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
#endif
}
-static int ppc_tr_init_disas_context(DisasContextBase *dcbase,
- CPUState *cs, int max_insns)
+static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
CPUPPCState *env = cs->env_ptr;
@@ -7281,7 +7280,7 @@ static int ppc_tr_init_disas_context(DisasContextBase *dcbase,
#endif
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
- return MIN(max_insns, bound);
+ ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
}
static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs)
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v1 3/6] target/riscv: convert to DisasJumpType
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 1/6] target/riscv: avoid integer overflow in next_page PC check Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 2/6] translator: merge max_insns into DisasContextBase Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 4/6] target/riscv: convert to DisasContextBase Michael Clark
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel
Cc: patches, Emilio G. Cota, Michael Clark, Palmer Dabbelt,
Sagar Karandikar, Bastian Koppelmann
From: "Emilio G. Cota" <cota@braap.org>
Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Cc: Michael Clark <mjc@sifive.com>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
target/riscv/translate.c | 72 +++++++++++++++++++-----------------------------
1 file changed, 28 insertions(+), 44 deletions(-)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index a98033ca77ca..1fee5b51dc20 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -26,6 +26,7 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "exec/translator.h"
#include "exec/log.h"
#include "instmap.h"
@@ -46,7 +47,7 @@ typedef struct DisasContext {
uint32_t flags;
uint32_t mem_idx;
int singlestep_enabled;
- int bstate;
+ DisasJumpType is_jmp;
/* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status. Or -1 for
no previous fp instruction. Note that we exit the TB when writing
@@ -55,13 +56,6 @@ typedef struct DisasContext {
int frm;
} DisasContext;
-enum {
- BS_NONE = 0, /* When seen outside of translation while loop, indicates
- need to exit tb due to end of page. */
- BS_STOP = 1, /* Need to exit tb for syscall, sret, etc. */
- BS_BRANCH = 2, /* Need to exit tb for branch, jal, etc. */
-};
-
/* convert riscv funct3 to qemu memop for load/store */
static const int tcg_memop_lookup[8] = {
[0 ... 7] = -1,
@@ -88,7 +82,7 @@ static void generate_exception(DisasContext *ctx, int excp)
TCGv_i32 helper_tmp = tcg_const_i32(excp);
gen_helper_raise_exception(cpu_env, helper_tmp);
tcg_temp_free_i32(helper_tmp);
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
}
static void generate_exception_mbadaddr(DisasContext *ctx, int excp)
@@ -98,7 +92,7 @@ static void generate_exception_mbadaddr(DisasContext *ctx, int excp)
TCGv_i32 helper_tmp = tcg_const_i32(excp);
gen_helper_raise_exception(cpu_env, helper_tmp);
tcg_temp_free_i32(helper_tmp);
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
}
static void gen_exception_debug(void)
@@ -531,7 +525,7 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
}
gen_goto_tb(ctx, 0, ctx->pc + imm); /* must use this for safety */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
}
static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
@@ -562,7 +556,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_set_label(misaligned);
gen_exception_inst_addr_mis(ctx);
}
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
break;
default:
@@ -616,7 +610,7 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
} else {
gen_goto_tb(ctx, 0, ctx->pc + bimm);
}
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
}
static void gen_load(DisasContext *ctx, uint32_t opc, int rd, int rs1,
@@ -1344,12 +1338,12 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
/* always generates U-level ECALL, fixed in do_interrupt handler */
generate_exception(ctx, RISCV_EXCP_U_ECALL);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
break;
case 0x1: /* EBREAK */
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
break;
#ifndef CONFIG_USER_ONLY
case 0x002: /* URET */
@@ -1359,7 +1353,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
if (riscv_has_ext(env, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
} else {
gen_exception_illegal(ctx);
}
@@ -1370,7 +1364,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
case 0x302: /* MRET */
gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
break;
case 0x7b2: /* DRET */
gen_exception_illegal(ctx);
@@ -1419,7 +1413,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
/* end tb since we may be changing priv modes, to get mmu_index right */
tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
break;
}
tcg_temp_free(source1);
@@ -1812,7 +1806,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
* however we need to end the translation block */
tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
tcg_gen_exit_tb(0);
- ctx->bstate = BS_BRANCH;
+ ctx->is_jmp = DISAS_NORETURN;
} else {
/* FENCE is a full memory barrier. */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
@@ -1862,7 +1856,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
ctx.singlestep_enabled = cs->singlestep_enabled;
ctx.tb = tb;
- ctx.bstate = BS_NONE;
+ ctx.is_jmp = DISAS_NEXT;
ctx.flags = tb->flags;
ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK;
ctx.frm = -1; /* unknown rounding mode */
@@ -1877,13 +1871,13 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
}
gen_tb_start(tb);
- while (ctx.bstate == BS_NONE) {
+ while (ctx.is_jmp == DISAS_NEXT) {
tcg_gen_insn_start(ctx.pc);
num_insns++;
if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
tcg_gen_movi_tl(cpu_pc, ctx.pc);
- ctx.bstate = BS_BRANCH;
+ ctx.is_jmp = DISAS_NORETURN;
gen_exception_debug();
/* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
@@ -1901,31 +1895,20 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
decode_opc(env, &ctx);
ctx.pc = ctx.next_pc;
- if (cs->singlestep_enabled) {
- break;
- }
- if (ctx.pc - page_start >= TARGET_PAGE_SIZE) {
- break;
- }
- if (tcg_op_buf_full()) {
- break;
+ if (ctx.is_jmp == DISAS_NEXT &&
+ (cs->singlestep_enabled ||
+ ctx.pc - page_start >= TARGET_PAGE_SIZE ||
+ tcg_op_buf_full() ||
+ num_insns >= max_insns ||
+ singlestep)) {
+ ctx.is_jmp = DISAS_TOO_MANY;
}
- if (num_insns >= max_insns) {
- break;
- }
- if (singlestep) {
- break;
- }
-
}
if (tb->cflags & CF_LAST_IO) {
gen_io_end();
}
- switch (ctx.bstate) {
- case BS_STOP:
- gen_goto_tb(&ctx, 0, ctx.pc);
- break;
- case BS_NONE: /* handle end of page - DO NOT CHAIN. See gen_goto_tb. */
+ switch (ctx.is_jmp) {
+ case DISAS_TOO_MANY:
tcg_gen_movi_tl(cpu_pc, ctx.pc);
if (cs->singlestep_enabled) {
gen_exception_debug();
@@ -1933,9 +1916,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
tcg_gen_exit_tb(0);
}
break;
- case BS_BRANCH: /* ops using BS_BRANCH generate own exit seq */
- default:
+ case DISAS_NORETURN:
break;
+ default:
+ g_assert_not_reached();
}
done_generating:
gen_tb_end(tb, num_insns);
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v1 4/6] target/riscv: convert to DisasContextBase
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
` (2 preceding siblings ...)
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 3/6] target/riscv: convert to DisasJumpType Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 5/6] target/riscv: convert to TranslatorOps Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 6/6] target/riscv: add misa to DisasContext Michael Clark
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel
Cc: patches, Emilio G. Cota, Michael Clark, Palmer Dabbelt,
Sagar Karandikar, Bastian Koppelmann
From: "Emilio G. Cota" <cota@braap.org>
Notes:
- Did not convert {num,max}_insns, since the corresponding code
will go away in the next patch.
- ctx->pc becomes ctx->base.pc_next, and ctx->next_pc becomes
ctx->pc_succ_insn.
While at it, convert the remaining tb->cflags readers to tb_cflags().
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Cc: Michael Clark <mjc@sifive.com>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
target/riscv/translate.c | 129 +++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 65 deletions(-)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1fee5b51dc20..68979abfd7ed 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -40,14 +40,12 @@ static TCGv load_val;
#include "exec/gen-icount.h"
typedef struct DisasContext {
- struct TranslationBlock *tb;
- target_ulong pc;
- target_ulong next_pc;
+ DisasContextBase base;
+ /* pc_succ_insn points to the instruction following base.pc_next */
+ target_ulong pc_succ_insn;
uint32_t opcode;
uint32_t flags;
uint32_t mem_idx;
- int singlestep_enabled;
- DisasJumpType is_jmp;
/* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status. Or -1 for
no previous fp instruction. Note that we exit the TB when writing
@@ -78,21 +76,21 @@ static const int tcg_memop_lookup[8] = {
static void generate_exception(DisasContext *ctx, int excp)
{
- tcg_gen_movi_tl(cpu_pc, ctx->pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
TCGv_i32 helper_tmp = tcg_const_i32(excp);
gen_helper_raise_exception(cpu_env, helper_tmp);
tcg_temp_free_i32(helper_tmp);
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
static void generate_exception_mbadaddr(DisasContext *ctx, int excp)
{
- tcg_gen_movi_tl(cpu_pc, ctx->pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
TCGv_i32 helper_tmp = tcg_const_i32(excp);
gen_helper_raise_exception(cpu_env, helper_tmp);
tcg_temp_free_i32(helper_tmp);
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
static void gen_exception_debug(void)
@@ -114,12 +112,12 @@ static void gen_exception_inst_addr_mis(DisasContext *ctx)
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
{
- if (unlikely(ctx->singlestep_enabled)) {
+ if (unlikely(ctx->base.singlestep_enabled)) {
return false;
}
#ifndef CONFIG_USER_ONLY
- return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
+ return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
#else
return true;
#endif
@@ -131,10 +129,10 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
/* chaining is only allowed when the jump is to the same page */
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(cpu_pc, dest);
- tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
+ tcg_gen_exit_tb((uintptr_t)ctx->base.tb + n);
} else {
tcg_gen_movi_tl(cpu_pc, dest);
- if (ctx->singlestep_enabled) {
+ if (ctx->base.singlestep_enabled) {
gen_exception_debug();
} else {
tcg_gen_exit_tb(0);
@@ -513,7 +511,7 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
target_ulong next_pc;
/* check misaligned: */
- next_pc = ctx->pc + imm;
+ next_pc = ctx->base.pc_next + imm;
if (!riscv_has_ext(env, RVC)) {
if ((next_pc & 0x3) != 0) {
gen_exception_inst_addr_mis(ctx);
@@ -521,11 +519,11 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
}
}
if (rd != 0) {
- tcg_gen_movi_tl(cpu_gpr[rd], ctx->next_pc);
+ tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn);
}
- gen_goto_tb(ctx, 0, ctx->pc + imm); /* must use this for safety */
- ctx->is_jmp = DISAS_NORETURN;
+ gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */
+ ctx->base.is_jmp = DISAS_NORETURN;
}
static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
@@ -548,7 +546,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
}
if (rd != 0) {
- tcg_gen_movi_tl(cpu_gpr[rd], ctx->next_pc);
+ tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn);
}
tcg_gen_exit_tb(0);
@@ -556,7 +554,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_set_label(misaligned);
gen_exception_inst_addr_mis(ctx);
}
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
break;
default:
@@ -602,15 +600,15 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
tcg_temp_free(source1);
tcg_temp_free(source2);
- gen_goto_tb(ctx, 1, ctx->next_pc);
+ gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
gen_set_label(l); /* branch taken */
- if (!riscv_has_ext(env, RVC) && ((ctx->pc + bimm) & 0x3)) {
+ if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) {
/* misaligned */
gen_exception_inst_addr_mis(ctx);
} else {
- gen_goto_tb(ctx, 0, ctx->pc + bimm);
+ gen_goto_tb(ctx, 0, ctx->base.pc_next + bimm);
}
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
}
static void gen_load(DisasContext *ctx, uint32_t opc, int rd, int rs1,
@@ -836,7 +834,7 @@ static void gen_atomic(DisasContext *ctx, uint32_t opc,
if (rl) {
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
}
- if (tb_cflags(ctx->tb) & CF_PARALLEL) {
+ if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
l1 = gen_new_label();
gen_set_label(l1);
} else {
@@ -853,7 +851,7 @@ static void gen_atomic(DisasContext *ctx, uint32_t opc,
tcg_gen_qemu_ld_tl(dat, src1, ctx->mem_idx, mop);
tcg_gen_movcond_tl(cond, src2, dat, src2, dat, src2);
- if (tb_cflags(ctx->tb) & CF_PARALLEL) {
+ if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
/* Parallel context. Make this operation atomic by verifying
that the memory didn't change while we computed the result. */
tcg_gen_atomic_cmpxchg_tl(src2, src1, dat, src2, ctx->mem_idx, mop);
@@ -1317,7 +1315,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
rs1_pass = tcg_temp_new();
imm_rs1 = tcg_temp_new();
gen_get_gpr(source1, rs1);
- tcg_gen_movi_tl(cpu_pc, ctx->pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
tcg_gen_movi_tl(rs1_pass, rs1);
tcg_gen_movi_tl(csr_store, csr); /* copy into temp reg to feed to helper */
@@ -1338,12 +1336,12 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
/* always generates U-level ECALL, fixed in do_interrupt handler */
generate_exception(ctx, RISCV_EXCP_U_ECALL);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
break;
case 0x1: /* EBREAK */
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
break;
#ifndef CONFIG_USER_ONLY
case 0x002: /* URET */
@@ -1353,7 +1351,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
if (riscv_has_ext(env, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
} else {
gen_exception_illegal(ctx);
}
@@ -1364,13 +1362,13 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
case 0x302: /* MRET */
gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
break;
case 0x7b2: /* DRET */
gen_exception_illegal(ctx);
break;
case 0x105: /* WFI */
- tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
gen_helper_wfi(cpu_env);
break;
case 0x104: /* SFENCE.VM */
@@ -1411,9 +1409,9 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_io_end();
gen_set_gpr(rd, dest);
/* end tb since we may be changing priv modes, to get mmu_index right */
- tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
tcg_gen_exit_tb(0); /* no chaining */
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
break;
}
tcg_temp_free(source1);
@@ -1731,7 +1729,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
break; /* NOP */
}
tcg_gen_movi_tl(cpu_gpr[rd], (sextract64(ctx->opcode, 12, 20) << 12) +
- ctx->pc);
+ ctx->base.pc_next);
break;
case OPC_RISC_JAL:
imm = GET_JAL_IMM(ctx->opcode);
@@ -1804,9 +1802,9 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
if (ctx->opcode & 0x1000) {
/* FENCE_I is a no-op in QEMU,
* however we need to end the translation block */
- tcg_gen_movi_tl(cpu_pc, ctx->next_pc);
+ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
tcg_gen_exit_tb(0);
- ctx->is_jmp = DISAS_NORETURN;
+ ctx->base.is_jmp = DISAS_NORETURN;
} else {
/* FENCE is a full memory barrier. */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
@@ -1830,11 +1828,11 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
if (!riscv_has_ext(env, RVC)) {
gen_exception_illegal(ctx);
} else {
- ctx->next_pc = ctx->pc + 2;
+ ctx->pc_succ_insn = ctx->base.pc_next + 2;
decode_RV32_64C(env, ctx);
}
} else {
- ctx->next_pc = ctx->pc + 4;
+ ctx->pc_succ_insn = ctx->base.pc_next + 4;
decode_RV32_64G(env, ctx);
}
}
@@ -1843,26 +1841,26 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
{
CPURISCVState *env = cs->env_ptr;
DisasContext ctx;
- target_ulong pc_start;
target_ulong page_start;
int num_insns;
int max_insns;
- pc_start = tb->pc;
- page_start = pc_start & TARGET_PAGE_MASK;
- ctx.pc = pc_start;
+ ctx.base.pc_first = tb->pc;
+ ctx.base.pc_next = ctx.base.pc_first;
/* once we have GDB, the rest of the translate.c implementation should be
ready for singlestep */
- ctx.singlestep_enabled = cs->singlestep_enabled;
+ ctx.base.singlestep_enabled = cs->singlestep_enabled;
+ ctx.base.tb = tb;
+ ctx.base.is_jmp = DISAS_NEXT;
- ctx.tb = tb;
- ctx.is_jmp = DISAS_NEXT;
+ page_start = ctx.base.pc_first & TARGET_PAGE_MASK;
+ ctx.pc_succ_insn = ctx.base.pc_first;
ctx.flags = tb->flags;
ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK;
ctx.frm = -1; /* unknown rounding mode */
num_insns = 0;
- max_insns = tb->cflags & CF_COUNT_MASK;
+ max_insns = tb_cflags(ctx.base.tb) & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
@@ -1871,45 +1869,45 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
}
gen_tb_start(tb);
- while (ctx.is_jmp == DISAS_NEXT) {
- tcg_gen_insn_start(ctx.pc);
+ while (ctx.base.is_jmp == DISAS_NEXT) {
+ tcg_gen_insn_start(ctx.base.pc_next);
num_insns++;
- if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
- tcg_gen_movi_tl(cpu_pc, ctx.pc);
- ctx.is_jmp = DISAS_NORETURN;
+ if (unlikely(cpu_breakpoint_test(cs, ctx.base.pc_next, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_pc, ctx.base.pc_next);
+ ctx.base.is_jmp = DISAS_NORETURN;
gen_exception_debug();
/* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
the logic setting tb->size below does the right thing. */
- ctx.pc += 4;
+ ctx.base.pc_next += 4;
goto done_generating;
}
- if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb_cflags(ctx.base.tb) & CF_LAST_IO)) {
gen_io_start();
}
- ctx.opcode = cpu_ldl_code(env, ctx.pc);
+ ctx.opcode = cpu_ldl_code(env, ctx.base.pc_next);
decode_opc(env, &ctx);
- ctx.pc = ctx.next_pc;
+ ctx.base.pc_next = ctx.pc_succ_insn;
- if (ctx.is_jmp == DISAS_NEXT &&
+ if (ctx.base.is_jmp == DISAS_NEXT &&
(cs->singlestep_enabled ||
- ctx.pc - page_start >= TARGET_PAGE_SIZE ||
+ ctx.base.pc_next - page_start >= TARGET_PAGE_SIZE ||
tcg_op_buf_full() ||
num_insns >= max_insns ||
singlestep)) {
- ctx.is_jmp = DISAS_TOO_MANY;
+ ctx.base.is_jmp = DISAS_TOO_MANY;
}
}
- if (tb->cflags & CF_LAST_IO) {
+ if (tb_cflags(ctx.base.tb) & CF_LAST_IO) {
gen_io_end();
}
- switch (ctx.is_jmp) {
+ switch (ctx.base.is_jmp) {
case DISAS_TOO_MANY:
- tcg_gen_movi_tl(cpu_pc, ctx.pc);
+ tcg_gen_movi_tl(cpu_pc, ctx.base.pc_next);
if (cs->singlestep_enabled) {
gen_exception_debug();
} else {
@@ -1923,14 +1921,15 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
}
done_generating:
gen_tb_end(tb, num_insns);
- tb->size = ctx.pc - pc_start;
+ tb->size = ctx.base.pc_next - ctx.base.pc_first;
tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
- && qemu_log_in_addr_range(pc_start)) {
- qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, ctx.pc - pc_start);
+ && qemu_log_in_addr_range(ctx.base.pc_first)) {
+ qemu_log("IN: %s\n", lookup_symbol(ctx.base.pc_first));
+ log_target_disas(cs, ctx.base.pc_first,
+ ctx.base.pc_next - ctx.base.pc_first);
qemu_log("\n");
}
#endif
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v1 5/6] target/riscv: convert to TranslatorOps
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
` (3 preceding siblings ...)
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 4/6] target/riscv: convert to DisasContextBase Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 6/6] target/riscv: add misa to DisasContext Michael Clark
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel
Cc: patches, Emilio G. Cota, Michael Clark, Palmer Dabbelt,
Sagar Karandikar, Bastian Koppelmann
From: "Emilio G. Cota" <cota@braap.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Cc: Michael Clark <mjc@sifive.com>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
target/riscv/translate.c | 158 ++++++++++++++++++++++++-----------------------
1 file changed, 80 insertions(+), 78 deletions(-)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 68979abfd7ed..1788668c6f28 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1837,78 +1837,71 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
}
}
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
- CPURISCVState *env = cs->env_ptr;
- DisasContext ctx;
- target_ulong page_start;
- int num_insns;
- int max_insns;
-
- ctx.base.pc_first = tb->pc;
- ctx.base.pc_next = ctx.base.pc_first;
- /* once we have GDB, the rest of the translate.c implementation should be
- ready for singlestep */
- ctx.base.singlestep_enabled = cs->singlestep_enabled;
- ctx.base.tb = tb;
- ctx.base.is_jmp = DISAS_NEXT;
-
- page_start = ctx.base.pc_first & TARGET_PAGE_MASK;
- ctx.pc_succ_insn = ctx.base.pc_first;
- ctx.flags = tb->flags;
- ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK;
- ctx.frm = -1; /* unknown rounding mode */
-
- num_insns = 0;
- max_insns = tb_cflags(ctx.base.tb) & CF_COUNT_MASK;
- if (max_insns == 0) {
- max_insns = CF_COUNT_MASK;
- }
- if (max_insns > TCG_MAX_INSNS) {
- max_insns = TCG_MAX_INSNS;
- }
- gen_tb_start(tb);
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
- while (ctx.base.is_jmp == DISAS_NEXT) {
- tcg_gen_insn_start(ctx.base.pc_next);
- num_insns++;
+ ctx->pc_succ_insn = ctx->base.pc_first;
+ ctx->flags = ctx->base.tb->flags;
+ ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
+ ctx->frm = -1; /* unknown rounding mode */
+}
- if (unlikely(cpu_breakpoint_test(cs, ctx.base.pc_next, BP_ANY))) {
- tcg_gen_movi_tl(cpu_pc, ctx.base.pc_next);
- ctx.base.is_jmp = DISAS_NORETURN;
- gen_exception_debug();
- /* The address covered by the breakpoint must be included in
- [tb->pc, tb->pc + tb->size) in order to for it to be
- properly cleared -- thus we increment the PC here so that
- the logic setting tb->size below does the right thing. */
- ctx.base.pc_next += 4;
- goto done_generating;
- }
+static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
- if (num_insns == max_insns && (tb_cflags(ctx.base.tb) & CF_LAST_IO)) {
- gen_io_start();
- }
+static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+ const CPUBreakpoint *bp)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ gen_exception_debug();
+ /* The address covered by the breakpoint must be included in
+ [tb->pc, tb->pc + tb->size) in order to for it to be
+ properly cleared -- thus we increment the PC here so that
+ the logic setting tb->size below does the right thing. */
+ ctx->base.pc_next += 4;
+ return true;
+}
+
+
+static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+ CPURISCVState *env = cpu->env_ptr;
- ctx.opcode = cpu_ldl_code(env, ctx.base.pc_next);
- decode_opc(env, &ctx);
- ctx.base.pc_next = ctx.pc_succ_insn;
-
- if (ctx.base.is_jmp == DISAS_NEXT &&
- (cs->singlestep_enabled ||
- ctx.base.pc_next - page_start >= TARGET_PAGE_SIZE ||
- tcg_op_buf_full() ||
- num_insns >= max_insns ||
- singlestep)) {
- ctx.base.is_jmp = DISAS_TOO_MANY;
+ ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
+ decode_opc(env, ctx);
+ ctx->base.pc_next = ctx->pc_succ_insn;
+
+ if (ctx->base.is_jmp == DISAS_NEXT) {
+ target_ulong page_start;
+
+ page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+ if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
+ ctx->base.is_jmp = DISAS_TOO_MANY;
}
}
- if (tb_cflags(ctx.base.tb) & CF_LAST_IO) {
- gen_io_end();
- }
- switch (ctx.base.is_jmp) {
+}
+
+static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ switch (ctx->base.is_jmp) {
case DISAS_TOO_MANY:
- tcg_gen_movi_tl(cpu_pc, ctx.base.pc_next);
- if (cs->singlestep_enabled) {
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+ if (ctx->base.singlestep_enabled) {
gen_exception_debug();
} else {
tcg_gen_exit_tb(0);
@@ -1919,20 +1912,29 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
default:
g_assert_not_reached();
}
-done_generating:
- gen_tb_end(tb, num_insns);
- tb->size = ctx.base.pc_next - ctx.base.pc_first;
- tb->icount = num_insns;
-
-#ifdef DEBUG_DISAS
- if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
- && qemu_log_in_addr_range(ctx.base.pc_first)) {
- qemu_log("IN: %s\n", lookup_symbol(ctx.base.pc_first));
- log_target_disas(cs, ctx.base.pc_first,
- ctx.base.pc_next - ctx.base.pc_first);
- qemu_log("\n");
- }
-#endif
+}
+
+static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
+{
+ qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+ log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
+}
+
+static const TranslatorOps riscv_tr_ops = {
+ .init_disas_context = riscv_tr_init_disas_context,
+ .tb_start = riscv_tr_tb_start,
+ .insn_start = riscv_tr_insn_start,
+ .breakpoint_check = riscv_tr_breakpoint_check,
+ .translate_insn = riscv_tr_translate_insn,
+ .tb_stop = riscv_tr_tb_stop,
+ .disas_log = riscv_tr_disas_log,
+};
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+{
+ DisasContext ctx;
+
+ translator_loop(&riscv_tr_ops, &ctx.base, cs, tb);
}
void riscv_translate_init(void)
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v1 6/6] target/riscv: add misa to DisasContext
2018-05-09 10:11 [Qemu-devel] [PATCH v1 0/6] Translation loop conversion for riscv Michael Clark
` (4 preceding siblings ...)
2018-05-09 10:11 ` [Qemu-devel] [PATCH v1 5/6] target/riscv: convert to TranslatorOps Michael Clark
@ 2018-05-09 10:11 ` Michael Clark
5 siblings, 0 replies; 7+ messages in thread
From: Michael Clark @ 2018-05-09 10:11 UTC (permalink / raw)
To: qemu-devel
Cc: patches, Michael Clark, Palmer Dabbelt, Sagar Karandikar,
Bastian Koppelmann, Alistair Francis, Emilio G . Cota
gen methods should access state from DisasContext. Add misa
field to the DisasContext struct and remove CPURISCVState
argument from all gen methods.
[Rebased against github.com/cota/qemu/tree/trloop-conv-v3]
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Cc: Emilio G. Cota <cota@braap.org>
Signed-off-by: Michael Clark <mjc@sifive.com>
---
target/riscv/translate.c | 77 ++++++++++++++++++++++++++----------------------
1 file changed, 42 insertions(+), 35 deletions(-)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 1788668c6f28..507d74186293 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -45,6 +45,7 @@ typedef struct DisasContext {
target_ulong pc_succ_insn;
uint32_t opcode;
uint32_t flags;
+ uint32_t misa;
uint32_t mem_idx;
/* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status. Or -1 for
@@ -74,6 +75,11 @@ static const int tcg_memop_lookup[8] = {
#define CASE_OP_32_64(X) case X
#endif
+static inline bool has_ext(DisasContext *ctx, uint32_t ext)
+{
+ return ctx->misa & ext;
+}
+
static void generate_exception(DisasContext *ctx, int excp)
{
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -505,14 +511,13 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd,
tcg_temp_free(source1);
}
-static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
- target_ulong imm)
+static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
{
target_ulong next_pc;
/* check misaligned: */
next_pc = ctx->base.pc_next + imm;
- if (!riscv_has_ext(env, RVC)) {
+ if (!has_ext(ctx, RVC)) {
if ((next_pc & 0x3) != 0) {
gen_exception_inst_addr_mis(ctx);
return;
@@ -526,8 +531,8 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd,
ctx->base.is_jmp = DISAS_NORETURN;
}
-static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rd, int rs1, target_long imm)
+static void gen_jalr(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+ target_long imm)
{
/* no chaining with JALR */
TCGLabel *misaligned = NULL;
@@ -539,7 +544,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
tcg_gen_addi_tl(cpu_pc, cpu_pc, imm);
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();
tcg_gen_andi_tl(t0, cpu_pc, 0x2);
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
@@ -564,8 +569,8 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
tcg_temp_free(t0);
}
-static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rs1, int rs2, target_long bimm)
+static void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2,
+ target_long bimm)
{
TCGLabel *l = gen_new_label();
TCGv source1, source2;
@@ -602,7 +607,7 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
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 */
gen_exception_inst_addr_mis(ctx);
} else {
@@ -1305,8 +1310,8 @@ static void gen_fp_arith(DisasContext *ctx, uint32_t opc, int rd,
}
}
-static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
- int rd, int rs1, int csr)
+static void gen_system(DisasContext *ctx, uint32_t opc, int rd, int rs1,
+ int csr)
{
TCGv source1, csr_store, dest, rs1_pass, imm_rs1;
source1 = tcg_temp_new();
@@ -1348,7 +1353,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_exception_illegal(ctx);
break;
case 0x102: /* SRET */
- if (riscv_has_ext(env, RVS)) {
+ if (has_ext(ctx, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
tcg_gen_exit_tb(0); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
@@ -1489,7 +1494,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 rd_rs1 = GET_C_RS1(ctx->opcode);
@@ -1509,7 +1514,7 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
GET_C_IMM(ctx->opcode));
#else
/* 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
break;
case 2:
@@ -1588,22 +1593,22 @@ static void decode_RV32_64C1(CPURISCVState *env, DisasContext *ctx)
break;
case 5:
/* 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;
case 6:
/* C.BEQZ -> beq rs1', x0, offset[8:1]*/
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;
case 7:
/* C.BNEZ -> bne rs1', x0, offset[8:1]*/
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;
}
}
-static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64C2(DisasContext *ctx)
{
uint8_t rd, rs2;
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
@@ -1637,7 +1642,7 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
if (extract32(ctx->opcode, 12, 1) == 0) {
if (rs2 == 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 {
/* C.MV -> add rd, x0, rs2 */
gen_arith(ctx, OPC_RISC_ADD, rd, 0, rs2);
@@ -1645,11 +1650,11 @@ static void decode_RV32_64C2(CPURISCVState *env, DisasContext *ctx)
} else {
if (rd == 0) {
/* C.EBREAK -> ebreak*/
- gen_system(env, ctx, OPC_RISC_ECALL, 0, 0, 0x1);
+ gen_system(ctx, OPC_RISC_ECALL, 0, 0, 0x1);
} else {
if (rs2 == 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 {
/* C.ADD -> add rd, rd, rs2 */
gen_arith(ctx, OPC_RISC_ADD, rd, rd, rs2);
@@ -1681,7 +1686,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);
@@ -1690,15 +1695,15 @@ static void decode_RV32_64C(CPURISCVState *env, DisasContext *ctx)
decode_RV32_64C0(ctx);
break;
case 1:
- decode_RV32_64C1(env, ctx);
+ decode_RV32_64C1(ctx);
break;
case 2:
- decode_RV32_64C2(env, ctx);
+ decode_RV32_64C2(ctx);
break;
}
}
-static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
+static void decode_RV32_64G(DisasContext *ctx)
{
int rs1;
int rs2;
@@ -1733,13 +1738,13 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
break;
case OPC_RISC_JAL:
imm = GET_JAL_IMM(ctx->opcode);
- gen_jal(env, ctx, rd, imm);
+ gen_jal(ctx, rd, imm);
break;
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;
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));
break;
case OPC_RISC_LOAD:
@@ -1812,7 +1817,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx)
#endif
break;
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);
break;
default:
@@ -1821,28 +1826,30 @@ 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 */
if (extract32(ctx->opcode, 0, 2) != 3) {
- if (!riscv_has_ext(env, RVC)) {
+ if (!has_ext(ctx, RVC)) {
gen_exception_illegal(ctx);
} else {
ctx->pc_succ_insn = ctx->base.pc_next + 2;
- decode_RV32_64C(env, ctx);
+ decode_RV32_64C(ctx);
}
} else {
ctx->pc_succ_insn = ctx->base.pc_next + 4;
- decode_RV32_64G(env, ctx);
+ decode_RV32_64G(ctx);
}
}
-static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
+static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
+ CPURISCVState *env = cpu->env_ptr;
ctx->pc_succ_insn = ctx->base.pc_first;
ctx->flags = ctx->base.tb->flags;
+ ctx->misa = env->misa;
ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
ctx->frm = -1; /* unknown rounding mode */
}
@@ -1881,7 +1888,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
CPURISCVState *env = cpu->env_ptr;
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;
if (ctx->base.is_jmp == DISAS_NEXT) {
--
2.7.0
^ permalink raw reply related [flat|nested] 7+ messages in thread