All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/11] Hexagon bug fixes and performance improvement
@ 2022-11-11  0:52 Taylor Simpson
  2022-11-11  0:52 ` [PULL 01/11] Hexagon (target/hexagon) Add pkt and insn to DisasContext Taylor Simpson
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

The following changes since commit 2ccad61746ca7de5dd3e25146062264387e43bd4:

  Merge tag 'pull-tcg-20221109' of https://gitlab.com/rth7680/qemu into staging (2022-11-09 13:26:45 -0500)

are available in the Git repository at:

  https://github.com/quic/qemu tags/pull-hex-20221110

for you to fetch changes up to f2630d5994fb716a302289d97844d1c9622f3aff:

  Hexagon (target/hexagon) Use direct block chaining for tight loops (2022-11-10 09:49:35 -0800)

----------------------------------------------------------------

1)
Performance improvement
Add pkt and insn to DisasContext
Many functions need information from all 3 structures, so merge
them together.

2)
Bug fix
Fix predicated assignment to .tmp and .cur

3)
Performance improvement
Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
These functions will not be handled by idef-parser

4-11)
The final 8 patches improve change-of-flow handling.

Currently, we set the PC to a new address before exiting a TB.  The
ultimate goal is to use direct block chaining.  However, several steps
are needed along the way.

4)
When a packet has more than one change-of-flow (COF) instruction, only
the first one taken is considered.  The runtime bookkeeping is only
needed when there is more than one COF instruction in a packet.

5, 6)
Remove PC and next_PC from the runtime state and always use a
translation-time constant.  Note that next_PC is used by call instructions
to set LR and by conditional COF instructions to set the fall-through
address.

7, 8, 9)
Add helper overrides for COF instructions.  In particular, we must
distinguish those that use a PC-relative address for the destination.
These are candidates for direct block chaining later.

10)
Use direct block chaining for packets that have a single PC-relative
COF instruction.  Instead of generating the code while processing the
instruction, we record the effect in DisasContext and generate the code
during gen_end_tb.

11)
Use direct block chaining for tight loops.  We look for TBs that end
with an endloop0 that will branch back to the TB start address.

----------------------------------------------------------------
Taylor Simpson (11):
      Hexagon (target/hexagon) Add pkt and insn to DisasContext
      Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur
      Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
      Hexagon (target/hexagon) Only use branch_taken when packet has multi cof
      Hexagon (target/hexagon) Remove PC from the runtime state
      Hexagon (target/hexagon) Remove next_PC from runtime state
      Hexagon (target/hexagon) Add overrides for direct call instructions
      Hexagon (target/hexagon) Add overrides for compound compare and jump
      Hexagon (target/hexagon) Add overrides for various forms of jump
      Hexagon (target/hexagon) Use direct block chaining for direct jump/branch
      Hexagon (target/hexagon) Use direct block chaining for tight loops

 target/hexagon/cpu.h                |  14 +-
 target/hexagon/gen_tcg.h            | 412 +++++++++++++++++++++++++++++++++++-
 target/hexagon/gen_tcg_hvx.h        |   6 +-
 target/hexagon/insn.h               |   9 +-
 target/hexagon/macros.h             |  16 +-
 target/hexagon/mmvec/macros.h       |   4 +-
 target/hexagon/translate.h          |  20 +-
 target/hexagon/decode.c             |  15 +-
 target/hexagon/genptr.c             | 392 +++++++++++++++++++++++++++++++++-
 target/hexagon/op_helper.c          |  28 ++-
 target/hexagon/translate.c          | 229 +++++++++++++-------
 tests/tcg/hexagon/hvx_misc.c        |  72 +++++++
 tests/tcg/hexagon/usr.c             |  34 ++-
 target/hexagon/gen_helper_funcs.py  |  13 +-
 target/hexagon/gen_helper_protos.py |  14 +-
 target/hexagon/gen_tcg_funcs.py     |  38 +++-
 target/hexagon/hex_common.py        |  29 ++-
 17 files changed, 1207 insertions(+), 138 deletions(-)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PULL 01/11] Hexagon (target/hexagon) Add pkt and insn to DisasContext
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 02/11] Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur Taylor Simpson
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

This enables us to reduce the number of parameters to many functions
In particular, the generated functions previously took all 3 as arguments

Not only does this simplify the code, it improves the translation time

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-2-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg_hvx.h    |   6 +-
 target/hexagon/insn.h           |   7 +-
 target/hexagon/macros.h         |  10 +--
 target/hexagon/mmvec/macros.h   |   4 +-
 target/hexagon/translate.h      |   9 ++-
 target/hexagon/genptr.c         |   6 +-
 target/hexagon/translate.c      | 120 +++++++++++++++++---------------
 target/hexagon/gen_tcg_funcs.py |  15 ++--
 8 files changed, 89 insertions(+), 88 deletions(-)

diff --git a/target/hexagon/gen_tcg_hvx.h b/target/hexagon/gen_tcg_hvx.h
index cdcc9382bb..083f4d92c6 100644
--- a/target/hexagon/gen_tcg_hvx.h
+++ b/target/hexagon/gen_tcg_hvx.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -697,7 +697,7 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 #define fGEN_TCG_NEWVAL_VEC_STORE(GET_EA, INC) \
     do { \
         GET_EA; \
-        gen_vreg_store(ctx, insn, pkt, EA, OsN_off, insn->slot, true); \
+        gen_vreg_store(ctx, EA, OsN_off, insn->slot, true); \
         INC; \
     } while (0)
 
@@ -736,7 +736,7 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
         PRED; \
         tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
         tcg_temp_free(LSB); \
-        gen_vreg_store(ctx, insn, pkt, EA, SRCOFF, insn->slot, ALIGN); \
+        gen_vreg_store(ctx, EA, SRCOFF, insn->slot, ALIGN); \
         INC; \
         tcg_gen_br(end_label); \
         gen_set_label(false_label); \
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index aa26389147..cb92586802 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,10 +28,7 @@ struct Instruction;
 struct Packet;
 struct DisasContext;
 
-typedef void (*SemanticInsn)(CPUHexagonState *env,
-                             struct DisasContext *ctx,
-                             struct Instruction *insn,
-                             struct Packet *pkt);
+typedef void (*SemanticInsn)(struct DisasContext *ctx);
 
 struct Instruction {
     SemanticInsn generate;            /* pointer to genptr routine */
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index c8805bdaeb..93ee4739a1 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -94,9 +94,9 @@
  */
 #define CHECK_NOSHUF(VA, SIZE) \
     do { \
-        if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
+        if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
             probe_noshuf_load(VA, SIZE, ctx->mem_idx); \
-            process_store(ctx, pkt, 1); \
+            process_store(ctx, 1); \
         } \
     } while (0)
 
@@ -105,12 +105,12 @@
         TCGLabel *label = gen_new_label(); \
         tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, label); \
         GET_EA; \
-        if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
+        if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
             probe_noshuf_load(EA, SIZE, ctx->mem_idx); \
         } \
         gen_set_label(label); \
-        if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
-            process_store(ctx, pkt, 1); \
+        if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
+            process_store(ctx, 1); \
         } \
     } while (0)
 
diff --git a/target/hexagon/mmvec/macros.h b/target/hexagon/mmvec/macros.h
index 8345753580..8c864e8c68 100644
--- a/target/hexagon/mmvec/macros.h
+++ b/target/hexagon/mmvec/macros.h
@@ -288,7 +288,7 @@
 #endif
 #ifdef QEMU_GENERATE
 #define fSTOREMMV(EA, SRC) \
-    gen_vreg_store(ctx, insn, pkt, EA, SRC##_off, insn->slot, true)
+    gen_vreg_store(ctx, EA, SRC##_off, insn->slot, true)
 #endif
 #ifdef QEMU_GENERATE
 #define fSTOREMMVQ(EA, SRC, MASK) \
@@ -300,7 +300,7 @@
 #endif
 #ifdef QEMU_GENERATE
 #define fSTOREMMVU(EA, SRC) \
-    gen_vreg_store(ctx, insn, pkt, EA, SRC##_off, insn->slot, false)
+    gen_vreg_store(ctx, EA, SRC##_off, insn->slot, false)
 #endif
 #define fVFOREACH(WIDTH, VAR) for (VAR = 0; VAR < fVELEM(WIDTH); VAR++)
 #define fVARRAY_ELEMENT_ACCESS(ARRAY, TYPE, INDEX) \
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index a245172827..115e29b84f 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,10 +23,13 @@
 #include "cpu.h"
 #include "exec/translator.h"
 #include "tcg/tcg-op.h"
+#include "insn.h"
 #include "internal.h"
 
 typedef struct DisasContext {
     DisasContextBase base;
+    Packet *pkt;
+    Insn *insn;
     uint32_t mem_idx;
     uint32_t num_packets;
     uint32_t num_insns;
@@ -147,6 +150,6 @@ extern TCGv hex_vstore_addr[VSTORES_MAX];
 extern TCGv hex_vstore_size[VSTORES_MAX];
 extern TCGv hex_vstore_pending[VSTORES_MAX];
 
-bool is_gather_store_insn(Insn *insn, Packet *pkt);
-void process_store(DisasContext *ctx, Packet *pkt, int slot_num);
+bool is_gather_store_insn(DisasContext *ctx);
+void process_store(DisasContext *ctx, int slot_num);
 #endif
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 806d0974ff..85416dd530 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -551,13 +551,13 @@ static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
     tcg_temp_free_i64(tmp);
 }
 
-static void gen_vreg_store(DisasContext *ctx, Insn *insn, Packet *pkt,
-                           TCGv EA, intptr_t srcoff, int slot, bool aligned)
+static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
+                           int slot, bool aligned)
 {
     intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
     intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
 
-    if (is_gather_store_insn(insn, pkt)) {
+    if (is_gather_store_insn(ctx)) {
         TCGv sl = tcg_constant_tl(slot);
         gen_helper_gather_store(cpu_env, EA, sl);
         return;
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 2329177537..0940d0f2c1 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -209,8 +209,9 @@ static bool need_pred_written(Packet *pkt)
     return check_for_attrib(pkt, A_WRITES_PRED_REG);
 }
 
-static void gen_start_packet(DisasContext *ctx, Packet *pkt)
+static void gen_start_packet(DisasContext *ctx)
 {
+    Packet *pkt = ctx->pkt;
     target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
     int i;
 
@@ -260,8 +261,10 @@ static void gen_start_packet(DisasContext *ctx, Packet *pkt)
     }
 }
 
-bool is_gather_store_insn(Insn *insn, Packet *pkt)
+bool is_gather_store_insn(DisasContext *ctx)
 {
+    Packet *pkt = ctx->pkt;
+    Insn *insn = ctx->insn;
     if (GET_ATTRIB(insn->opcode, A_CVI_NEW) &&
         insn->new_value_producer_slot == 1) {
         /* Look for gather instruction */
@@ -280,15 +283,15 @@ bool is_gather_store_insn(Insn *insn, Packet *pkt)
  * However, there are some implicit writes marked as attributes
  * of the applicable instructions.
  */
-static void mark_implicit_reg_write(DisasContext *ctx, Insn *insn,
-                                    int attrib, int rnum)
+static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
 {
-    if (GET_ATTRIB(insn->opcode, attrib)) {
+    uint16_t opcode = ctx->insn->opcode;
+    if (GET_ATTRIB(opcode, attrib)) {
         /*
          * USR is used to set overflow and FP exceptions,
          * so treat it as conditional
          */
-        bool is_predicated = GET_ATTRIB(insn->opcode, A_CONDEXEC) ||
+        bool is_predicated = GET_ATTRIB(opcode, A_CONDEXEC) ||
                              rnum == HEX_REG_USR;
         if (is_predicated && !is_preloaded(ctx, rnum)) {
             tcg_gen_mov_tl(hex_new_value[rnum], hex_gpr[rnum]);
@@ -298,39 +301,38 @@ static void mark_implicit_reg_write(DisasContext *ctx, Insn *insn,
     }
 }
 
-static void mark_implicit_pred_write(DisasContext *ctx, Insn *insn,
-                                     int attrib, int pnum)
+static void mark_implicit_pred_write(DisasContext *ctx, int attrib, int pnum)
 {
-    if (GET_ATTRIB(insn->opcode, attrib)) {
+    if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
         ctx_log_pred_write(ctx, pnum);
     }
 }
 
-static void mark_implicit_reg_writes(DisasContext *ctx, Insn *insn)
+static void mark_implicit_reg_writes(DisasContext *ctx)
 {
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_FP,  HEX_REG_FP);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SP,  HEX_REG_SP);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LR,  HEX_REG_LR);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
-    mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_USR, HEX_REG_USR);
-    mark_implicit_reg_write(ctx, insn, A_FPOP, HEX_REG_USR);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_FP,  HEX_REG_FP);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SP,  HEX_REG_SP);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LR,  HEX_REG_LR);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
+    mark_implicit_reg_write(ctx, A_IMPLICIT_WRITES_USR, HEX_REG_USR);
+    mark_implicit_reg_write(ctx, A_FPOP, HEX_REG_USR);
 }
 
-static void mark_implicit_pred_writes(DisasContext *ctx, Insn *insn)
+static void mark_implicit_pred_writes(DisasContext *ctx)
 {
-    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P0, 0);
-    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P1, 1);
-    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P2, 2);
-    mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P3, 3);
+    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P0, 0);
+    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P1, 1);
+    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P2, 2);
+    mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
 }
 
-static void mark_store_width(DisasContext *ctx, Insn *insn)
+static void mark_store_width(DisasContext *ctx)
 {
-    uint16_t opcode = insn->opcode;
-    uint32_t slot = insn->slot;
+    uint16_t opcode = ctx->insn->opcode;
+    uint32_t slot = ctx->insn->slot;
     uint8_t width = 0;
 
     if (GET_ATTRIB(opcode, A_SCALAR_STORE)) {
@@ -351,14 +353,13 @@ static void mark_store_width(DisasContext *ctx, Insn *insn)
     }
 }
 
-static void gen_insn(CPUHexagonState *env, DisasContext *ctx,
-                     Insn *insn, Packet *pkt)
+static void gen_insn(DisasContext *ctx)
 {
-    if (insn->generate) {
-        mark_implicit_reg_writes(ctx, insn);
-        insn->generate(env, ctx, insn, pkt);
-        mark_implicit_pred_writes(ctx, insn);
-        mark_store_width(ctx, insn);
+    if (ctx->insn->generate) {
+        mark_implicit_reg_writes(ctx);
+        ctx->insn->generate(ctx);
+        mark_implicit_pred_writes(ctx);
+        mark_store_width(ctx);
     } else {
         gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
     }
@@ -378,7 +379,7 @@ static void gen_reg_writes(DisasContext *ctx)
     }
 }
 
-static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
+static void gen_pred_writes(DisasContext *ctx)
 {
     int i;
 
@@ -393,7 +394,7 @@ static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
      * instructions, we can use the non-conditional
      * write of the predicates.
      */
-    if (pkt->pkt_has_endloop) {
+    if (ctx->pkt->pkt_has_endloop) {
         TCGv zero = tcg_constant_tl(0);
         TCGv pred_written = tcg_temp_new();
         for (i = 0; i < ctx->preg_log_idx; i++) {
@@ -439,9 +440,9 @@ static bool slot_is_predicated(Packet *pkt, int slot_num)
     g_assert_not_reached();
 }
 
-void process_store(DisasContext *ctx, Packet *pkt, int slot_num)
+void process_store(DisasContext *ctx, int slot_num)
 {
-    bool is_predicated = slot_is_predicated(pkt, slot_num);
+    bool is_predicated = slot_is_predicated(ctx->pkt, slot_num);
     TCGLabel *label_end = NULL;
 
     /*
@@ -517,27 +518,28 @@ void process_store(DisasContext *ctx, Packet *pkt, int slot_num)
     }
 }
 
-static void process_store_log(DisasContext *ctx, Packet *pkt)
+static void process_store_log(DisasContext *ctx)
 {
     /*
      *  When a packet has two stores, the hardware processes
      *  slot 1 and then slot 0.  This will be important when
      *  the memory accesses overlap.
      */
+    Packet *pkt = ctx->pkt;
     if (pkt->pkt_has_store_s1) {
         g_assert(!pkt->pkt_has_dczeroa);
-        process_store(ctx, pkt, 1);
+        process_store(ctx, 1);
     }
     if (pkt->pkt_has_store_s0) {
         g_assert(!pkt->pkt_has_dczeroa);
-        process_store(ctx, pkt, 0);
+        process_store(ctx, 0);
     }
 }
 
 /* Zero out a 32-bit cache line */
-static void process_dczeroa(DisasContext *ctx, Packet *pkt)
+static void process_dczeroa(DisasContext *ctx)
 {
-    if (pkt->pkt_has_dczeroa) {
+    if (ctx->pkt->pkt_has_dczeroa) {
         /* Store 32 bytes of zero starting at (addr & ~0x1f) */
         TCGv addr = tcg_temp_new();
         TCGv_i64 zero = tcg_constant_i64(0);
@@ -567,7 +569,7 @@ static bool pkt_has_hvx_store(Packet *pkt)
     return false;
 }
 
-static void gen_commit_hvx(DisasContext *ctx, Packet *pkt)
+static void gen_commit_hvx(DisasContext *ctx)
 {
     int i;
 
@@ -637,13 +639,14 @@ static void gen_commit_hvx(DisasContext *ctx, Packet *pkt)
         }
     }
 
-    if (pkt_has_hvx_store(pkt)) {
+    if (pkt_has_hvx_store(ctx->pkt)) {
         gen_helper_commit_hvx_stores(cpu_env);
     }
 }
 
-static void update_exec_counters(DisasContext *ctx, Packet *pkt)
+static void update_exec_counters(DisasContext *ctx)
 {
+    Packet *pkt = ctx->pkt;
     int num_insns = pkt->num_insns;
     int num_real_insns = 0;
     int num_hvx_insns = 0;
@@ -664,8 +667,7 @@ static void update_exec_counters(DisasContext *ctx, Packet *pkt)
     ctx->num_hvx_insns += num_hvx_insns;
 }
 
-static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx,
-                              Packet *pkt)
+static void gen_commit_packet(DisasContext *ctx)
 {
     /*
      * If there is more than one store in a packet, make sure they are all OK
@@ -684,6 +686,7 @@ static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx,
      * store.  Therefore, we call process_store_log before anything else
      * involved in committing the packet.
      */
+    Packet *pkt = ctx->pkt;
     bool has_store_s0 = pkt->pkt_has_store_s0;
     bool has_store_s1 = (pkt->pkt_has_store_s1 && !ctx->s1_store_processed);
     bool has_hvx_store = pkt_has_hvx_store(pkt);
@@ -693,7 +696,7 @@ static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx,
          * a store in slot 1 or an HVX store.
          */
         g_assert(!has_store_s1 && !has_hvx_store);
-        process_dczeroa(ctx, pkt);
+        process_dczeroa(ctx);
     } else if (has_hvx_store) {
         TCGv mem_idx = tcg_constant_tl(ctx->mem_idx);
 
@@ -724,14 +727,14 @@ static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx,
         gen_helper_probe_pkt_scalar_store_s0(cpu_env, mem_idx);
     }
 
-    process_store_log(ctx, pkt);
+    process_store_log(ctx);
 
     gen_reg_writes(ctx);
-    gen_pred_writes(ctx, pkt);
+    gen_pred_writes(ctx);
     if (pkt->pkt_has_hvx) {
-        gen_commit_hvx(ctx, pkt);
+        gen_commit_hvx(ctx);
     }
-    update_exec_counters(ctx, pkt);
+    update_exec_counters(ctx);
     if (HEX_DEBUG) {
         TCGv has_st0 =
             tcg_constant_tl(pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa);
@@ -744,7 +747,8 @@ static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx,
 
     if (pkt->vhist_insn != NULL) {
         ctx->pre_commit = false;
-        pkt->vhist_insn->generate(env, ctx, pkt->vhist_insn, pkt);
+        ctx->insn = pkt->vhist_insn;
+        pkt->vhist_insn->generate(ctx);
     }
 
     if (pkt->pkt_has_cof) {
@@ -767,11 +771,13 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
 
     if (decode_packet(nwords, words, &pkt, false) > 0) {
         HEX_DEBUG_PRINT_PKT(&pkt);
-        gen_start_packet(ctx, &pkt);
+        ctx->pkt = &pkt;
+        gen_start_packet(ctx);
         for (i = 0; i < pkt.num_insns; i++) {
-            gen_insn(env, ctx, &pkt.insn[i], &pkt);
+            ctx->insn = &pkt.insn[i];
+            gen_insn(ctx);
         }
-        gen_commit_packet(env, ctx, &pkt);
+        gen_commit_packet(ctx);
         ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
     } else {
         gen_exception_end_tb(ctx, HEX_EXCP_INVALID_PACKET);
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 6dea02b0b9..02a6565685 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -561,11 +561,7 @@ def genptr_dst_write_opn(f,regtype, regid, tag):
 ## Generate the TCG code to call the helper
 ##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
 ##     We produce:
-##    static void generate_A2_add()
-##                    CPUHexagonState *env
-##                    DisasContext *ctx,
-##                    Insn *insn,
-##                    Packet *pkt)
+##    static void generate_A2_add(DisasContext *ctx)
 ##       {
 ##           TCGv RdV = tcg_temp_local_new();
 ##           const int RdN = insn->regno[0];
@@ -584,12 +580,11 @@ def genptr_dst_write_opn(f,regtype, regid, tag):
 ##       <GEN>  is gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
 ##
 def gen_tcg_func(f, tag, regs, imms):
-    f.write("static void generate_%s(\n" %tag)
-    f.write("                CPUHexagonState *env,\n")
-    f.write("                DisasContext *ctx,\n")
-    f.write("                Insn *insn,\n")
-    f.write("                Packet *pkt)\n")
+    f.write("static void generate_%s(DisasContext *ctx)\n" %tag)
     f.write('{\n')
+
+    f.write("    Insn *insn __attribute__((unused)) = ctx->insn;\n")
+
     if hex_common.need_ea(tag): gen_decl_ea_tcg(f, tag)
     i=0
     ## Declare all the operands (regs and immediates)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 02/11] Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
  2022-11-11  0:52 ` [PULL 01/11] Hexagon (target/hexagon) Add pkt and insn to DisasContext Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 03/11] Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Here are example instructions with a predicated .tmp/.cur assignment
    if (p1) v12.tmp = vmem(r7 + #0)
    if (p0) v12.cur = vmem(r9 + #0)
The .tmp/.cur indicates that references to v12 in the same packet
take the result of the load.  However, when the predicate is false,
the value at the start of the packet should be used.  After the packet
commits, the .tmp value is dropped, but the .cur value is maintained.

To fix this bug, we preload the original value from the HVX register
into the temporary used for the result.

Test cases added to tests/tcg/hexagon/hvx_misc.c

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-3-tsimpson@quicinc.com>
---
 target/hexagon/translate.h      |  6 +++
 tests/tcg/hexagon/hvx_misc.c    | 72 +++++++++++++++++++++++++++++++++
 target/hexagon/gen_tcg_funcs.py | 12 ++++++
 3 files changed, 90 insertions(+)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 115e29b84f..b8fcf615e8 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -86,6 +86,12 @@ static inline bool is_preloaded(DisasContext *ctx, int num)
     return test_bit(num, ctx->regs_written);
 }
 
+static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
+{
+    return test_bit(num, ctx->vregs_updated) ||
+           test_bit(num, ctx->vregs_updated_tmp);
+}
+
 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
                              int num, bool alloc_ok);
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index 6e2c9ab3cd..53d5c9b44f 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -541,6 +541,75 @@ static void test_vshuff(void)
     check_output_b(__LINE__, 1);
 }
 
