> -----Original Message-----
> From: Matheus Bernardino (QUIC) <quic_mathb...@quicinc.com>
> Sent: Friday, April 26, 2024 1:16 PM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bc...@quicinc.com>; Sid Manning <sidn...@quicinc.com>;
> a...@rev.ng; a...@rev.ng; ltaylorsimp...@gmail.com
> Subject: [PATCH] Hexagon: add PC alignment check and exception
> 
> The Hexagon Programmer's Reference Manual says that the exception 0x1e
> should be raised upon an unaligned program counter. Let's implement that
> and also add tests for both the most common case as well as packets with
> multiple change-of-flow instructions.
> 
> Signed-off-by: Matheus Tavares Bernardino <quic_mathb...@quicinc.com>

Reviewed-by: Brian Cain <bc...@quicinc.com>

> ---
>  target/hexagon/cpu_bits.h                  |  1 +
>  target/hexagon/translate.h                 |  2 ++
>  target/hexagon/genptr.c                    | 21 ++++++++++++++++-----
>  target/hexagon/translate.c                 |  2 +-
>  tests/tcg/hexagon/Makefile.target          | 13 +++++++++++++
>  tests/tcg/hexagon/unaligned_pc.S           | 10 ++++++++++
>  tests/tcg/hexagon/unaligned_pc_multi_cof.S | 13 +++++++++++++
>  7 files changed, 56 insertions(+), 6 deletions(-)
>  create mode 100644 tests/tcg/hexagon/unaligned_pc.S
>  create mode 100644 tests/tcg/hexagon/unaligned_pc_multi_cof.S
> 
> diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
> index 96fef71729..d6900c8bda 100644
> --- a/target/hexagon/cpu_bits.h
> +++ b/target/hexagon/cpu_bits.h
> @@ -23,6 +23,7 @@
>  #define HEX_EXCP_FETCH_NO_UPAGE  0x012
>  #define HEX_EXCP_INVALID_PACKET  0x015
>  #define HEX_EXCP_INVALID_OPCODE  0x015
> +#define HEX_EXCP_PC_NOT_ALIGNED  0x01e
>  #define HEX_EXCP_PRIV_NO_UREAD   0x024
>  #define HEX_EXCP_PRIV_NO_UWRITE  0x025
> 
> diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
> index 4dd59c6726..daf11eb584 100644
> --- a/target/hexagon/translate.h
> +++ b/target/hexagon/translate.h
> @@ -75,6 +75,8 @@ typedef struct DisasContext {
>      TCGv dczero_addr;
>  } DisasContext;
> 
> +void gen_exception_end_tb(DisasContext *ctx, int excp);
> +
>  static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
>  {
>      if (!test_bit(pnum, ctx->pregs_written)) {
> diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
> index dbae6c570a..c96edd9379 100644
> --- a/target/hexagon/genptr.c
> +++ b/target/hexagon/genptr.c
> @@ -473,6 +473,7 @@ static void gen_write_new_pc_addr(DisasContext
> *ctx, TCGv addr,
>                                    TCGCond cond, TCGv pred)
>  {
>      TCGLabel *pred_false = NULL;
> +    TCGLabel *branch_taken = NULL;
>      if (cond != TCG_COND_ALWAYS) {
>          pred_false = gen_new_label();
>          tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
> @@ -480,12 +481,22 @@ static void gen_write_new_pc_addr(DisasContext
> *ctx, TCGv addr,
> 
>      if (ctx->pkt->pkt_has_multi_cof) {
>          /* If there are multiple branches in a packet, ignore the second one 
> */
> -        tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
> -                           ctx->branch_taken, tcg_constant_tl(0),
> -                           hex_gpr[HEX_REG_PC], addr);
> +        branch_taken = gen_new_label();
> +        tcg_gen_brcondi_tl(TCG_COND_NE, ctx->branch_taken, 0,
> branch_taken);
>          tcg_gen_movi_tl(ctx->branch_taken, 1);
> -    } else {
> -        tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
> +    }
> +
> +    TCGLabel *pc_aligned = gen_new_label();
> +    TCGv pc_remainder = tcg_temp_new();
> +    tcg_gen_andi_tl(pc_remainder, addr, PCALIGN_MASK);
> +    tcg_gen_brcondi_tl(TCG_COND_EQ, pc_remainder, 0, pc_aligned);
> +    gen_exception_end_tb(ctx, HEX_EXCP_PC_NOT_ALIGNED);
> +    gen_set_label(pc_aligned);
> +
> +    tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
> +
> +    if (ctx->pkt->pkt_has_multi_cof) {
> +        gen_set_label(branch_taken);
>      }
> 
>      if (cond != TCG_COND_ALWAYS) {
> diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
> index f163eefe97..e6ee63a53e 100644
> --- a/target/hexagon/translate.c
> +++ b/target/hexagon/translate.c
> @@ -185,7 +185,7 @@ static void gen_end_tb(DisasContext *ctx)
>      ctx->base.is_jmp = DISAS_NORETURN;
>  }
> 
> -static void gen_exception_end_tb(DisasContext *ctx, int excp)
> +void gen_exception_end_tb(DisasContext *ctx, int excp)
>  {
>      gen_exec_counters(ctx);
>      tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
> diff --git a/tests/tcg/hexagon/Makefile.target
> b/tests/tcg/hexagon/Makefile.target
> index f839b2c0d5..02d7fff34c 100644
> --- a/tests/tcg/hexagon/Makefile.target
> +++ b/tests/tcg/hexagon/Makefile.target
> @@ -51,6 +51,19 @@ HEX_TESTS += scatter_gather
>  HEX_TESTS += hvx_misc
>  HEX_TESTS += hvx_histogram
>  HEX_TESTS += invalid-slots
> +HEX_TESTS += unaligned_pc
> +HEX_TESTS += unaligned_pc_multi_cof
> +
> +run-unaligned_pc: unaligned_pc
> +run-unaligned_pc_multi_cof: unaligned_pc_multi_cof
> +run-unaligned_pc run-unaligned_pc_multi_cof:
> +     $(call run-test, $<, $(QEMU) $< 2> $<.stderr,"$< on
> $(TARGET_NAME)"); \
> +     if [ $$? -ne 1 ] ; then \
> +             return 1; \
> +     fi
> +     $(call quiet-command, \
> +             grep -q "exception 0x1e" $<.stderr, \
> +             "GREP", "exception 0x1e");
> 
>  run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \
>       test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr)
> diff --git a/tests/tcg/hexagon/unaligned_pc.S
> b/tests/tcg/hexagon/unaligned_pc.S
> new file mode 100644
> index 0000000000..39d6b2060b
> --- /dev/null
> +++ b/tests/tcg/hexagon/unaligned_pc.S
> @@ -0,0 +1,10 @@
> +test:
> +     allocframe(#0x8)
> +     r0 = #0xffffffff
> +     framekey = r0
> +     dealloc_return
> +
> +.global _start
> +_start:
> +     call test
> +     jump pass
> diff --git a/tests/tcg/hexagon/unaligned_pc_multi_cof.S
> b/tests/tcg/hexagon/unaligned_pc_multi_cof.S
> new file mode 100644
> index 0000000000..a83e248ece
> --- /dev/null
> +++ b/tests/tcg/hexagon/unaligned_pc_multi_cof.S
> @@ -0,0 +1,13 @@
> +.org 0x3
> +test:
> +     nop
> +     jumpr r31
> +
> +.global _start
> +_start:
> +     p0 = cmp.eq(r0, r0)
> +     {
> +             if (p0) jump test
> +             jump pass
> +     }
> +     jump pass
> --
> 2.37.2


Reply via email to