Hexagon (target/hexagon) Add overrides for allocframe/deallocframe

These instructions have implicit writes to registers, so we don't
want them to be helpers when idef-parser is off.

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230427230012.3800327-5-tsimpson@quicinc.com>
This commit is contained in:
Taylor Simpson 2023-04-27 15:59:55 -07:00
parent 17fda3c2d4
commit 085b6700f0
2 changed files with 79 additions and 0 deletions

View File

@ -500,6 +500,38 @@
#define fGEN_TCG_Y2_icinva(SHORTCODE) \
do { RsV = RsV; } while (0)
/*
* allocframe(#uiV)
* RxV == r29
*/
#define fGEN_TCG_S2_allocframe(SHORTCODE) \
gen_allocframe(ctx, RxV, uiV)
/* sub-instruction version (no RxV, so handle it manually) */
#define fGEN_TCG_SS2_allocframe(SHORTCODE) \
do { \
TCGv r29 = tcg_temp_new(); \
tcg_gen_mov_tl(r29, hex_gpr[HEX_REG_SP]); \
gen_allocframe(ctx, r29, uiV); \
gen_log_reg_write(ctx, HEX_REG_SP, r29); \
} while (0)
/*
* Rdd32 = deallocframe(Rs32):raw
* RddV == r31:30
* RsV == r30
*/
#define fGEN_TCG_L2_deallocframe(SHORTCODE) \
gen_deallocframe(ctx, RddV, RsV)
/* sub-instruction version (no RddV/RsV, so handle it manually) */
#define fGEN_TCG_SL2_deallocframe(SHORTCODE) \
do { \
TCGv_i64 r31_30 = tcg_temp_new_i64(); \
gen_deallocframe(ctx, r31_30, hex_gpr[HEX_REG_FP]); \
gen_log_reg_write_pair(ctx, HEX_REG_FP, r31_30); \
} while (0)
/*
* dealloc_return
* Assembler mapped to

View File

@ -709,6 +709,18 @@ static void gen_cond_callr(DisasContext *ctx,
gen_set_label(skip);
}
#ifndef CONFIG_HEXAGON_IDEF_PARSER
/* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */
static TCGv_i64 gen_frame_scramble(void)
{
TCGv_i64 frame = tcg_temp_new_i64();
TCGv tmp = tcg_temp_new();
tcg_gen_xor_tl(tmp, hex_gpr[HEX_REG_LR], hex_gpr[HEX_REG_FRAMEKEY]);
tcg_gen_concat_i32_i64(frame, hex_gpr[HEX_REG_FP], tmp);
return frame;
}
#endif
/* frame ^= (int64_t)FRAMEKEY << 32 */
static void gen_frame_unscramble(TCGv_i64 frame)
{
@ -725,6 +737,41 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
}
#ifndef CONFIG_HEXAGON_IDEF_PARSER
/* Stack overflow check */
static void gen_framecheck(TCGv EA, int framesize)
{
/* Not modelled in linux-user mode */
/* Placeholder for system mode */
#ifndef CONFIG_USER_ONLY
g_assert_not_reached();
#endif
}
static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize)
{
TCGv r30 = tcg_temp_new();
TCGv_i64 frame;
tcg_gen_addi_tl(r30, r29, -8);
frame = gen_frame_scramble();
gen_store8(cpu_env, r30, frame, ctx->insn->slot);
gen_log_reg_write(ctx, HEX_REG_FP, r30);
gen_framecheck(r30, framesize);
tcg_gen_subi_tl(r29, r30, framesize);
}
static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30)
{
TCGv r29 = tcg_temp_new();
TCGv_i64 frame = tcg_temp_new_i64();
gen_load_frame(ctx, frame, r30);
gen_frame_unscramble(frame);
tcg_gen_mov_i64(r31_30, frame);
tcg_gen_addi_tl(r29, r30, 8);
gen_log_reg_write(ctx, HEX_REG_SP, r29);
}
#endif
static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
{
/*