@@ -237,6 +237,8 @@ struct Nios2CPU {
CPUNios2State env;
bool mmu_present;
+ bool eic_present;
+
uint32_t pid_num_bits;
uint32_t tlb_num_ways;
uint32_t tlb_num_entries;
@@ -22,6 +22,8 @@ DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(eret, noreturn, env, i32)
+DEF_HELPER_FLAGS_2(rdprs, TCG_CALL_NO_WG, i32, env, i32)
+DEF_HELPER_3(wrprs, void, env, i32, i32)
DEF_HELPER_2(mmu_write_tlbacc, void, env, i32)
DEF_HELPER_2(mmu_write_tlbmisc, void, env, i32)
DEF_HELPER_2(mmu_write_pteaddr, void, env, i32)
@@ -38,4 +38,16 @@ void helper_eret(CPUNios2State *env, uint32_t new_pc)
env->pc = new_pc;
cpu_loop_exit(env_cpu(env));
}
+
+uint32_t helper_rdprs(CPUNios2State *env, uint32_t regno)
+{
+ unsigned prs = FIELD_EX32(env->status, CR_STATUS, PRS);
+ return env->shadow_regs[prs][regno];
+}
+
+void helper_wrprs(CPUNios2State *env, uint32_t regno, uint32_t val)
+{
+ unsigned prs = FIELD_EX32(env->status, CR_STATUS, PRS);
+ env->shadow_regs[prs][regno] = val;
+}
#endif /* !CONFIG_USER_ONLY */
@@ -103,6 +103,7 @@ typedef struct DisasContext {
bool crs0;
TCGv sink;
const ControlRegState *cr_state;
+ bool eic_present;
} DisasContext;
static TCGv cpu_R[NUM_GP_REGS];
@@ -305,6 +306,27 @@ gen_i_math_logic(andhi, andi, 0, instr.imm16.u << 16)
gen_i_math_logic(orhi , ori, 1, instr.imm16.u << 16)
gen_i_math_logic(xorhi, xori, 1, instr.imm16.u << 16)
+/* rB <- prs.rA + sigma(IMM16) */
+static void rdprs(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+ if (!dc->eic_present) {
+ t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+ return;
+ }
+ if (!gen_check_supervisor(dc)) {
+ return;
+ }
+
+#ifdef CONFIG_USER_ONLY
+ g_assert_not_reached();
+#else
+ I_TYPE(instr, code);
+ TCGv dest = dest_gpr(dc, instr.b);
+ gen_helper_rdprs(dest, cpu_env, tcg_constant_i32(instr.a));
+ tcg_gen_addi_tl(dest, dest, instr.imm16.s);
+#endif
+}
+
/* Prototype only, defined below */
static void handle_r_type_instr(DisasContext *dc, uint32_t code,
uint32_t flags);
@@ -366,7 +388,7 @@ static const Nios2Instruction i_type_instructions[] = {
INSTRUCTION_FLG(gen_stx, MO_SL), /* stwio */
INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU), /* bltu */
INSTRUCTION_FLG(gen_ldx, MO_UL), /* ldwio */
- INSTRUCTION_UNIMPLEMENTED(), /* rdprs */
+ INSTRUCTION(rdprs), /* rdprs */
INSTRUCTION_ILLEGAL(),
INSTRUCTION_FLG(handle_r_type_instr, 0), /* R-Type */
INSTRUCTION_NOP(), /* flushd */
@@ -552,6 +574,26 @@ static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
#endif
}
+/* prs.rC <- rA */
+static void wrprs(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+ if (!dc->eic_present) {
+ t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+ return;
+ }
+ if (!gen_check_supervisor(dc)) {
+ return;
+ }
+
+#ifdef CONFIG_USER_ONLY
+ g_assert_not_reached();
+#else
+ R_TYPE(instr, code);
+ gen_helper_wrprs(cpu_env, tcg_constant_i32(instr.c),
+ load_gpr(dc, instr.a));
+#endif
+}
+
/* Comparison instructions */
static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
{
@@ -690,7 +732,7 @@ static const Nios2Instruction r_type_instructions[] = {
INSTRUCTION_ILLEGAL(),
INSTRUCTION(slli), /* slli */
INSTRUCTION(sll), /* sll */
- INSTRUCTION_UNIMPLEMENTED(), /* wrprs */
+ INSTRUCTION(wrprs), /* wrprs */
INSTRUCTION_ILLEGAL(),
INSTRUCTION(or), /* or */
INSTRUCTION(mulxsu), /* mulxsu */
@@ -791,6 +833,7 @@ static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->mem_idx = cpu_mmu_index(env, false);
dc->cr_state = cpu->cr_state;
+ dc->eic_present = cpu->eic_present;
dc->crs0 = FIELD_EX32(dc->base.tb->flags, TBFLAGS, CRS0);
/* Bound the number of insns to execute to those left on the page. */
Implement these out of line, so that tcg global temps (aka the architectural registers) are synced back to storage as required. This makes sure that we get the proper results when status.PRS == status.CRS. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/nios2/cpu.h | 2 ++ target/nios2/helper.h | 2 ++ target/nios2/op_helper.c | 12 ++++++++++ target/nios2/translate.c | 47 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 2 deletions(-)