diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 35e9036288..f4a353958f 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -545,6 +545,10 @@ static void gen_start_packet(DisasContext *ctx) ctx->reg_log_idx = 0; bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS); bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS); +#ifndef CONFIG_USER_ONLY + ctx->greg_log_idx = 0; + ctx->sreg_log_idx = 0; +#endif ctx->preg_log_idx = 0; bitmap_zero(ctx->pregs_written, NUM_PREGS); ctx->future_vregs_idx = 0; @@ -577,6 +581,25 @@ static void gen_start_packet(DisasContext *ctx) * gen phase, so clear it again. */ bitmap_zero(ctx->pregs_written, NUM_PREGS); +#ifndef CONFIG_USER_ONLY + for (i = 0; i < HEX_SREG_GLB_START; i++) { + ctx->t_sreg_new_value[i] = NULL; + } + for (i = 0; i < ctx->sreg_log_idx; i++) { + int reg_num = ctx->sreg_log[i]; + if (reg_num < HEX_SREG_GLB_START && + (ctx->need_commit || reg_num == HEX_SREG_SSR)) { + ctx->t_sreg_new_value[reg_num] = tcg_temp_new(); + } + } + for (i = 0; i < NUM_GREGS; i++) { + ctx->greg_new_value[i] = NULL; + } + for (i = 0; i < ctx->greg_log_idx; i++) { + int reg_num = ctx->greg_log[i]; + ctx->greg_new_value[reg_num] = tcg_temp_new(); + } +#endif /* Initialize the runtime state for packet semantics */ if (need_slot_cancelled(&ctx->pkt)) { @@ -734,6 +757,50 @@ static void gen_reg_writes(DisasContext *ctx) } } +#ifndef CONFIG_USER_ONLY +static void gen_greg_writes(DisasContext *ctx) +{ + int i; + + for (i = 0; i < ctx->greg_log_idx; i++) { + int reg_num = ctx->greg_log[i]; + + tcg_gen_mov_tl(hex_greg[reg_num], ctx->greg_new_value[reg_num]); + } +} + + +static void gen_sreg_writes(DisasContext *ctx) +{ + int i; + + TCGv_i32 old_reg = tcg_temp_new_i32(); + for (i = 0; i < ctx->sreg_log_idx; i++) { + int reg_num = ctx->sreg_log[i]; + + if (reg_num == HEX_SREG_SSR) { + tcg_gen_mov_tl(old_reg, hex_t_sreg[reg_num]); + tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]); + gen_helper_modify_ssr(tcg_env, ctx->t_sreg_new_value[reg_num], + old_reg); + } else if ((reg_num == HEX_SREG_STID) || + (reg_num == HEX_SREG_IMASK) || + (reg_num == HEX_SREG_IPENDAD)) { + if (ctx->need_commit && reg_num < HEX_SREG_GLB_START) { + tcg_gen_mov_tl(hex_t_sreg[reg_num], + ctx->t_sreg_new_value[reg_num]); + } + gen_helper_pending_interrupt(tcg_env); + } else if ((reg_num == HEX_SREG_BESTWAIT) || + (reg_num == HEX_SREG_SCHEDCFG)) { + gen_helper_resched(tcg_env); + } else if (ctx->need_commit && reg_num < HEX_SREG_GLB_START) { + tcg_gen_mov_tl(hex_t_sreg[reg_num], ctx->t_sreg_new_value[reg_num]); + } + } +} +#endif + static void gen_pred_writes(DisasContext *ctx) { /* Early exit if not needed or the log is empty */ @@ -1030,6 +1097,10 @@ static void gen_commit_packet(DisasContext *ctx) process_store_log(ctx); gen_reg_writes(ctx); +#ifndef CONFIG_USER_ONLY + gen_greg_writes(ctx); + gen_sreg_writes(ctx); +#endif gen_pred_writes(ctx); if (ctx->pkt.pkt_has_hvx) { gen_commit_hvx(ctx); @@ -1242,6 +1313,8 @@ void hexagon_translate_init(void) hex_llsc_val_i64 = tcg_global_mem_new_i64(tcg_env, offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64"); #ifndef CONFIG_USER_ONLY + hex_cause_code = tcg_global_mem_new_i32(tcg_env, + offsetof(CPUHexagonState, cause_code), "cause_code"); hex_cycle_count = tcg_global_mem_new_i64(tcg_env, offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count"); #endif @@ -1282,8 +1355,4 @@ void hexagon_translate_init(void) offsetof(CPUHexagonState, vstore_pending[i]), vstore_pending_names[i]); } -#ifndef CONFIG_USER_ONLY - hex_cause_code = tcg_global_mem_new(tcg_env, - offsetof(CPUHexagonState, cause_code), "cause_code"); -#endif } diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h index fea88cb2db..0a7f37d584 100644 --- a/target/hexagon/translate.h +++ b/target/hexagon/translate.h @@ -46,7 +46,7 @@ typedef struct DisasContext { int greg_log_idx; int sreg_log[SREG_WRITES_MAX]; int sreg_log_idx; - TCGv_i32 t_sreg_new_value[NUM_SREGS]; + TCGv_i32 t_sreg_new_value[HEX_SREG_GLB_START]; TCGv_i32 greg_new_value[NUM_GREGS]; #endif int preg_log[PRED_WRITES_MAX];