+static void test_load_tmp_predicated(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+    bool pred = true;
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        /*
+         * Load into v12 as .tmp with a predicate
+         * When the predicate is true, we get the vector from buffer1[i]
+         * When the predicate is false, we get a vector of all 1's
+         * Regardless of the predicate, the next packet should have
+         * a vector of all 1's
+         */
+        asm("v3 = vmem(%0 + #0)\n\t"
+            "r1 = #1\n\t"
+            "v12 = vsplat(r1)\n\t"
+            "p1 = !cmp.eq(%3, #0)\n\t"
+            "{\n\t"
+            "    if (p1) v12.tmp = vmem(%1 + #0)\n\t"
+            "    v4.w = vadd(v12.w, v3.w)\n\t"
+            "}\n\t"
+            "v4.w = vadd(v4.w, v12.w)\n\t"
+            "vmem(%2 + #0) = v4\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout), "r"(pred)
+            : "r1", "p1", "v12", "v3", "v4", "v6", "memory");
+        p0 += sizeof(MMVector);
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[i].w[j] =
+                pred ? buffer0[i].w[j] + buffer1[i].w[j] + 1
+                     : buffer0[i].w[j] + 2;
+        }
+        pred = !pred;
+    }
+
+    check_output_w(__LINE__, BUFSIZE);
+}
+
+static void test_load_cur_predicated(void)
+{
+    bool pred = true;
+    for (int i = 0; i < BUFSIZE; i++) {
+        asm volatile("p0 = !cmp.eq(%3, #0)\n\t"
+                     "v3 = vmem(%0+#0)\n\t"
+                     /*
+                      * Preload v4 to make sure that the assignment from the
+                      * packet below is not being ignored when pred is false.
+                      */
+                     "r0 = #0x01237654\n\t"
+                     "v4 = vsplat(r0)\n\t"
+                     "{\n\t"
+                     "    if (p0) v3.cur = vmem(%1+#0)\n\t"
+                     "    v4 = v3\n\t"
+                     "}\n\t"
+                     "vmem(%2+#0) = v4\n\t"
+                     :
+                     : "r"(&buffer0[i]), "r"(&buffer1[i]),
+                       "r"(&output[i]), "r"(pred)
+                     : "r0", "p0", "v3", "v4", "memory");
+        expect[i] = pred ? buffer1[i] : buffer0[i];
+        pred = !pred;
+    }
+    check_output_w(__LINE__, BUFSIZE);
+}
+
 int main()
 {
     init_buffers();
@@ -578,6 +647,9 @@ int main()
 
     test_vshuff();
 
+    test_load_tmp_predicated();
+    test_load_cur_predicated();
+
     puts(err ? "FAIL" : "PASS");
     return err ? 1 : 0;
 }
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 02a6565685..ca5fde91cc 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -173,6 +173,18 @@ def genptr_decl(f, tag, regtype, regid, regno):
                 f.write("        ctx_future_vreg_off(ctx, %s%sN," % \
                     (regtype, regid))
                 f.write(" 1, true);\n");
+            if 'A_CONDEXEC' in hex_common.attribdict[tag]:
+                f.write("    if (!is_vreg_preloaded(ctx, %s)) {\n" % (regN))
+                f.write("        intptr_t src_off =")
+                f.write(" offsetof(CPUHexagonState, VRegs[%s%sN]);\n"% \
+                                     (regtype, regid))
+                f.write("        tcg_gen_gvec_mov(MO_64, %s%sV_off,\n" % \
+                                     (regtype, regid))
+                f.write("                         src_off,\n")
+                f.write("                         sizeof(MMVector),\n")
+                f.write("                         sizeof(MMVector));\n")
+                f.write("    }\n")
+
             if (not hex_common.skip_qemu_helper(tag)):
                 f.write("    TCGv_ptr %s%sV = tcg_temp_new_ptr();\n" % \
                     (regtype, regid))
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 03/11] Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
  2022-11-11  0:52 ` [PULL 01/11] Hexagon (target/hexagon) Add pkt and insn to DisasContext Taylor Simpson
  2022-11-11  0:52 ` [PULL 02/11] Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 04/11] Hexagon (target/hexagon) Only use branch_taken when packet has multi cof Taylor Simpson
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

These instructions will not be generated by idef-parser, so we override
them manually.

Test cases added to tests/tcg/hexagon/usr.c

Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20221108162906.3166-4-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h |  10 +++-
 target/hexagon/genptr.c  | 104 +++++++++++++++++++++++++++++++++++++++
 tests/tcg/hexagon/usr.c  |  34 ++++++++++---
 3 files changed, 141 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 50634ac459..b5fe22a07a 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -612,6 +612,14 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+/* r0 = asr(r1, r2):sat */
+#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
+    gen_asr_r_r_sat(RdV, RsV, RtV)
+
+/* r0 = asl(r1, r2):sat */
+#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
+    gen_asl_r_r_sat(RdV, RsV, RtV)
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
     gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 85416dd530..cd3d74525e 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -456,6 +456,110 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
     return result;
 }
 
+/* Shift left with saturation */
+static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt)
+{
+    TCGv sh32 = tcg_temp_new();
+    TCGv dst_sar = tcg_temp_new();
+    TCGv ovf = tcg_temp_new();
+    TCGv satval = tcg_temp_new();
+    TCGv min = tcg_constant_tl(0x80000000);
+    TCGv max = tcg_constant_tl(0x7fffffff);
+
+    /*
+     *    Possible values for shift_amt are 0 .. 64
+     *    We need special handling for values above 31
+     *
+     *    sh32 = shift & 31;
+     *    dst = sh32 == shift ? src : 0;
+     *    dst <<= sh32;
+     *    dst_sar = dst >> sh32;
+     *    satval = src < 0 ? min : max;
+     *    if (dst_asr != src) {
+     *        usr.OVF |= 1;
+     *        dst = satval;
+     *    }
+     */
+
+    tcg_gen_andi_tl(sh32, shift_amt, 31);
+    tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt,
+                       src, tcg_constant_tl(0));
+    tcg_gen_shl_tl(dst, dst, sh32);
+    tcg_gen_sar_tl(dst_sar, dst, sh32);
+    tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
+
+    tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
+    tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
+    tcg_gen_or_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR], ovf);
+
+    tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval);
+
+    tcg_temp_free(sh32);
+    tcg_temp_free(dst_sar);
+    tcg_temp_free(ovf);
+    tcg_temp_free(satval);
+}
+
+static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
+{
+    /*
+     *  Shift arithmetic right
+     *  Robust when shift_amt is >31 bits
+     */
+    TCGv tmp = tcg_temp_new();
+    tcg_gen_umin_tl(tmp, shift_amt, tcg_constant_tl(31));
+    tcg_gen_sar_tl(dst, src, tmp);
+    tcg_temp_free(tmp);
+}
+
+/* Bidirectional shift right with saturation */
+static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift left */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    gen_shl_sat(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift right */
+    gen_sar(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
+/* Bidirectional shift left with saturation */
+static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift right */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    gen_sar(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift left */
+    gen_shl_sat(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
 static intptr_t vreg_src_off(DisasContext *ctx, int num)
 {
     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c
index fb4514989c..5f68c539dd 100644
--- a/tests/tcg/hexagon/usr.c
+++ b/tests/tcg/hexagon/usr.c
@@ -429,6 +429,7 @@ FUNC_P_OP_P(vabshsat,           "%0 = vabsh(%2):sat")
 FUNC_P_OP_PP(vnavgwr,           "%0 = vnavgw(%2, %3):rnd:sat")
 FUNC_R_OP_RI(round_ri_sat,      "%0 = round(%2, #%3):sat")
 FUNC_R_OP_RR(asr_r_r_sat,       "%0 = asr(%2, %3):sat")
+FUNC_R_OP_RR(asl_r_r_sat,       "%0 = asl(%2, %3):sat")
 
 FUNC_XPp_OP_PP(ACS,             "%0, p2 = vacsh(%3, %4)")
 
@@ -907,12 +908,33 @@ int main()
     TEST_R_OP_RI(round_ri_sat,         0x0000ffff, 2, 0x00004000, USR_CLEAR);
     TEST_R_OP_RI(round_ri_sat,         0x7fffffff, 2, 0x1fffffff, USR_OVF);
 
-    TEST_R_OP_RR(asr_r_r_sat,          0x0000ffff, 0x00000002, 0x00003fff,
-                 USR_CLEAR);
-    TEST_R_OP_RR(asr_r_r_sat,          0x00ffffff, 0xfffffff5, 0x7fffffff,
-                 USR_OVF);
-    TEST_R_OP_RR(asr_r_r_sat,          0x80000000, 0xfffffff5, 0x80000000,
-                 USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x0000ffff, 0x02, 0x00003fff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0x01, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0xffffffff, 0x01, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x00ffffff, 0xf5, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0xf5, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x7fff0000, 0x42, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0xff000000, 0x42, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,        4096,   32, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,        4096,  -32, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,       -4096,   32, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,       -4096,  -32, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,           0,  -32, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,           1,  -32, 0x7fffffff, USR_OVF);
+
+    TEST_R_OP_RR(asl_r_r_sat,  0x00000000, 0x40, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0xff, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0xffffffff, 0xff, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x00ffffff, 0x0b, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0x0b, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x7fff0000, 0xbe, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0xff000000, 0xbe, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,        4096,   32, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,        4096,  -32, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,       -4096,   32, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,       -4096,  -32, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,           0,   32, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,           1,   32, 0x7fffffff, USR_OVF);
 
     TEST_XPp_OP_PP(ACS, 0x0004000300020001ULL, 0x0001000200030004ULL,
                    0x0000000000000000ULL, 0x0004000300030004ULL, 0xf0,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 04/11] Hexagon (target/hexagon) Only use branch_taken when packet has multi cof
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (2 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 03/11] Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 05/11] Hexagon (target/hexagon) Remove PC from the runtime state Taylor Simpson
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

When a packet has more than one change-of-flow instruction, only the first
one to branch is considered.  We use the branch_taken variable to keep
track of this.

However, when there is a single cof instruction, we don't need the same
amount of bookkeeping.

We add the pkt_has_multi_cof member to the Packet structure, and pass this
information to the needed functions.

When there is a generated helper function with cof, the generator will
pass this pkt_has_multi_cof as a runtime value.

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-5-tsimpson@quicinc.com>
---
 target/hexagon/insn.h               |  1 +
 target/hexagon/macros.h             |  2 +-
 target/hexagon/decode.c             | 15 +++++++++++++--
 target/hexagon/op_helper.c          | 24 +++++++++++++++---------
 target/hexagon/translate.c          |  4 +++-
 target/hexagon/gen_helper_funcs.py  |  5 ++++-
 target/hexagon/gen_helper_protos.py |  8 ++++++--
 target/hexagon/gen_tcg_funcs.py     |  5 +++++
 target/hexagon/hex_common.py        |  3 +++
 9 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index cb92586802..775c4c183d 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -57,6 +57,7 @@ struct Packet {
 
     /* Pre-decodes about COF */
     bool pkt_has_cof;          /* Has any change-of-flow */
+    bool pkt_has_multi_cof;    /* Has more than one change-of-flow */
     bool pkt_has_endloop;
 
     bool pkt_has_dczeroa;
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 93ee4739a1..8fd8123cec 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -407,7 +407,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 
 #define fCHECK_PCALIGN(A)
 
-#define fWRITE_NPC(A) write_new_pc(env, A)
+#define fWRITE_NPC(A) write_new_pc(env, pkt_has_multi_cof != 0, A)
 
 #define fBRANCH(LOC, TYPE)          fWRITE_NPC(LOC)
 #define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 6b73b5c60c..041c8de751 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -388,6 +388,7 @@ static void decode_set_insn_attr_fields(Packet *pkt)
     uint16_t opcode;
 
     pkt->pkt_has_cof = false;
+    pkt->pkt_has_multi_cof = false;
     pkt->pkt_has_endloop = false;
     pkt->pkt_has_dczeroa = false;
 
@@ -412,13 +413,23 @@ static void decode_set_insn_attr_fields(Packet *pkt)
             }
         }
 
-        pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
+        if (decode_opcode_can_jump(opcode)) {
+            if (pkt->pkt_has_cof) {
+                pkt->pkt_has_multi_cof = true;
+            }
+            pkt->pkt_has_cof = true;
+        }
 
         pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
 
         pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
 
-        pkt->pkt_has_cof |= pkt->pkt_has_endloop;
+        if (pkt->pkt_has_endloop) {
+            if (pkt->pkt_has_cof) {
+                pkt->pkt_has_multi_cof = true;
+            }
+            pkt->pkt_has_cof = true;
+        }
     }
 }
 
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 085afc3274..84391e25eb 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -104,20 +104,26 @@ static void log_store64(CPUHexagonState *env, target_ulong addr,
     env->mem_log_stores[slot].data64 = val;
 }
 
-static void write_new_pc(CPUHexagonState *env, target_ulong addr)
+static void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof,
+                         target_ulong addr)
 {
     HEX_DEBUG_LOG("write_new_pc(0x" TARGET_FMT_lx ")\n", addr);
 
-    /*
-     * If more than one branch is taken in a packet, only the first one
-     * is actually done.
-     */
-    if (env->branch_taken) {
-        HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
-                      "ignoring the second one\n");
+    if (pkt_has_multi_cof) {
+        /*
+         * If more than one branch is taken in a packet, only the first one
+         * is actually done.
+         */
+        if (env->branch_taken) {
+            HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
+                          "ignoring the second one\n");
+        } else {
+            fCHECK_PCALIGN(addr);
+            env->next_PC = addr;
+            env->branch_taken = 1;
+        }
     } else {
         fCHECK_PCALIGN(addr);
-        env->branch_taken = 1;
         env->next_PC = addr;
     }
 }
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 0940d0f2c1..1d872d72b6 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -248,7 +248,9 @@ static void gen_start_packet(DisasContext *ctx)
         tcg_gen_movi_tl(hex_slot_cancelled, 0);
     }
     if (pkt->pkt_has_cof) {
-        tcg_gen_movi_tl(hex_branch_taken, 0);
+        if (pkt->pkt_has_multi_cof) {
+            tcg_gen_movi_tl(hex_branch_taken, 0);
+        }
         tcg_gen_movi_tl(hex_next_PC, next_PC);
     }
     if (need_pred_written(pkt)) {
diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index a446c45384..c4fc609b31 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
 ##
 ##  This program is free software; you can redistribute it and/or modify
 ##  it under the terms of the GNU General Public License as published by
@@ -238,6 +238,9 @@ def gen_helper_function(f, tag, tagregs, tagimms):
             gen_helper_arg_imm(f,immlett)
             i += 1
 
+        if (hex_common.need_pkt_has_multi_cof(tag)):
+            f.write(", uint32_t pkt_has_multi_cof")
+
         if hex_common.need_slot(tag):
             if i > 0: f.write(", ")
             f.write("uint32_t slot")
diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 3b4e993fd1..8c6b36d8d8 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
 ##
 ##  This program is free software; you can redistribute it and/or modify
 ##  it under the terms of the GNU General Public License as published by
@@ -82,6 +82,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         ## Figure out how many arguments the helper will take
         if (numscalarresults == 0):
             def_helper_size = len(regs)+len(imms)+numscalarreadwrite+1
+            if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
@@ -89,6 +90,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             f.write(', void' )
         else:
             def_helper_size = len(regs)+len(imms)+numscalarreadwrite
+            if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
@@ -126,7 +128,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         for immlett,bits,immshift in imms:
             f.write(", s32")
 
-        ## Add the arguments for the instruction slot and part1 (if needed)
+        ## Add the arguments for the instruction pkt_has_multi_cof, slot and
+        ## part1 (if needed)
+        if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
         if hex_common.need_slot(tag): f.write(', i32' )
         if hex_common.need_part1(tag): f.write(' , i32' )
         f.write(')\n')
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index ca5fde91cc..bd199dcbf1 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -622,6 +622,9 @@ def gen_tcg_func(f, tag, regs, imms):
         ## Generate the call to the helper
         for immlett,bits,immshift in imms:
             gen_helper_decl_imm(f,immlett)
+        if hex_common.need_pkt_has_multi_cof(tag):
+            f.write("    TCGv pkt_has_multi_cof = ")
+            f.write("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof);\n")
         if hex_common.need_part1(tag):
             f.write("    TCGv part1 = tcg_constant_tl(insn->part1);\n")
         if hex_common.need_slot(tag):
@@ -654,6 +657,8 @@ def gen_tcg_func(f, tag, regs, imms):
         for immlett,bits,immshift in imms:
             gen_helper_call_imm(f,immlett)
 
+        if hex_common.need_pkt_has_multi_cof(tag):
+            f.write(", pkt_has_multi_cof")
         if hex_common.need_slot(tag): f.write(", slot")
         if hex_common.need_part1(tag): f.write(", part1" )
         f.write(");\n")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index d9ba7df786..f5b58501db 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -207,6 +207,9 @@ def need_part1(tag):
 def need_ea(tag):
     return re.compile(r"\bEA\b").search(semdict[tag])
 
+def need_pkt_has_multi_cof(tag):
+    return 'A_COF' in attribdict[tag]
+
 def skip_qemu_helper(tag):
     return tag in overrides.keys()
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 05/11] Hexagon (target/hexagon) Remove PC from the runtime state
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (3 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 04/11] Hexagon (target/hexagon) Only use branch_taken when packet has multi cof Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 06/11] Hexagon (target/hexagon) Remove next_PC from " Taylor Simpson
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Add pc field to Packet structure
For helpers that need PC, pass an extra argument
Remove slot arg from conditional jump helpers
On a trap0, copy pkt->pc into hex_gpr[HEX_REG_PC]

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-6-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h            | 7 +++++++
 target/hexagon/insn.h               | 1 +
 target/hexagon/macros.h             | 2 +-
 target/hexagon/translate.c          | 9 +--------
 target/hexagon/gen_helper_funcs.py  | 4 ++++
 target/hexagon/gen_helper_protos.py | 3 +++
 target/hexagon/gen_tcg_funcs.py     | 3 +++
 target/hexagon/hex_common.py        | 6 +++++-
 8 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index b5fe22a07a..d38db72ce9 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -750,4 +750,11 @@
         RsV = RsV; \
     } while (0)
 
+#define fGEN_TCG_J2_trap0(SHORTCODE) \
+    do { \
+        uiV = uiV; \
+        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->pkt->pc); \
+        TCGv excp = tcg_constant_tl(HEX_EXCP_TRAP0); \
+        gen_helper_raise_exception(cpu_env, excp); \
+    } while (0)
 #endif
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 775c4c183d..3e7a22c91e 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -54,6 +54,7 @@ typedef struct Instruction Insn;
 struct Packet {
     uint16_t num_insns;
     uint16_t encod_pkt_size_in_bytes;
+    uint32_t pc;
 
     /* Pre-decodes about COF */
     bool pkt_has_cof;          /* Has any change-of-flow */
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 8fd8123cec..6e7a6a156a 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -398,7 +398,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 #else
 #define fREAD_GP() READ_REG(HEX_REG_GP)
 #endif
-#define fREAD_PC() (READ_REG(HEX_REG_PC))
+#define fREAD_PC() (PC)
 
 #define fREAD_NPC() (env->next_PC & (0xfffffffe))
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 1d872d72b6..9efc6c88aa 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -194,11 +194,6 @@ static bool check_for_attrib(Packet *pkt, int attrib)
     return false;
 }
 
-static bool need_pc(Packet *pkt)
-{
-    return check_for_attrib(pkt, A_IMPLICIT_READS_PC);
-}
-
 static bool need_slot_cancelled(Packet *pkt)
 {
     return check_for_attrib(pkt, A_CONDEXEC);
@@ -241,9 +236,6 @@ static void gen_start_packet(DisasContext *ctx)
     }
 
     /* Initialize the runtime state for packet semantics */
-    if (need_pc(pkt)) {
-        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
-    }
     if (need_slot_cancelled(pkt)) {
         tcg_gen_movi_tl(hex_slot_cancelled, 0);
     }
@@ -772,6 +764,7 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
     }
 
     if (decode_packet(nwords, words, &pkt, false) > 0) {
+        pkt.pc = ctx->base.pc_next;
         HEX_DEBUG_PRINT_PKT(&pkt);
         ctx->pkt = &pkt;
         gen_start_packet(ctx);
diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index c4fc609b31..024f70d166 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -241,6 +241,10 @@ def gen_helper_function(f, tag, tagregs, tagimms):
         if (hex_common.need_pkt_has_multi_cof(tag)):
             f.write(", uint32_t pkt_has_multi_cof")
 
+        if hex_common.need_PC(tag):
+            if i > 0: f.write(", ")
+            f.write("target_ulong PC")
+            i += 1
         if hex_common.need_slot(tag):
             if i > 0: f.write(", ")
             f.write("uint32_t slot")
diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 8c6b36d8d8..00c48dff7c 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -85,6 +85,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
+            if hex_common.need_PC(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
             ## The return type is void
             f.write(', void' )
@@ -93,6 +94,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
+            if hex_common.need_PC(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
 
         ## Generate the qemu DEF_HELPER type for each result
@@ -131,6 +133,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         ## Add the arguments for the instruction pkt_has_multi_cof, slot and
         ## part1 (if needed)
         if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
+        if hex_common.need_PC(tag): f.write(', i32')
         if hex_common.need_slot(tag): f.write(', i32' )
         if hex_common.need_part1(tag): f.write(' , i32' )
         f.write(')\n')
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index bd199dcbf1..7dbdde3191 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -629,6 +629,8 @@ def gen_tcg_func(f, tag, regs, imms):
             f.write("    TCGv part1 = tcg_constant_tl(insn->part1);\n")
         if hex_common.need_slot(tag):
             f.write("    TCGv slot = tcg_constant_tl(insn->slot);\n")
+        if hex_common.need_PC(tag):
+            f.write("    TCGv PC = tcg_constant_tl(ctx->pkt->pc);\n")
         f.write("    gen_helper_%s(" % (tag))
         i=0
         ## If there is a scalar result, it is the return type
@@ -659,6 +661,7 @@ def gen_tcg_func(f, tag, regs, imms):
 
         if hex_common.need_pkt_has_multi_cof(tag):
             f.write(", pkt_has_multi_cof")
+        if hex_common.need_PC(tag): f.write(", PC")
         if hex_common.need_slot(tag): f.write(", slot")
         if hex_common.need_part1(tag): f.write(", part1" )
         f.write(");\n")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index f5b58501db..cfe5fe7b35 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -194,7 +194,8 @@ def is_new_val(regtype, regid, tag):
     return regtype+regid+'N' in semdict[tag]
 
 def need_slot(tag):
-    if ('A_CONDEXEC' in attribdict[tag] or
+    if (('A_CONDEXEC' in attribdict[tag] and
+         'A_JUMP' not in attribdict[tag]) or
         'A_STORE' in attribdict[tag] or
         'A_LOAD' in attribdict[tag]):
         return 1
@@ -207,6 +208,9 @@ def need_part1(tag):
 def need_ea(tag):
     return re.compile(r"\bEA\b").search(semdict[tag])
 
+def need_PC(tag):
+    return 'A_IMPLICIT_READS_PC' in attribdict[tag]
+
 def need_pkt_has_multi_cof(tag):
     return 'A_COF' in attribdict[tag]
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 06/11] Hexagon (target/hexagon) Remove next_PC from runtime state
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (4 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 05/11] Hexagon (target/hexagon) Remove PC from the runtime state Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 07/11] Hexagon (target/hexagon) Add overrides for direct call instructions Taylor Simpson
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

The imported files don't properly mark all CONDEXEC instructions, so
we add some logic to hex_common.py to add the attribute.

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-7-tsimpson@quicinc.com>
---
 target/hexagon/cpu.h                |  1 -
 target/hexagon/gen_tcg.h            |  6 ++++++
 target/hexagon/macros.h             |  2 +-
 target/hexagon/translate.h          |  2 +-
 target/hexagon/op_helper.c          |  6 +++---
 target/hexagon/translate.c          | 29 +++++++++++++++++++++++------
 target/hexagon/gen_helper_funcs.py  |  4 ++++
 target/hexagon/gen_helper_protos.py |  3 +++
 target/hexagon/gen_tcg_funcs.py     |  3 +++
 target/hexagon/hex_common.py        | 20 ++++++++++++++++++++
 10 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 2a65a57bab..ff8c26272d 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -78,7 +78,6 @@ typedef struct CPUArchState {
     target_ulong gpr[TOTAL_PER_THREAD_REGS];
     target_ulong pred[NUM_PREGS];
     target_ulong branch_taken;
-    target_ulong next_PC;
 
     /* For comparing with LLDB on target - see adjust_stack_ptrs function */
     target_ulong last_pc_dumped;
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index d38db72ce9..df279ab43b 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -612,6 +612,12 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+#define fGEN_TCG_J2_pause(SHORTCODE) \
+    do { \
+        uiV = uiV; \
+        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC); \
+    } while (0)
+
 /* r0 = asr(r1, r2):sat */
 #define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
     gen_asr_r_r_sat(RdV, RsV, RtV)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 6e7a6a156a..903503540e 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -400,7 +400,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 #endif
 #define fREAD_PC() (PC)
 
-#define fREAD_NPC() (env->next_PC & (0xfffffffe))
+#define fREAD_NPC() (next_PC & (0xfffffffe))
 
 #define fREAD_P0() (READ_PREG(0))
 #define fREAD_P3() (READ_PREG(3))
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index b8fcf615e8..96509a4da7 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -30,6 +30,7 @@ typedef struct DisasContext {
     DisasContextBase base;
     Packet *pkt;
     Insn *insn;
+    uint32_t next_PC;
     uint32_t mem_idx;
     uint32_t num_packets;
     uint32_t num_insns;
@@ -134,7 +135,6 @@ static inline void ctx_log_qreg_write(DisasContext *ctx,
 
 extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
 extern TCGv hex_pred[NUM_PREGS];
-extern TCGv hex_next_PC;
 extern TCGv hex_this_PC;
 extern TCGv hex_slot_cancelled;
 extern TCGv hex_branch_taken;
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 84391e25eb..aad0195eb6 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -119,12 +119,12 @@ static void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof,
                           "ignoring the second one\n");
         } else {
             fCHECK_PCALIGN(addr);
-            env->next_PC = addr;
+            env->gpr[HEX_REG_PC] = addr;
             env->branch_taken = 1;
         }
     } else {
         fCHECK_PCALIGN(addr);
-        env->next_PC = addr;
+        env->gpr[HEX_REG_PC] = addr;
     }
 }
 
@@ -299,7 +299,7 @@ void HELPER(debug_commit_end)(CPUHexagonState *env, int has_st0, int has_st1)
         }
     }
 
-    HEX_DEBUG_LOG("Next PC = " TARGET_FMT_lx "\n", env->next_PC);
+    HEX_DEBUG_LOG("Next PC = " TARGET_FMT_lx "\n", env->gpr[HEX_REG_PC]);
     HEX_DEBUG_LOG("Exec counters: pkt = " TARGET_FMT_lx
                   ", insn = " TARGET_FMT_lx
                   ", hvx = " TARGET_FMT_lx "\n",
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 9efc6c88aa..fa6415936c 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -31,7 +31,6 @@
 
 TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
 TCGv hex_pred[NUM_PREGS];
-TCGv hex_next_PC;
 TCGv hex_this_PC;
 TCGv hex_slot_cancelled;
 TCGv hex_branch_taken;
@@ -120,7 +119,6 @@ static void gen_exec_counters(DisasContext *ctx)
 static void gen_end_tb(DisasContext *ctx)
 {
     gen_exec_counters(ctx);
-    tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
     tcg_gen_exit_tb(NULL, 0);
     ctx->base.is_jmp = DISAS_NORETURN;
 }
@@ -128,7 +126,7 @@ static void gen_end_tb(DisasContext *ctx)
 static void gen_exception_end_tb(DisasContext *ctx, int excp)
 {
     gen_exec_counters(ctx);
-    tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
+    tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
     gen_exception_raw(excp);
     ctx->base.is_jmp = DISAS_NORETURN;
 
@@ -204,6 +202,24 @@ static bool need_pred_written(Packet *pkt)
     return check_for_attrib(pkt, A_WRITES_PRED_REG);
 }
 
+static bool need_next_PC(DisasContext *ctx)
+{
+    Packet *pkt = ctx->pkt;
+
+    /* Check for conditional control flow or HW loop end */
+    for (int i = 0; i < pkt->num_insns; i++) {
+        uint16_t opcode = pkt->insn[i].opcode;
+        if (GET_ATTRIB(opcode, A_CONDEXEC) && GET_ATTRIB(opcode, A_COF)) {
+            return true;
+        }
+        if (GET_ATTRIB(opcode, A_HWLOOP0_END) ||
+            GET_ATTRIB(opcode, A_HWLOOP1_END)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 static void gen_start_packet(DisasContext *ctx)
 {
     Packet *pkt = ctx->pkt;
@@ -211,6 +227,7 @@ static void gen_start_packet(DisasContext *ctx)
     int i;
 
     /* Clear out the disassembly context */
+    ctx->next_PC = next_PC;
     ctx->reg_log_idx = 0;
     bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
     ctx->preg_log_idx = 0;
@@ -243,7 +260,9 @@ static void gen_start_packet(DisasContext *ctx)
         if (pkt->pkt_has_multi_cof) {
             tcg_gen_movi_tl(hex_branch_taken, 0);
         }
-        tcg_gen_movi_tl(hex_next_PC, next_PC);
+        if (need_next_PC(ctx)) {
+            tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
+        }
     }
     if (need_pred_written(pkt)) {
         tcg_gen_movi_tl(hex_pred_written, 0);
@@ -936,8 +955,6 @@ void hexagon_translate_init(void)
     }
     hex_pred_written = tcg_global_mem_new(cpu_env,
         offsetof(CPUHexagonState, pred_written), "pred_written");
-    hex_next_PC = tcg_global_mem_new(cpu_env,
-        offsetof(CPUHexagonState, next_PC), "next_PC");
     hex_this_PC = tcg_global_mem_new(cpu_env,
         offsetof(CPUHexagonState, this_PC), "this_PC");
     hex_slot_cancelled = tcg_global_mem_new(cpu_env,
diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index 024f70d166..00ee58f159 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -245,6 +245,10 @@ def gen_helper_function(f, tag, tagregs, tagimms):
             if i > 0: f.write(", ")
             f.write("target_ulong PC")
             i += 1
+        if hex_common.helper_needs_next_PC(tag):
+            if i > 0: f.write(", ")
+            f.write("target_ulong next_PC")
+            i += 1
         if hex_common.need_slot(tag):
             if i > 0: f.write(", ")
             f.write("uint32_t slot")
diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 00c48dff7c..ed4b9cf0d4 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -86,6 +86,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             if hex_common.need_PC(tag): def_helper_size += 1
+            if hex_common.helper_needs_next_PC(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
             ## The return type is void
             f.write(', void' )
@@ -95,6 +96,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             if hex_common.need_PC(tag): def_helper_size += 1
+            if hex_common.helper_needs_next_PC(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
 
         ## Generate the qemu DEF_HELPER type for each result
@@ -134,6 +136,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         ## part1 (if needed)
         if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
         if hex_common.need_PC(tag): f.write(', i32')
+        if hex_common.helper_needs_next_PC(tag): f.write(', i32')
         if hex_common.need_slot(tag): f.write(', i32' )
         if hex_common.need_part1(tag): f.write(' , i32' )
         f.write(')\n')
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 7dbdde3191..f4cea6dfc4 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -631,6 +631,8 @@ def gen_tcg_func(f, tag, regs, imms):
             f.write("    TCGv slot = tcg_constant_tl(insn->slot);\n")
         if hex_common.need_PC(tag):
             f.write("    TCGv PC = tcg_constant_tl(ctx->pkt->pc);\n")
+        if hex_common.helper_needs_next_PC(tag):
+            f.write("    TCGv next_PC = tcg_constant_tl(ctx->next_PC);\n")
         f.write("    gen_helper_%s(" % (tag))
         i=0
         ## If there is a scalar result, it is the return type
@@ -662,6 +664,7 @@ def gen_tcg_func(f, tag, regs, imms):
         if hex_common.need_pkt_has_multi_cof(tag):
             f.write(", pkt_has_multi_cof")
         if hex_common.need_PC(tag): f.write(", PC")
+        if hex_common.helper_needs_next_PC(tag): f.write(", next_PC")
         if hex_common.need_slot(tag): f.write(", slot")
         if hex_common.need_part1(tag): f.write(", part1" )
         f.write(");\n")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index cfe5fe7b35..da8e75fbc7 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -66,6 +66,18 @@ def add_qemu_macro_attrib(name, attrib):
     macros[name].attribs.add(attrib)
 
 immextre = re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])')
+
+def is_cond_jump(tag):
+    if tag == 'J2_rte':
+        return False
+    if ('A_HWLOOP0_END' in attribdict[tag] or
+        'A_HWLOOP1_END' in attribdict[tag]):
+        return False
+    return re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag])
+
+def is_cond_call(tag):
+    return re.compile(r"(if.*fCALL)").search(semdict[tag])
+
 def calculate_attribs():
     add_qemu_macro_attrib('fREAD_PC', 'A_IMPLICIT_READS_PC')
     add_qemu_macro_attrib('fTRAP', 'A_IMPLICIT_READS_PC')
@@ -96,6 +108,11 @@ def calculate_attribs():
         for regtype, regid, toss, numregs in regs:
             if regtype == "P" and is_written(regid):
                 attribdict[tag].add('A_WRITES_PRED_REG')
+    # Mark conditional jumps and calls
+    #     Not all instructions are properly marked with A_CONDEXEC
+    for tag in tags:
+        if is_cond_jump(tag) or is_cond_call(tag):
+            attribdict[tag].add('A_CONDEXEC')
 
 def SEMANTICS(tag, beh, sem):
     #print tag,beh,sem
@@ -211,6 +228,9 @@ def need_ea(tag):
 def need_PC(tag):
     return 'A_IMPLICIT_READS_PC' in attribdict[tag]
 
+def helper_needs_next_PC(tag):
+    return 'A_CALL' in attribdict[tag]
+
 def need_pkt_has_multi_cof(tag):
     return 'A_COF' in attribdict[tag]
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 07/11] Hexagon (target/hexagon) Add overrides for direct call instructions
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (5 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 06/11] Hexagon (target/hexagon) Remove next_PC from " Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 08/11] Hexagon (target/hexagon) Add overrides for compound compare and jump Taylor Simpson
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Add overrides for
    J2_call
    J2_callt
    J2_callf

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-8-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h |  8 ++++++
 target/hexagon/genptr.c  | 55 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index df279ab43b..1bdc787a02 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -612,6 +612,14 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+#define fGEN_TCG_J2_call(SHORTCODE) \
+    gen_call(ctx, riV)
+
+#define fGEN_TCG_J2_callt(SHORTCODE) \
+    gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
+#define fGEN_TCG_J2_callf(SHORTCODE) \
+    gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
+
 #define fGEN_TCG_J2_pause(SHORTCODE) \
     do { \
         uiV = uiV; \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cd3d74525e..580c403879 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -456,6 +456,61 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
     return result;
 }
 
+static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
+                                  TCGCond cond, TCGv pred)
+{
+    TCGLabel *pred_false = NULL;
+    if (cond != TCG_COND_ALWAYS) {
+        pred_false = gen_new_label();
+        tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
+    }
+
+    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],
+                           hex_branch_taken, tcg_constant_tl(0),
+                           hex_gpr[HEX_REG_PC], addr);
+        tcg_gen_movi_tl(hex_branch_taken, 1);
+    } else {
+        tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
+    }
+
+    if (cond != TCG_COND_ALWAYS) {
+        gen_set_label(pred_false);
+    }
+}
+
+static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
+                                   TCGCond cond, TCGv pred)
+{
+    target_ulong dest = ctx->pkt->pc + pc_off;
+    gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
+}
+
+static void gen_call(DisasContext *ctx, int pc_off)
+{
+    TCGv next_PC =
+        tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
+    gen_log_reg_write(HEX_REG_LR, next_PC);
+    gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
+}
+
+static void gen_cond_call(DisasContext *ctx, TCGv pred,
+                          TCGCond cond, int pc_off)
+{
+    TCGv next_PC;
+    TCGv lsb = tcg_temp_local_new();
+    TCGLabel *skip = gen_new_label();
+    tcg_gen_andi_tl(lsb, pred, 1);
+    gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
+    tcg_gen_brcondi_tl(cond, lsb, 0, skip);
+    tcg_temp_free(lsb);
+    next_PC =
+        tcg_constant_tl(ctx->pkt->pc + ctx->pkt->encod_pkt_size_in_bytes);
+    gen_log_reg_write(HEX_REG_LR, next_PC);
+    gen_set_label(skip);
+}
+
 /* Shift left with saturation */
 static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt)
 {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 08/11] Hexagon (target/hexagon) Add overrides for compound compare and jump
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (6 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 07/11] Hexagon (target/hexagon) Add overrides for direct call instructions Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 09/11] Hexagon (target/hexagon) Add overrides for various forms of jump Taylor Simpson
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-9-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h | 177 +++++++++++++++++++++++++++++++++++++++
 target/hexagon/genptr.c  |  90 ++++++++++++++++++++
 2 files changed, 267 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 1bdc787a02..506b454e4e 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -620,6 +620,183 @@
 #define fGEN_TCG_J2_callf(SHORTCODE) \
     gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
 
+/*
+ * Compound compare and jump instructions
+ * Here is a primer to understand the tag names
+ *
+ * Comparison
+ *      cmpeqi   compare equal to an immediate
+ *      cmpgti   compare greater than an immediate
+ *      cmpgtiu  compare greater than an unsigned immediate
+ *      cmpeqn1  compare equal to negative 1
+ *      cmpgtn1  compare greater than negative 1
+ *      cmpeq    compare equal (two registers)
+ *      cmpgtu   compare greater than unsigned (two registers)
+ *      tstbit0  test bit zero
+ *
+ * Condition
+ *      tp0      p0 is true     p0 = cmp.eq(r0,#5); if (p0.new) jump:nt address
+ *      fp0      p0 is false    p0 = cmp.eq(r0,#5); if (!p0.new) jump:nt address
+ *      tp1      p1 is true     p1 = cmp.eq(r0,#5); if (p1.new) jump:nt address
+ *      fp1      p1 is false    p1 = cmp.eq(r0,#5); if (!p1.new) jump:nt address
+ *
+ * Prediction (not modelled in qemu)
+ *      _nt      not taken
+ *      _t       taken
+ */
+#define fGEN_TCG_J4_cmpeq_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
+
+#define fGEN_TCG_J4_cmpgt_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
+
+#define fGEN_TCG_J4_cmpgtu_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
+
+#define fGEN_TCG_J4_cmpeqi_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
+
+#define fGEN_TCG_J4_cmpgti_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
+
+#define fGEN_TCG_J4_cmpgtui_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
+
+#define fGEN_TCG_J4_cmpeqn1_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_EQ, RsV, riV)
+#define fGEN_TCG_J4_cmpeqn1_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_EQ, RsV, riV)
+
+#define fGEN_TCG_J4_cmpgtn1_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
+#define fGEN_TCG_J4_cmpgtn1_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
+
+#define fGEN_TCG_J4_tstbit0_tp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_tp0_jump_t(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_fp0_jump_nt(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
+#define fGEN_TCG_J4_tstbit0_fp0_jump_t(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
+#define fGEN_TCG_J4_tstbit0_tp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_tp1_jump_t(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_fp1_jump_nt(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
+#define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
+    gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
+
 #define fGEN_TCG_J2_pause(SHORTCODE) \
     do { \
         uiV = uiV; \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 580c403879..c003800247 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -487,6 +487,96 @@ static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
     gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
 }
 
+static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
+{
+    TCGv one = tcg_constant_tl(0xff);
+    TCGv zero = tcg_constant_tl(0);
+
+    tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
+}
+
+static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
+                          int pc_off)
+{
+    gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
+}
+
+static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
+                              int pnum, TCGCond cond1, TCGv arg1, TCGv arg2,
+                              TCGCond cond2, int pc_off)
+{
+    if (ctx->insn->part1) {
+        TCGv pred = tcg_temp_new();
+        gen_compare(cond1, pred, arg1, arg2);
+        gen_log_pred_write(ctx, pnum, pred);
+        tcg_temp_free(pred);
+    } else {
+        TCGv pred = tcg_temp_new();
+        tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
+        gen_cond_jump(ctx, cond2, pred, pc_off);
+        tcg_temp_free(pred);
+    }
+}
+
+static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
+                                int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
+                                int pc_off)
+{
+    gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
+}
+
+static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
+                                int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
+                                int pc_off)
+{
+    gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
+}
+
+static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
+                                 int pnum, TCGCond cond, TCGv arg1, int arg2,
+                                 int pc_off)
+{
+    TCGv tmp = tcg_constant_tl(arg2);
+    gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
+}
+
+static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
+                                 int pnum, TCGCond cond, TCGv arg1, int arg2,
+                                 int pc_off)
+{
+    TCGv tmp = tcg_constant_tl(arg2);
+    gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
+}
+
+static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
+                                   TCGv arg, int pc_off)
+{
+    gen_cmpnd_cmpi_jmp_t(ctx, pnum, cond, arg, -1, pc_off);
+}
+
+static void gen_cmpnd_cmp_n1_jmp_f(DisasContext *ctx, int pnum, TCGCond cond,
+                                   TCGv arg, int pc_off)
+{
+    gen_cmpnd_cmpi_jmp_f(ctx, pnum, cond, arg, -1, pc_off);
+}
+
+static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
+                                  int pnum, TCGv arg, TCGCond cond, int pc_off)
+{
+    if (ctx->insn->part1) {
+        TCGv pred = tcg_temp_new();
+        tcg_gen_andi_tl(pred, arg, 1);
+        gen_8bitsof(pred, pred);
+        gen_log_pred_write(ctx, pnum, pred);
+        tcg_temp_free(pred);
+    } else {
+        TCGv pred = tcg_temp_new();
+        tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
+        gen_cond_jump(ctx, cond, pred, pc_off);
+        tcg_temp_free(pred);
+    }
+}
+
 static void gen_call(DisasContext *ctx, int pc_off)
 {
     TCGv next_PC =
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 09/11] Hexagon (target/hexagon) Add overrides for various forms of jump
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (7 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 08/11] Hexagon (target/hexagon) Add overrides for compound compare and jump Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 10/11] Hexagon (target/hexagon) Use direct block chaining for direct jump/branch Taylor Simpson
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-10-tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h | 201 +++++++++++++++++++++++++++++++++++++++
 target/hexagon/genptr.c  |  43 +++++++++
 2 files changed, 244 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 506b454e4e..3583f390e9 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -797,6 +797,207 @@
 #define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
     gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
 
+#define fGEN_TCG_J2_jump(SHORTCODE) \
+    gen_jump(ctx, riV)
+#define fGEN_TCG_J2_jumpr(SHORTCODE) \
+    gen_jumpr(ctx, RsV)
+#define fGEN_TCG_J4_jumpseti(SHORTCODE) \
+    do { \
+        tcg_gen_movi_tl(RdV, UiV); \
+        gen_jump(ctx, riV); \
+    } while (0)
+
+#define fGEN_TCG_cond_jumpt(COND) \
+    do { \
+        TCGv LSB = tcg_temp_new(); \
+        COND; \
+        gen_cond_jump(ctx, TCG_COND_EQ, LSB, riV); \
+        tcg_temp_free(LSB); \
+    } while (0)
+#define fGEN_TCG_cond_jumpf(COND) \
+    do { \
+        TCGv LSB = tcg_temp_new(); \
+        COND; \
+        gen_cond_jump(ctx, TCG_COND_NE, LSB, riV); \
+        tcg_temp_free(LSB); \
+    } while (0)
+
+#define fGEN_TCG_J2_jumpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumptpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumpf(SHORTCODE) \
+    fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumpfpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumptnew(SHORTCODE) \
+    gen_cond_jump(ctx, TCG_COND_EQ, PuN, riV)
+#define fGEN_TCG_J2_jumptnewpt(SHORTCODE) \
+    gen_cond_jump(ctx, TCG_COND_EQ, PuN, riV)
+#define fGEN_TCG_J2_jumpfnewpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
+#define fGEN_TCG_J2_jumpfnew(SHORTCODE) \
+    fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
+#define fGEN_TCG_J2_jumprz(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprzpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprnz(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_EQ, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprnzpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_EQ, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprgtez(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_GE, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprgtezpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_GE, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprltez(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
+#define fGEN_TCG_J2_jumprltezpt(SHORTCODE) \
+    fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
+
+#define fGEN_TCG_cond_jumprt(COND) \
+    do { \
+        TCGv LSB = tcg_temp_new(); \
+        COND; \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_EQ, LSB); \
+        tcg_temp_free(LSB); \
+    } while (0)
+#define fGEN_TCG_cond_jumprf(COND) \
+    do { \
+        TCGv LSB = tcg_temp_new(); \
+        COND; \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_NE, LSB); \
+        tcg_temp_free(LSB); \
+    } while (0)
+
+#define fGEN_TCG_J2_jumprt(SHORTCODE) \
+    fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumprtpt(SHORTCODE) \
+    fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumprf(SHORTCODE) \
+    fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumprfpt(SHORTCODE) \
+    fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
+#define fGEN_TCG_J2_jumprtnew(SHORTCODE) \
+    fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
+#define fGEN_TCG_J2_jumprtnewpt(SHORTCODE) \
+    fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
+#define fGEN_TCG_J2_jumprfnew(SHORTCODE) \
+    fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
+#define fGEN_TCG_J2_jumprfnewpt(SHORTCODE) \
+    fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
+
+/*
+ * New value compare & jump instructions
+ * if ([!]COND(r0.new, r1) jump:t address
+ * if ([!]COND(r0.new, #7) jump:t address
+ */
+#define fGEN_TCG_J4_cmpgt_t_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GT, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_t_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GT, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_f_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LE, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgt_f_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LE, NsN, RtV, riV)
+
+#define fGEN_TCG_J4_cmpeq_t_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_EQ, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_t_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_EQ, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_f_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_NE, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpeq_f_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_NE, NsN, RtV, riV)
+
+#define fGEN_TCG_J4_cmplt_t_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LT, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmplt_t_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LT, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmplt_f_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GE, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmplt_f_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GE, NsN, RtV, riV)
+
+#define fGEN_TCG_J4_cmpeqi_t_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_t_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_f_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpeqi_f_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, UiV, riV)
+
+#define fGEN_TCG_J4_cmpgti_t_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_t_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_f_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgti_f_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, UiV, riV)
+
+#define fGEN_TCG_J4_cmpltu_t_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LTU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpltu_t_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LTU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpltu_f_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GEU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpltu_f_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GEU, NsN, RtV, riV)
+
+#define fGEN_TCG_J4_cmpgtui_t_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GTU, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_t_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GTU, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_f_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LEU, NsN, UiV, riV)
+#define fGEN_TCG_J4_cmpgtui_f_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LEU, NsN, UiV, riV)
+
+#define fGEN_TCG_J4_cmpgtu_t_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GTU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_t_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_GTU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_f_jumpnv_t(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LEU, NsN, RtV, riV)
+#define fGEN_TCG_J4_cmpgtu_f_jumpnv_nt(SHORTCODE) \
+    gen_cmp_jumpnv(ctx, TCG_COND_LEU, NsN, RtV, riV)
+
+#define fGEN_TCG_J4_cmpeqn1_t_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpeqn1_t_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpeqn1_f_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpeqn1_f_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, -1, riV)
+
+#define fGEN_TCG_J4_cmpgtn1_t_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpgtn1_t_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpgtn1_f_jumpnv_t(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
+#define fGEN_TCG_J4_cmpgtn1_f_jumpnv_nt(SHORTCODE) \
+    gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
+
+#define fGEN_TCG_J4_tstbit0_t_jumpnv_t(SHORTCODE) \
+    gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_t_jumpnv_nt(SHORTCODE) \
+    gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
+#define fGEN_TCG_J4_tstbit0_f_jumpnv_t(SHORTCODE) \
+    gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
+#define fGEN_TCG_J4_tstbit0_f_jumpnv_nt(SHORTCODE) \
+    gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
+
+/* r0 = r1 ; jump address */
+#define fGEN_TCG_J4_jumpsetr(SHORTCODE) \
+    do { \
+        tcg_gen_mov_tl(RdV, RsV); \
+        gen_jump(ctx, riV); \
+    } while (0)
+
 #define fGEN_TCG_J2_pause(SHORTCODE) \
     do { \
         uiV = uiV; \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index c003800247..be9c715ea8 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -495,6 +495,12 @@ static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
     tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
 }
 
+static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
+                           TCGCond cond, TCGv pred)
+{
+    gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
+}
+
 static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
                           int pc_off)
 {
@@ -577,6 +583,25 @@ static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
     }
 }
 
+static void gen_testbit0_jumpnv(DisasContext *ctx,
+                                TCGv arg, TCGCond cond, int pc_off)
+{
+    TCGv pred = tcg_temp_new();
+    tcg_gen_andi_tl(pred, arg, 1);
+    gen_cond_jump(ctx, cond, pred, pc_off);
+    tcg_temp_free(pred);
+}
+
+static void gen_jump(DisasContext *ctx, int pc_off)
+{
+    gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
+}
+
+static void gen_jumpr(DisasContext *ctx, TCGv new_pc)
+{
+    gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
+}
+
 static void gen_call(DisasContext *ctx, int pc_off)
 {
     TCGv next_PC =
@@ -601,6 +626,24 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
     gen_set_label(skip);
 }
 
+static void gen_cmp_jumpnv(DisasContext *ctx,
+                           TCGCond cond, TCGv val, TCGv src, int pc_off)
+{
+    TCGv pred = tcg_temp_new();
+    tcg_gen_setcond_tl(cond, pred, val, src);
+    gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
+    tcg_temp_free(pred);
+}
+
+static void gen_cmpi_jumpnv(DisasContext *ctx,
+                            TCGCond cond, TCGv val, int src, int pc_off)
+{
+    TCGv pred = tcg_temp_new();
+    tcg_gen_setcondi_tl(cond, pred, val, src);
+    gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
+    tcg_temp_free(pred);
+}
+
 /* Shift left with saturation */
 static void gen_shl_sat(TCGv dst, TCGv src, TCGv shift_amt)
 {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 10/11] Hexagon (target/hexagon) Use direct block chaining for direct jump/branch
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (8 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 09/11] Hexagon (target/hexagon) Add overrides for various forms of jump Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  0:52 ` [PULL 11/11] Hexagon (target/hexagon) Use direct block chaining for tight loops Taylor Simpson
  2022-11-11  1:06 ` [PULL 00/11] Hexagon bug fixes and performance improvement Stefan Hajnoczi
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Direct block chaining is documented here
https://qemu.readthedocs.io/en/latest/devel/tcg.html#direct-block-chaining

Recall that Hexagon allows packets with multiple jumps where only the
first one with a true predicate will actually jump.  We can  use
tcg_gen_goto_tb/tcg_gen_exit_tb when the packet contains a single
PC-relative branch or jump.  If not, we use tcg_gen_lookup_and_goto_ptr.

We add the following to DisasContext in order to delay the branching
until the end of packet commit (in gen_end_tb)
    branch_cond
        The TCGCond condition under which the branch is taken
        When branch_cond == TCG_COND_NEVER, there isn't a single
        direct branch in this packet.
        When branch_cond != TCG_COND_ALWAYS, the value is in
        hex_branch_taken
    branch_dest
        The destination of the branch

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-11-tsimpson@quicinc.com>
---
 target/hexagon/translate.h |  2 ++
 target/hexagon/genptr.c    | 12 +++++++++++-
 target/hexagon/translate.c | 34 +++++++++++++++++++++++++++++++++-
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 96509a4da7..aacf0b0921 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -57,6 +57,8 @@ typedef struct DisasContext {
     bool qreg_is_predicated[NUM_QREGS];
     int qreg_log_idx;
     bool pre_commit;
+    TCGCond branch_cond;
+    target_ulong branch_dest;
 } DisasContext;
 
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index be9c715ea8..ee0f86fab2 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -484,7 +484,17 @@ static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
                                    TCGCond cond, TCGv pred)
 {
     target_ulong dest = ctx->pkt->pc + pc_off;
-    gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
+    if (ctx->pkt->pkt_has_multi_cof) {
+        gen_write_new_pc_addr(ctx, tcg_constant_tl(dest), cond, pred);
+    } else {
+        /* Defer this jump to the end of the TB */
+        ctx->branch_cond = TCG_COND_ALWAYS;
+        if (pred != NULL) {
+            ctx->branch_cond = cond;
+            tcg_gen_mov_tl(hex_branch_taken, pred);
+        }
+        ctx->branch_dest = dest;
+    }
 }
 
 static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index fa6415936c..f5ef54f039 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -116,10 +116,41 @@ static void gen_exec_counters(DisasContext *ctx)
                     hex_gpr[HEX_REG_QEMU_HVX_CNT], ctx->num_hvx_insns);
 }
 
+static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
+{
+    return translator_use_goto_tb(&ctx->base, dest);
+}
+
+static void gen_goto_tb(DisasContext *ctx, int idx, target_ulong dest)
+{
+    if (use_goto_tb(ctx, dest)) {
+        tcg_gen_goto_tb(idx);
+        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
+        tcg_gen_exit_tb(ctx->base.tb, idx);
+    } else {
+        tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], dest);
+        tcg_gen_lookup_and_goto_ptr();
+    }
+}
+
 static void gen_end_tb(DisasContext *ctx)
 {
     gen_exec_counters(ctx);
-    tcg_gen_exit_tb(NULL, 0);
+
+    if (ctx->branch_cond != TCG_COND_NEVER) {
+        if (ctx->branch_cond != TCG_COND_ALWAYS) {
+            TCGLabel *skip = gen_new_label();
+            tcg_gen_brcondi_tl(ctx->branch_cond, hex_branch_taken, 0, skip);
+            gen_goto_tb(ctx, 0, ctx->branch_dest);
+            gen_set_label(skip);
+            gen_goto_tb(ctx, 1, ctx->next_PC);
+        } else {
+            gen_goto_tb(ctx, 0, ctx->branch_dest);
+        }
+    } else {
+        tcg_gen_lookup_and_goto_ptr();
+    }
+
     ctx->base.is_jmp = DISAS_NORETURN;
 }
 
@@ -807,6 +838,7 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
     ctx->num_packets = 0;
     ctx->num_insns = 0;
     ctx->num_hvx_insns = 0;
+    ctx->branch_cond = TCG_COND_NEVER;
 }
 
 static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PULL 11/11] Hexagon (target/hexagon) Use direct block chaining for tight loops
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (9 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 10/11] Hexagon (target/hexagon) Use direct block chaining for direct jump/branch Taylor Simpson
@ 2022-11-11  0:52 ` Taylor Simpson
  2022-11-11  1:06 ` [PULL 00/11] Hexagon bug fixes and performance improvement Stefan Hajnoczi
  11 siblings, 0 replies; 17+ messages in thread
From: Taylor Simpson @ 2022-11-11  0:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: tsimpson, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Direct block chaining is documented here
https://qemu.readthedocs.io/en/latest/devel/tcg.html#direct-block-chaining

Hexagon inner loops end with the endloop0 instruction
To go back to the beginning of the loop, this instructions writes to PC
from register SA0 (start address 0).  To use direct block chaining, we
have to assign PC with a constant value.  So, we specialize the code
generation when the start of the translation block is equal to SA0.

When this is the case, we defer the compare/branch from endloop0 to
gen_end_tb.  When this is done, we can assign the start address of the TB
to PC.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-12-tsimpson@quicinc.com>
---
 target/hexagon/cpu.h       | 13 +++---
 target/hexagon/gen_tcg.h   |  3 ++
 target/hexagon/translate.h |  1 +
 target/hexagon/genptr.c    | 84 ++++++++++++++++++++++++++++++++++++++
 target/hexagon/translate.c | 33 +++++++++++++++
 5 files changed, 129 insertions(+), 5 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index ff8c26272d..1d89e11a1a 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -25,6 +25,7 @@
 #include "mmvec/mmvec.h"
 #include "qom/object.h"
 #include "hw/core/cpu.h"
+#include "hw/registerfields.h"
 
 #define NUM_PREGS 4
 #define TOTAL_PER_THREAD_REGS 64
@@ -152,16 +153,18 @@ struct ArchCPU {
 
 #include "cpu_bits.h"
 
+FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
+
 static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
 {
+    uint32_t hex_flags = 0;
     *pc = env->gpr[HEX_REG_PC];
     *cs_base = 0;
-#ifdef CONFIG_USER_ONLY
-    *flags = 0;
-#else
-#error System mode not supported on Hexagon yet
-#endif
+    if (*pc == env->gpr[HEX_REG_SA0]) {
+        hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
+    }
+    *flags = hex_flags;
 }
 
 static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 3583f390e9..19697b42a5 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -620,6 +620,9 @@
 #define fGEN_TCG_J2_callf(SHORTCODE) \
     gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
 
+#define fGEN_TCG_J2_endloop0(SHORTCODE) \
+    gen_endloop0(ctx)
+
 /*
  * Compound compare and jump instructions
  * Here is a primer to understand the tag names
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index aacf0b0921..d971f4f095 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -59,6 +59,7 @@ typedef struct DisasContext {
     bool pre_commit;
     TCGCond branch_cond;
     target_ulong branch_dest;
+    bool is_tight_loop;
 } DisasContext;
 
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index ee0f86fab2..a4a79c8454 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -497,6 +497,33 @@ static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
     }
 }
 
+static void gen_set_usr_field(int field, TCGv val)
+{
+    tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
+                       val,
+                       reg_field_info[field].offset,
+                       reg_field_info[field].width);
+}
+
+static void gen_set_usr_fieldi(int field, int x)
+{
+    if (reg_field_info[field].width == 1) {
+        target_ulong bit = 1 << reg_field_info[field].offset;
+        if ((x & 1) == 1) {
+            tcg_gen_ori_tl(hex_new_value[HEX_REG_USR],
+                           hex_new_value[HEX_REG_USR],
+                           bit);
+        } else {
+            tcg_gen_andi_tl(hex_new_value[HEX_REG_USR],
+                            hex_new_value[HEX_REG_USR],
+                            ~bit);
+        }
+    } else {
+        TCGv val = tcg_constant_tl(x);
+        gen_set_usr_field(field, val);
+    }
+}
+
 static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
 {
     TCGv one = tcg_constant_tl(0xff);
@@ -636,6 +663,63 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
     gen_set_label(skip);
 }
 
+static void gen_endloop0(DisasContext *ctx)
+{
+    TCGv lpcfg = tcg_temp_local_new();
+
+    GET_USR_FIELD(USR_LPCFG, lpcfg);
+
+    /*
+     *    if (lpcfg == 1) {
+     *        hex_new_pred_value[3] = 0xff;
+     *        hex_pred_written |= 1 << 3;
+     *    }
+     */
+    TCGLabel *label1 = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
+    {
+        tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
+        tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
+    }
+    gen_set_label(label1);
+
+    /*
+     *    if (lpcfg) {
+     *        SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
+     *    }
+     */
+    TCGLabel *label2 = gen_new_label();
+    tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
+    {
+        tcg_gen_subi_tl(lpcfg, lpcfg, 1);
+        SET_USR_FIELD(USR_LPCFG, lpcfg);
+    }
+    gen_set_label(label2);
+
+    /*
+     * If we're in a tight loop, we'll do this at the end of the TB to take
+     * advantage of direct block chaining.
+     */
+    if (!ctx->is_tight_loop) {
+        /*
+         *    if (hex_gpr[HEX_REG_LC0] > 1) {
+         *        PC = hex_gpr[HEX_REG_SA0];
+         *        hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
+         *    }
+         */
+        TCGLabel *label3 = gen_new_label();
+        tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
+        {
+            gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
+            tcg_gen_subi_tl(hex_new_value[HEX_REG_LC0],
+                            hex_gpr[HEX_REG_LC0], 1);
+        }
+        gen_set_label(label3);
+    }
+
+    tcg_temp_free(lpcfg);
+}
+
 static void gen_cmp_jumpnv(DisasContext *ctx,
                            TCGCond cond, TCGv val, TCGv src, int pc_off)
 {
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index f5ef54f039..2de434d57f 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -135,6 +135,8 @@ static void gen_goto_tb(DisasContext *ctx, int idx, target_ulong dest)
 
 static void gen_end_tb(DisasContext *ctx)
 {
+    Packet *pkt = ctx->pkt;
+
     gen_exec_counters(ctx);
 
     if (ctx->branch_cond != TCG_COND_NEVER) {
@@ -147,6 +149,18 @@ static void gen_end_tb(DisasContext *ctx)
         } else {
             gen_goto_tb(ctx, 0, ctx->branch_dest);
         }
+    } else if (ctx->is_tight_loop &&
+        pkt->insn[pkt->num_insns - 1].opcode == J2_endloop0) {
+        /*
+         * When we're in a tight loop, we defer the endloop0 processing
+         * to take advantage of direct block chaining
+         */
+        TCGLabel *skip = gen_new_label();
+        tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, skip);
+        tcg_gen_subi_tl(hex_gpr[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
+        gen_goto_tb(ctx, 0, ctx->base.tb->pc);
+        gen_set_label(skip);
+        gen_goto_tb(ctx, 1, ctx->next_PC);
     } else {
         tcg_gen_lookup_and_goto_ptr();
     }
@@ -337,6 +351,15 @@ static void mark_implicit_reg_write(DisasContext *ctx, int attrib, int rnum)
          */
         bool is_predicated = GET_ATTRIB(opcode, A_CONDEXEC) ||
                              rnum == HEX_REG_USR;
+
+        /* LC0/LC1 is conditionally written by endloop instructions */
+        if ((rnum == HEX_REG_LC0 || rnum == HEX_REG_LC1) &&
+            (opcode == J2_endloop0 ||
+             opcode == J2_endloop1 ||
+             opcode == J2_endloop01)) {
+            is_predicated = true;
+        }
+
         if (is_predicated && !is_preloaded(ctx, rnum)) {
             tcg_gen_mov_tl(hex_new_value[rnum], hex_gpr[rnum]);
         }
@@ -420,6 +443,14 @@ static void gen_reg_writes(DisasContext *ctx)
         int reg_num = ctx->reg_log[i];
 
         tcg_gen_mov_tl(hex_gpr[reg_num], hex_new_value[reg_num]);
+
+        /*
+         * ctx->is_tight_loop is set when SA0 points to the beginning of the TB.
+         * If we write to SA0, we have to turn off tight loop handling.
+         */
+        if (reg_num == HEX_REG_SA0) {
+            ctx->is_tight_loop = false;
+        }
     }
 }
 
@@ -833,12 +864,14 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
                                           CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    uint32_t hex_flags = dcbase->tb->flags;
 
     ctx->mem_idx = MMU_USER_IDX;
     ctx->num_packets = 0;
     ctx->num_insns = 0;
     ctx->num_hvx_insns = 0;
     ctx->branch_cond = TCG_COND_NEVER;
+    ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
 }
 
 static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PULL 00/11] Hexagon bug fixes and performance improvement
  2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
                   ` (10 preceding siblings ...)
  2022-11-11  0:52 ` [PULL 11/11] Hexagon (target/hexagon) Use direct block chaining for tight loops Taylor Simpson
@ 2022-11-11  1:06 ` Stefan Hajnoczi
  2022-11-15 16:16   ` Taylor Simpson
  11 siblings, 1 reply; 17+ messages in thread
From: Stefan Hajnoczi @ 2022-11-11  1:06 UTC (permalink / raw)
  To: Taylor Simpson
  Cc: qemu-devel, richard.henderson, philmd, peter.maydell, bcain,
	quic_mathbern, stefanha

Hi Taylor,
QEMU is frozen for the 7.2 release cycle. Only bug fixes can be merged
as the tree is being stabilized. You can find the release schedule
here:
https://wiki.qemu.org/Planning/7.2

Please resend with only the bug fixes needed for the 7.2 release. Thanks!

Stefan


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PULL 00/11] Hexagon bug fixes and performance improvement
  2022-11-11  1:06 ` [PULL 00/11] Hexagon bug fixes and performance improvement Stefan Hajnoczi
@ 2022-11-15 16:16   ` Taylor Simpson
  2022-11-15 16:52     ` Stefan Hajnoczi
  0 siblings, 1 reply; 17+ messages in thread
From: Taylor Simpson @ 2022-11-15 16:16 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, richard.henderson, philmd, peter.maydell, Brian Cain,
	Matheus Bernardino (QUIC),
	stefanha

OK.  I wasn't sure if performance improvements would be considered new features or not.

Taylor


> -----Original Message-----
> From: Stefan Hajnoczi <stefanha@gmail.com>
> Sent: Thursday, November 10, 2022 7:07 PM
> To: Taylor Simpson <tsimpson@quicinc.com>
> Cc: qemu-devel@nongnu.org; richard.henderson@linaro.org;
> philmd@linaro.org; peter.maydell@linaro.org; Brian Cain
> <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; stefanha@redhat.com
> Subject: Re: [PULL 00/11] Hexagon bug fixes and performance improvement
> 
> Hi Taylor,
> QEMU is frozen for the 7.2 release cycle. Only bug fixes can be merged as the
> tree is being stabilized. You can find the release schedule
> here:
> https://wiki.qemu.org/Planning/7.2
> 
> Please resend with only the bug fixes needed for the 7.2 release. Thanks!
> 
> Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PULL 00/11] Hexagon bug fixes and performance improvement
  2022-11-15 16:16   ` Taylor Simpson
@ 2022-11-15 16:52     ` Stefan Hajnoczi
  2022-11-15 17:44       ` Taylor Simpson
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Hajnoczi @ 2022-11-15 16:52 UTC (permalink / raw)
  To: Taylor Simpson
  Cc: qemu-devel, richard.henderson, philmd, peter.maydell, Brian Cain,
	Matheus Bernardino (QUIC),
	stefanha

On Tue, 15 Nov 2022 at 11:16, Taylor Simpson <tsimpson@quicinc.com> wrote:
>
> OK.  I wasn't sure if performance improvements would be considered new features or not.

No problem! If there is a performance regression in the upcoming
release, then fixes will be accepted. For example, if QEMU 7.1 was
fast but the upcoming QEMU 7.2 release is going to be slow then a
performance fix will be accepted to avoid a regression in 7.2.

On the other hand, if it's a fix for something that was already slow
in the last release (7.1), then it's less likely to be accepted during
freeze.

These are general guidelines and maintainers have a say in what gets
merged. In this case I looked at the pull request and I wasn't sure if
you had decided based on these guidelines or not. It helps when it's
clear from the commit message (or from the commit description in more
involved cases) that the commit fixes a bug or has some other
justification.

Thanks,
Stefan


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PULL 00/11] Hexagon bug fixes and performance improvement
  2022-11-15 16:52     ` Stefan Hajnoczi
@ 2022-11-15 17:44       ` Taylor Simpson
  2022-11-15 18:42         ` Stefan Hajnoczi
  0 siblings, 1 reply; 17+ messages in thread
From: Taylor Simpson @ 2022-11-15 17:44 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, richard.henderson, philmd, peter.maydell, Brian Cain,
	Matheus Bernardino (QUIC),
	stefanha



> -----Original Message-----
> From: Stefan Hajnoczi <stefanha@gmail.com>
> Sent: Tuesday, November 15, 2022 10:52 AM
> To: Taylor Simpson <tsimpson@quicinc.com>
> Cc: qemu-devel@nongnu.org; richard.henderson@linaro.org;
> philmd@linaro.org; peter.maydell@linaro.org; Brian Cain
> <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; stefanha@redhat.com
> Subject: Re: [PULL 00/11] Hexagon bug fixes and performance improvement
> 
> On Tue, 15 Nov 2022 at 11:16, Taylor Simpson <tsimpson@quicinc.com>
> wrote:
> >
> > OK.  I wasn't sure if performance improvements would be considered new
> features or not.
> 
> No problem! If there is a performance regression in the upcoming release,
> then fixes will be accepted. For example, if QEMU 7.1 was fast but the
> upcoming QEMU 7.2 release is going to be slow then a performance fix will
> be accepted to avoid a regression in 7.2.
> 
> On the other hand, if it's a fix for something that was already slow in the last
> release (7.1), then it's less likely to be accepted during freeze.

The performance improvements fall into this bucket.

> 
> These are general guidelines and maintainers have a say in what gets
> merged. In this case I looked at the pull request and I wasn't sure if you had
> decided based on these guidelines or not. It helps when it's clear from the
> commit message (or from the commit description in more involved cases)
> that the commit fixes a bug or has some other justification.

I'm the maintainer for the directories touched by these patches (target/hexagon and tests/tcg/hexagon), but I'll defer you as a more senior maintainer to decide not to merge if it is too risky at this stage.

Taylor
 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PULL 00/11] Hexagon bug fixes and performance improvement
  2022-11-15 17:44       ` Taylor Simpson
@ 2022-11-15 18:42         ` Stefan Hajnoczi
  0 siblings, 0 replies; 17+ messages in thread
From: Stefan Hajnoczi @ 2022-11-15 18:42 UTC (permalink / raw)
  To: Taylor Simpson
  Cc: qemu-devel, Richard Henderson, Philippe Mathieu-Daudé,
	Peter Maydell, Brian Cain, Matheus Bernardino (QUIC),
	Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 1877 bytes --]

On Tue, Nov 15, 2022, 12:44 Taylor Simpson <tsimpson@quicinc.com> wrote:

>
>
> > -----Original Message-----
> > From: Stefan Hajnoczi <stefanha@gmail.com>
> > Sent: Tuesday, November 15, 2022 10:52 AM
> > To: Taylor Simpson <tsimpson@quicinc.com>
> > Cc: qemu-devel@nongnu.org; richard.henderson@linaro.org;
> > philmd@linaro.org; peter.maydell@linaro.org; Brian Cain
> > <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> > <quic_mathbern@quicinc.com>; stefanha@redhat.com
> > Subject: Re: [PULL 00/11] Hexagon bug fixes and performance improvement
> >
> > On Tue, 15 Nov 2022 at 11:16, Taylor Simpson <tsimpson@quicinc.com>
> > wrote:
> > >
> > > OK.  I wasn't sure if performance improvements would be considered new
> > features or not.
> >
> > No problem! If there is a performance regression in the upcoming release,
> > then fixes will be accepted. For example, if QEMU 7.1 was fast but the
> > upcoming QEMU 7.2 release is going to be slow then a performance fix will
> > be accepted to avoid a regression in 7.2.
> >
> > On the other hand, if it's a fix for something that was already slow in
> the last
> > release (7.1), then it's less likely to be accepted during freeze.
>
> The performance improvements fall into this bucket.
>
> >
> > These are general guidelines and maintainers have a say in what gets
> > merged. In this case I looked at the pull request and I wasn't sure if
> you had
> > decided based on these guidelines or not. It helps when it's clear from
> the
> > commit message (or from the commit description in more involved cases)
> > that the commit fixes a bug or has some other justification.
>
> I'm the maintainer for the directories touched by these patches
> (target/hexagon and tests/tcg/hexagon), but I'll defer you as a more senior
> maintainer to decide not to merge if it is too risky at this stage.
>

Thanks!

Stefan


> Taylor
>
>
>

[-- Attachment #2: Type: text/html, Size: 3473 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-11-15 18:43 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-11  0:52 [PULL 00/11] Hexagon bug fixes and performance improvement Taylor Simpson
2022-11-11  0:52 ` [PULL 01/11] Hexagon (target/hexagon) Add pkt and insn to DisasContext Taylor Simpson
2022-11-11  0:52 ` [PULL 02/11] Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur Taylor Simpson
2022-11-11  0:52 ` [PULL 03/11] Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
2022-11-11  0:52 ` [PULL 04/11] Hexagon (target/hexagon) Only use branch_taken when packet has multi cof Taylor Simpson
2022-11-11  0:52 ` [PULL 05/11] Hexagon (target/hexagon) Remove PC from the runtime state Taylor Simpson
2022-11-11  0:52 ` [PULL 06/11] Hexagon (target/hexagon) Remove next_PC from " Taylor Simpson
2022-11-11  0:52 ` [PULL 07/11] Hexagon (target/hexagon) Add overrides for direct call instructions Taylor Simpson
2022-11-11  0:52 ` [PULL 08/11] Hexagon (target/hexagon) Add overrides for compound compare and jump Taylor Simpson
2022-11-11  0:52 ` [PULL 09/11] Hexagon (target/hexagon) Add overrides for various forms of jump Taylor Simpson
2022-11-11  0:52 ` [PULL 10/11] Hexagon (target/hexagon) Use direct block chaining for direct jump/branch Taylor Simpson
2022-11-11  0:52 ` [PULL 11/11] Hexagon (target/hexagon) Use direct block chaining for tight loops Taylor Simpson
2022-11-11  1:06 ` [PULL 00/11] Hexagon bug fixes and performance improvement Stefan Hajnoczi
2022-11-15 16:16   ` Taylor Simpson
2022-11-15 16:52     ` Stefan Hajnoczi
2022-11-15 17:44       ` Taylor Simpson
2022-11-15 18:42         ` Stefan Hajnoczi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.