target/riscv: Move cpu_get_tb_cpu_state to tcg-cpu.c
This function is only relevant to tcg. Move it to a tcg-specific file. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
9da84372c4
commit
5b1c93be57
2 changed files with 98 additions and 97 deletions
|
|
@ -135,103 +135,6 @@ bool riscv_env_smode_dbltrp_enabled(CPURISCVState *env, bool virt)
|
|||
#endif
|
||||
}
|
||||
|
||||
void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *pflags)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
RISCVExtStatus fs, vs;
|
||||
uint32_t flags = 0;
|
||||
bool pm_signext = riscv_cpu_virt_mem_enabled(env);
|
||||
|
||||
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
|
||||
*cs_base = 0;
|
||||
|
||||
if (cpu->cfg.ext_zve32x) {
|
||||
/*
|
||||
* If env->vl equals to VLMAX, we can use generic vector operation
|
||||
* expanders (GVEC) to accerlate the vector operations.
|
||||
* However, as LMUL could be a fractional number. The maximum
|
||||
* vector size can be operated might be less than 8 bytes,
|
||||
* which is not supported by GVEC. So we set vl_eq_vlmax flag to true
|
||||
* only when maxsz >= 8 bytes.
|
||||
*/
|
||||
|
||||
/* lmul encoded as in DisasContext::lmul */
|
||||
int8_t lmul = sextract32(FIELD_EX64(env->vtype, VTYPE, VLMUL), 0, 3);
|
||||
uint32_t vsew = FIELD_EX64(env->vtype, VTYPE, VSEW);
|
||||
uint32_t vlmax = vext_get_vlmax(cpu->cfg.vlenb, vsew, lmul);
|
||||
uint32_t maxsz = vlmax << vsew;
|
||||
bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
|
||||
(maxsz >= 8);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, SEW, vsew);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
|
||||
FIELD_EX64(env->vtype, VTYPE, VLMUL));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VTA,
|
||||
FIELD_EX64(env->vtype, VTYPE, VTA));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VMA,
|
||||
FIELD_EX64(env->vtype, VTYPE, VMA));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
|
||||
} else {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
|
||||
}
|
||||
|
||||
if (cpu_get_fcfien(env)) {
|
||||
/*
|
||||
* For Forward CFI, only the expectation of a lpad at
|
||||
* the start of the block is tracked via env->elp. env->elp
|
||||
* is turned on during jalr translation.
|
||||
*/
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FCFI_LP_EXPECTED, env->elp);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FCFI_ENABLED, 1);
|
||||
}
|
||||
|
||||
if (cpu_get_bcfien(env)) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, BCFI_ENABLED, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
fs = EXT_STATUS_DIRTY;
|
||||
vs = EXT_STATUS_DIRTY;
|
||||
#else
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
|
||||
|
||||
flags |= riscv_env_mmu_index(env, 0);
|
||||
fs = get_field(env->mstatus, MSTATUS_FS);
|
||||
vs = get_field(env->mstatus, MSTATUS_VS);
|
||||
|
||||
if (env->virt_enabled) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
|
||||
/*
|
||||
* Merge DISABLED and !DIRTY states using MIN.
|
||||
* We will set both fields when dirtying.
|
||||
*/
|
||||
fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
|
||||
vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
|
||||
}
|
||||
|
||||
/* With Zfinx, floating point is enabled/disabled by Smstateen. */
|
||||
if (!riscv_has_ext(env, RVF)) {
|
||||
fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
|
||||
? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
|
||||
}
|
||||
|
||||
if (cpu->cfg.debug && !icount_enabled()) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
|
||||
}
|
||||
#endif
|
||||
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
|
||||
|
||||
*pflags = flags;
|
||||
}
|
||||
|
||||
RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/boards.h"
|
||||
#include "system/tcg.h"
|
||||
#include "exec/icount.h"
|
||||
#endif
|
||||
|
||||
/* Hash that stores user set extensions */
|
||||
|
|
@ -97,6 +98,103 @@ static int riscv_cpu_mmu_index(CPUState *cs, bool ifetch)
|
|||
return riscv_env_mmu_index(cpu_env(cs), ifetch);
|
||||
}
|
||||
|
||||
void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *pflags)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
RISCVExtStatus fs, vs;
|
||||
uint32_t flags = 0;
|
||||
bool pm_signext = riscv_cpu_virt_mem_enabled(env);
|
||||
|
||||
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
|
||||
*cs_base = 0;
|
||||
|
||||
if (cpu->cfg.ext_zve32x) {
|
||||
/*
|
||||
* If env->vl equals to VLMAX, we can use generic vector operation
|
||||
* expanders (GVEC) to accerlate the vector operations.
|
||||
* However, as LMUL could be a fractional number. The maximum
|
||||
* vector size can be operated might be less than 8 bytes,
|
||||
* which is not supported by GVEC. So we set vl_eq_vlmax flag to true
|
||||
* only when maxsz >= 8 bytes.
|
||||
*/
|
||||
|
||||
/* lmul encoded as in DisasContext::lmul */
|
||||
int8_t lmul = sextract32(FIELD_EX64(env->vtype, VTYPE, VLMUL), 0, 3);
|
||||
uint32_t vsew = FIELD_EX64(env->vtype, VTYPE, VSEW);
|
||||
uint32_t vlmax = vext_get_vlmax(cpu->cfg.vlenb, vsew, lmul);
|
||||
uint32_t maxsz = vlmax << vsew;
|
||||
bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) &&
|
||||
(maxsz >= 8);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, SEW, vsew);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
|
||||
FIELD_EX64(env->vtype, VTYPE, VLMUL));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VTA,
|
||||
FIELD_EX64(env->vtype, VTYPE, VTA));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VMA,
|
||||
FIELD_EX64(env->vtype, VTYPE, VMA));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == 0);
|
||||
} else {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
|
||||
}
|
||||
|
||||
if (cpu_get_fcfien(env)) {
|
||||
/*
|
||||
* For Forward CFI, only the expectation of a lpad at
|
||||
* the start of the block is tracked via env->elp. env->elp
|
||||
* is turned on during jalr translation.
|
||||
*/
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FCFI_LP_EXPECTED, env->elp);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FCFI_ENABLED, 1);
|
||||
}
|
||||
|
||||
if (cpu_get_bcfien(env)) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, BCFI_ENABLED, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
fs = EXT_STATUS_DIRTY;
|
||||
vs = EXT_STATUS_DIRTY;
|
||||
#else
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
|
||||
|
||||
flags |= riscv_env_mmu_index(env, 0);
|
||||
fs = get_field(env->mstatus, MSTATUS_FS);
|
||||
vs = get_field(env->mstatus, MSTATUS_VS);
|
||||
|
||||
if (env->virt_enabled) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1);
|
||||
/*
|
||||
* Merge DISABLED and !DIRTY states using MIN.
|
||||
* We will set both fields when dirtying.
|
||||
*/
|
||||
fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS));
|
||||
vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
|
||||
}
|
||||
|
||||
/* With Zfinx, floating point is enabled/disabled by Smstateen. */
|
||||
if (!riscv_has_ext(env, RVF)) {
|
||||
fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE)
|
||||
? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
|
||||
}
|
||||
|
||||
if (cpu->cfg.debug && !icount_enabled()) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
|
||||
}
|
||||
#endif
|
||||
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, FS, fs);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
|
||||
|
||||
*pflags = flags;
|
||||
}
|
||||
|
||||
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue