qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/15] target-hexagon queue, hexagon docker
@ 2024-01-22  6:34 Brian Cain
  2024-01-22  6:34 ` [PULL 01/15] tests/docker: Hexagon toolchain update Brian Cain
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

The following changes since commit 3f2a357b95845ea0bf7463eff6661e43b97d1afc:

  Merge tag 'hw-cpus-20240119' of https://github.com/philmd/qemu into staging (2024-01-19 11:39:38 +0000)

are available in the Git repository at:

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

for you to fetch changes up to bbe4209c8b4300d722f47791f9151e1a69cb0135:

  target/hexagon: reduce scope of def_regnum, remove dead assignment (2024-01-21 22:02:48 -0800)

----------------------------------------------------------------
Coverity fix, cross toolchain update, switch to decodetree

----------------------------------------------------------------
Brian Cain (2):
      tests/docker: Hexagon toolchain update
      target/hexagon: reduce scope of def_regnum, remove dead assignment

Taylor Simpson (13):
      Hexagon (target/hexagon) Fix shadow variable when idef-parser is off
      Hexagon (target/hexagon) Clean up handling of modifier registers
      Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs
      Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
      Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs
      Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs
      Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
      Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs
      Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
      Hexagon (target/hexagon) Remove dead functions from hex_common.py
      Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)
      Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)
      Hexagon (target/hexagon) Remove old dectree.py

 target/hexagon/README                              |  14 +-
 target/hexagon/attribs_def.h.inc                   |   1 -
 target/hexagon/decode.c                            | 439 +++-------
 target/hexagon/decode.h                            |   5 +-
 target/hexagon/dectree.py                          | 403 ---------
 target/hexagon/gen_analyze_funcs.py                | 163 +---
 target/hexagon/gen_decodetree.py                   | 198 +++++
 target/hexagon/gen_dectree_import.c                |  49 --
 target/hexagon/gen_helper_funcs.py                 | 370 ++-------
 target/hexagon/gen_helper_protos.py                | 149 +---
 target/hexagon/gen_idef_parser_funcs.py            |  20 +-
 target/hexagon/gen_op_regs.py                      |   6 +-
 target/hexagon/gen_tcg.h                           |   9 +-
 target/hexagon/gen_tcg_funcs.py                    | 566 +------------
 target/hexagon/gen_trans_funcs.py                  | 124 +++
 target/hexagon/hex_common.py                       | 921 +++++++++++++++++++--
 target/hexagon/idef-parser/parser-helpers.c        |   8 +-
 target/hexagon/macros.h                            |   9 +-
 target/hexagon/meson.build                         | 147 +++-
 target/hexagon/mmvec/decode_ext_mmvec.c            |   4 +-
 target/hexagon/opcodes.c                           |  29 -
 target/hexagon/opcodes.h                           |   2 -
 target/hexagon/translate.c                         |   4 +-
 .../docker/dockerfiles/debian-hexagon-cross.docker |   4 +-
 24 files changed, 1559 insertions(+), 2085 deletions(-)
 delete mode 100755 target/hexagon/dectree.py
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

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

* [PULL 01/15] tests/docker: Hexagon toolchain update
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 02/15] Hexagon (target/hexagon) Fix shadow variable when idef-parser is off Brian Cain
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson,
	Alex Bennée, Thomas Huth, Wainer dos Santos Moschetta,
	Beraldo Leal

This update includes support for privileged instructions.

Signed-off-by: Brian Cain <bcain@quicinc.com>
Reviewed-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Tested-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Message-Id: <20240114232354.4109231-1-bcain@quicinc.com>
---
 tests/docker/dockerfiles/debian-hexagon-cross.docker | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/docker/dockerfiles/debian-hexagon-cross.docker b/tests/docker/dockerfiles/debian-hexagon-cross.docker
index 7c38d7c9e4..60bd8faa20 100644
--- a/tests/docker/dockerfiles/debian-hexagon-cross.docker
+++ b/tests/docker/dockerfiles/debian-hexagon-cross.docker
@@ -38,9 +38,9 @@ RUN apt-get update && \
 RUN /usr/bin/pip3 install tomli
 
 ENV TOOLCHAIN_INSTALL /opt
-ENV TOOLCHAIN_RELEASE 16.0.0
+ENV TOOLCHAIN_RELEASE 12.Dec.2023
 ENV TOOLCHAIN_BASENAME "clang+llvm-${TOOLCHAIN_RELEASE}-cross-hexagon-unknown-linux-musl"
-ENV TOOLCHAIN_URL https://codelinaro.jfrog.io/artifactory/codelinaro-toolchain-for-hexagon/v${TOOLCHAIN_RELEASE}/${TOOLCHAIN_BASENAME}.tar.xz
+ENV TOOLCHAIN_URL https://codelinaro.jfrog.io/artifactory/codelinaro-toolchain-for-hexagon/${TOOLCHAIN_RELEASE}/${TOOLCHAIN_BASENAME}.tar.xz
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 
 RUN curl -#SL "$TOOLCHAIN_URL" | tar -xJC "$TOOLCHAIN_INSTALL"
-- 
2.25.1


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

* [PULL 02/15] Hexagon (target/hexagon) Fix shadow variable when idef-parser is off
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
  2024-01-22  6:34 ` [PULL 01/15] tests/docker: Hexagon toolchain update Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 03/15] Hexagon (target/hexagon) Clean up handling of modifier registers Brian Cain
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Adding -Werror=shadow=compatible-local causes Hexagon not to build
when idef-parser is off.  The "label" variable in CHECK_NOSHUF_PRED
shadows a variable in the surrounding code.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20231130183955.54314-1-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/macros.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 9a51b5709b..f99390e2a8 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -93,13 +93,13 @@
 
 #define CHECK_NOSHUF_PRED(GET_EA, SIZE, PRED) \
     do { \
-        TCGLabel *label = gen_new_label(); \
-        tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, label); \
+        TCGLabel *noshuf_label = gen_new_label(); \
+        tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, noshuf_label); \
         GET_EA; \
         if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
             probe_noshuf_load(EA, SIZE, ctx->mem_idx); \
         } \
-        gen_set_label(label); \
+        gen_set_label(noshuf_label); \
         if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
             process_store(ctx, 1); \
         } \
-- 
2.25.1


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

* [PULL 03/15] Hexagon (target/hexagon) Clean up handling of modifier registers
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
  2024-01-22  6:34 ` [PULL 01/15] tests/docker: Hexagon toolchain update Brian Cain
  2024-01-22  6:34 ` [PULL 02/15] Hexagon (target/hexagon) Fix shadow variable when idef-parser is off Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 04/15] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Brian Cain
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Currently, the register number (MuN) for modifier registers is the
modifier register number rather than the index into hex_gpr.  This
patch changes MuN to the hex_gpr index, which is consistent with
the handling of control registers.

Note that HELPER(fcircadd) needs the CS register corresponding to the
modifier register specified in the instruction.  We create a TCGv
variable "CS" to hold the value to pass to the helper.

Reviewed-by: Brian Cain <bcain@quicinc.com>
Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Message-Id: <20231210220712.491494-2-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_tcg.h                    |  9 ++++-----
 target/hexagon/gen_tcg_funcs.py             | 13 +++++++++----
 target/hexagon/idef-parser/parser-helpers.c |  8 +++-----
 target/hexagon/macros.h                     |  3 +--
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index d992059fce..1c4391b415 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -68,15 +68,14 @@
     do { \
         TCGv tcgv_siV = tcg_constant_tl(siV); \
         tcg_gen_mov_tl(EA, RxV); \
-        gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, \
-                            hex_gpr[HEX_REG_CS0 + MuN]); \
+        gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, CS); \
     } while (0)
 #define GET_EA_pcr(SHIFT) \
     do { \
         TCGv ireg = tcg_temp_new(); \
         tcg_gen_mov_tl(EA, RxV); \
         gen_read_ireg(ireg, MuV, (SHIFT)); \
-        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+        gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
     } while (0)
 
 /* Instructions with multiple definitions */
@@ -113,7 +112,7 @@
         TCGv ireg = tcg_temp_new(); \
         tcg_gen_mov_tl(EA, RxV); \
         gen_read_ireg(ireg, MuV, SHIFT); \
-        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+        gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
         LOAD; \
     } while (0)
 
@@ -427,7 +426,7 @@
         TCGv BYTE G_GNUC_UNUSED = tcg_temp_new(); \
         tcg_gen_mov_tl(EA, RxV); \
         gen_read_ireg(ireg, MuV, SHIFT); \
-        gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+        gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
         STORE; \
     } while (0)
 
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index f5246cee6d..02d93bc5ce 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -99,10 +99,15 @@ def genptr_decl(f, tag, regtype, regid, regno):
             hex_common.bad_register(regtype, regid)
     elif regtype == "M":
         if regid == "u":
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
             f.write(
-                f"    TCGv {regtype}{regid}V = hex_gpr[{regtype}{regid}N + "
-                "HEX_REG_M0];\n"
+                f"    const int {regN} = insn->regno[{regno}] + HEX_REG_M0;\n"
+            )
+            f.write(
+                f"    TCGv {regtype}{regid}V = hex_gpr[{regN}];\n"
+            )
+            f.write(
+                f"    TCGv CS G_GNUC_UNUSED = "
+                f"hex_gpr[{regN} - HEX_REG_M0 + HEX_REG_CS0];\n"
             )
         else:
             hex_common.bad_register(regtype, regid)
@@ -528,7 +533,7 @@ def gen_tcg_func(f, tag, regs, imms):
             ):
                 declared.append(f"{regtype}{regid}V")
                 if regtype == "M":
-                    declared.append(f"{regtype}{regid}N")
+                    declared.append("CS")
             elif hex_common.is_new_val(regtype, regid, tag):
                 declared.append(f"{regtype}{regid}N")
             else:
diff --git a/target/hexagon/idef-parser/parser-helpers.c b/target/hexagon/idef-parser/parser-helpers.c
index 4af020933a..95f2b43076 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1541,10 +1541,8 @@ void gen_circ_op(Context *c,
                  HexValue *increment,
                  HexValue *modifier)
 {
-    HexValue cs = gen_tmp(c, locp, 32, UNSIGNED);
     HexValue increment_m = *increment;
     increment_m = rvalue_materialize(c, locp, &increment_m);
-    OUT(c, locp, "gen_read_reg(", &cs, ", HEX_REG_CS0 + MuN);\n");
     OUT(c,
         locp,
         "gen_helper_fcircadd(",
@@ -1555,7 +1553,7 @@ void gen_circ_op(Context *c,
         &increment_m,
         ", ",
         modifier);
-    OUT(c, locp, ", ", &cs, ");\n");
+    OUT(c, locp, ", CS);\n");
 }
 
 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src)
@@ -2080,9 +2078,9 @@ void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg)
             char reg_id[5];
             reg_compose(c, locp, &(arg->reg), reg_id);
             EMIT_SIG(c, ", %s %s", type, reg_id);
-            /* MuV register requires also MuN to provide its index */
+            /* MuV register requires also CS for circular addressing*/
             if (arg->reg.type == MODIFIER) {
-                EMIT_SIG(c, ", int MuN");
+                EMIT_SIG(c, ", TCGv CS");
             }
         }
         break;
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index f99390e2a8..1376d6ccc1 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -462,8 +462,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 #define fPM_CIRI(REG, IMM, MVAL) \
     do { \
         TCGv tcgv_siV = tcg_constant_tl(siV); \
-        gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, \
-                            hex_gpr[HEX_REG_CS0 + MuN]); \
+        gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, CS); \
     } while (0)
 #else
 #define fEA_IMM(IMM)        do { EA = (IMM); } while (0)
-- 
2.25.1


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

* [PULL 04/15] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (2 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 03/15] Hexagon (target/hexagon) Clean up handling of modifier registers Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 05/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Brian Cain
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

The generators are generally a bunch of Python if-then-else
statements based on the regtype and regid.  Encapsulate regtype/regid
into a class hierarchy.  Clients lookup the register and invoke
methods.

This has several advantages for making the code easier to read,
understand, and maintain
- The class name makes it more clear what the operand does
- All the methods for a given type of operand are together
- Don't need hex_common.bad_register
  If a regtype/regid is missing, the lookup in hex_common.get_register
  will fail
- We can remove the functions in hex_common that use regtype/regid
  (e.g., is_read)

This patch creates the class hierarchy in hex_common and converts
gen_tcg_funcs.py.  The other scripts will be converted in subsequent
patches in this series.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-3-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_tcg_funcs.py | 571 ++-------------------------
 target/hexagon/hex_common.py    | 659 ++++++++++++++++++++++++++++++++
 2 files changed, 683 insertions(+), 547 deletions(-)

diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 02d93bc5ce..3d8e3cb6a2 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -23,466 +23,13 @@
 import hex_common
 
 
-##
-## Helpers for gen_tcg_func
-##
-def gen_decl_ea_tcg(f, tag):
-    f.write("    TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
-
-
-def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
-    regN = f"{regtype}{regid}N"
-    if regtype == "R":
-        f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-    elif regtype == "C":
-        f.write(f"    const int {regN} = insn->regno[{regno}] + HEX_REG_SA0;\n")
-    else:
-        hex_common.bad_register(regtype, regid)
-    f.write(f"    TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, {regN});\n")
-
-
-def genptr_decl_writable(f, tag, regtype, regid, regno):
-    regN = f"{regtype}{regid}N"
-    if regtype == "R":
-        f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-        f.write(f"    TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-    elif regtype == "C":
-        f.write(f"    const int {regN} = insn->regno[{regno}] + HEX_REG_SA0;\n")
-        f.write(f"    TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-    elif regtype == "P":
-        f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-        f.write(f"    TCGv {regtype}{regid}V = tcg_temp_new();\n")
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl(f, tag, regtype, regid, regno):
-    regN = f"{regtype}{regid}N"
-    if regtype == "R":
-        if regid in {"ss", "tt"}:
-            f.write(f"    TCGv_i64 {regtype}{regid}V = tcg_temp_new_i64();\n")
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"dd", "ee", "xx", "yy"}:
-            genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-        elif regid in {"s", "t", "u", "v"}:
-            f.write(
-                f"    TCGv {regtype}{regid}V = " f"hex_gpr[insn->regno[{regno}]];\n"
-            )
-        elif regid in {"d", "e", "x", "y"}:
-            genptr_decl_writable(f, tag, regtype, regid, regno)
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid in {"s", "t", "u", "v"}:
-            f.write(
-                f"    TCGv {regtype}{regid}V = " f"hex_pred[insn->regno[{regno}]];\n"
-            )
-        elif regid in {"d", "e", "x"}:
-            genptr_decl_writable(f, tag, regtype, regid, regno)
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "C":
-        if regid == "ss":
-            f.write(f"    TCGv_i64 {regtype}{regid}V = " f"tcg_temp_new_i64();\n")
-            f.write(f"    const int {regN} = insn->regno[{regno}] + " "HEX_REG_SA0;\n")
-        elif regid == "dd":
-            genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-        elif regid == "s":
-            f.write(f"    TCGv {regtype}{regid}V = tcg_temp_new();\n")
-            f.write(
-                f"    const int {regtype}{regid}N = insn->regno[{regno}] + "
-                "HEX_REG_SA0;\n"
-            )
-        elif regid == "d":
-            genptr_decl_writable(f, tag, regtype, regid, regno)
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "M":
-        if regid == "u":
-            f.write(
-                f"    const int {regN} = insn->regno[{regno}] + HEX_REG_M0;\n"
-            )
-            f.write(
-                f"    TCGv {regtype}{regid}V = hex_gpr[{regN}];\n"
-            )
-            f.write(
-                f"    TCGv CS G_GNUC_UNUSED = "
-                f"hex_gpr[{regN} - HEX_REG_M0 + HEX_REG_CS0];\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "V":
-        if regid in {"dd"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            if hex_common.is_tmp_result(tag):
-                f.write(
-                    f"        ctx_tmp_vreg_off(ctx, {regtype}{regid}N, 2, " "true);\n"
-                )
-            else:
-                f.write(f"        ctx_future_vreg_off(ctx, {regtype}{regid}N,")
-                f.write(" 2, true);\n")
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        elif regid in {"uu", "vv", "xx"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            f.write(f"        offsetof(CPUHexagonState, {regtype}{regid}V);\n")
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        elif regid in {"s", "u", "v", "w"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            f.write(f"        vreg_src_off(ctx, {regtype}{regid}N);\n")
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-        elif regid in {"d", "x", "y"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            if regid == "y":
-                f.write("        offsetof(CPUHexagonState, vtmp);\n")
-            elif hex_common.is_tmp_result(tag):
-                f.write(
-                    f"        ctx_tmp_vreg_off(ctx, {regtype}{regid}N, 1, " "true);\n"
-                )
-            else:
-                f.write(f"        ctx_future_vreg_off(ctx, {regtype}{regid}N,")
-                f.write(" 1, true);\n")
-
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "Q":
-        if regid in {"d", "e", "x"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            f.write(f"        get_result_qreg(ctx, {regtype}{regid}N);\n")
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        elif regid in {"s", "t", "u", "v"}:
-            f.write(f"    const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
-            f.write(f"    const intptr_t {regtype}{regid}V_off =\n")
-            f.write(
-                f"        offsetof(CPUHexagonState, " f"QRegs[{regtype}{regid}N]);\n"
-            )
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(f"    TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl_new(f, tag, regtype, regid, regno):
-    if regtype == "N":
-        if regid in {"s", "t"}:
-            f.write(
-                f"    TCGv {regtype}{regid}N = "
-                f"get_result_gpr(ctx, insn->regno[{regno}]);\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid in {"t", "u", "v"}:
-            f.write(
-                f"    TCGv {regtype}{regid}N = "
-                f"ctx->new_pred_value[insn->regno[{regno}]];\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "O":
-        if regid == "s":
-            f.write(
-                f"    const intptr_t {regtype}{regid}N_num = "
-                f"insn->regno[{regno}];\n"
-            )
-            if hex_common.skip_qemu_helper(tag):
-                f.write(f"    const intptr_t {regtype}{regid}N_off =\n")
-                f.write("         ctx_future_vreg_off(ctx, " f"{regtype}{regid}N_num,")
-                f.write(" 1, true);\n")
-            else:
-                f.write(
-                    f"    TCGv {regtype}{regid}N = "
-                    f"tcg_constant_tl({regtype}{regid}N_num);\n"
-                )
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl_opn(f, tag, regtype, regid, i):
-    if hex_common.is_pair(regid):
-        genptr_decl(f, tag, regtype, regid, i)
-    elif hex_common.is_single(regid):
-        if hex_common.is_old_val(regtype, regid, tag):
-            genptr_decl(f, tag, regtype, regid, i)
-        elif hex_common.is_new_val(regtype, regid, tag):
-            genptr_decl_new(f, tag, regtype, regid, i)
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl_imm(f, immlett):
-    if immlett.isupper():
-        i = 1
-    else:
-        i = 0
-    f.write(f"    int {hex_common.imm_name(immlett)} = insn->immed[{i}];\n")
-
-
-def genptr_src_read(f, tag, regtype, regid):
-    if regtype == "R":
-        if regid in {"ss", "tt", "xx", "yy"}:
-            f.write(
-                f"    tcg_gen_concat_i32_i64({regtype}{regid}V, "
-                f"hex_gpr[{regtype}{regid}N],\n"
-            )
-            f.write(
-                f"                                 hex_gpr[{regtype}"
-                f"{regid}N + 1]);\n"
-            )
-        elif regid in {"x", "y"}:
-            ## For read/write registers, we need to get the original value into
-            ## the result TCGv.  For conditional instructions, this is done in
-            ## gen_start_packet.  For unconditional instructions, we do it here.
-            if "A_CONDEXEC" not in hex_common.attribdict[tag]:
-                f.write(
-                    f"    tcg_gen_mov_tl({regtype}{regid}V, "
-                    f"hex_gpr[{regtype}{regid}N]);\n"
-                )
-        elif regid not in {"s", "t", "u", "v"}:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid == "x":
-            f.write(
-                f"    tcg_gen_mov_tl({regtype}{regid}V, "
-                f"hex_pred[{regtype}{regid}N]);\n"
-            )
-        elif regid not in {"s", "t", "u", "v"}:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "C":
-        if regid == "ss":
-            f.write(
-                f"    gen_read_ctrl_reg_pair(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        elif regid == "s":
-            f.write(
-                f"    gen_read_ctrl_reg(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "M":
-        if regid != "u":
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "V":
-        if regid in {"uu", "vv", "xx"}:
-            f.write(f"    tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n")
-            f.write(f"        vreg_src_off(ctx, {regtype}{regid}N),\n")
-            f.write("        sizeof(MMVector), sizeof(MMVector));\n")
-            f.write("    tcg_gen_gvec_mov(MO_64,\n")
-            f.write(f"        {regtype}{regid}V_off + sizeof(MMVector),\n")
-            f.write(f"        vreg_src_off(ctx, {regtype}{regid}N ^ 1),\n")
-            f.write("        sizeof(MMVector), sizeof(MMVector));\n")
-        elif regid in {"s", "u", "v", "w"}:
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        elif regid in {"x", "y"}:
-            f.write(f"    tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n")
-            f.write(f"        vreg_src_off(ctx, {regtype}{regid}N),\n")
-            f.write("        sizeof(MMVector), sizeof(MMVector));\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "Q":
-        if regid in {"s", "t", "u", "v"}:
-            if not hex_common.skip_qemu_helper(tag):
-                f.write(
-                    f"    tcg_gen_addi_ptr({regtype}{regid}V, tcg_env, "
-                    f"{regtype}{regid}V_off);\n"
-                )
-        elif regid in {"x"}:
-            f.write(f"    tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n")
-            f.write(
-                f"        offsetof(CPUHexagonState, " f"QRegs[{regtype}{regid}N]),\n"
-            )
-            f.write("        sizeof(MMQReg), sizeof(MMQReg));\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_src_read_new(f, regtype, regid):
-    if regtype == "N":
-        if regid not in {"s", "t"}:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid not in {"t", "u", "v"}:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "O":
-        if regid != "s":
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_src_read_opn(f, regtype, regid, tag):
-    if hex_common.is_pair(regid):
-        genptr_src_read(f, tag, regtype, regid)
-    elif hex_common.is_single(regid):
-        if hex_common.is_old_val(regtype, regid, tag):
-            genptr_src_read(f, tag, regtype, regid)
-        elif hex_common.is_new_val(regtype, regid, tag):
-            genptr_src_read_new(f, regtype, regid)
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_call_opn(f, tag, regtype, regid, i):
-    if i > 0:
-        f.write(", ")
-    if hex_common.is_pair(regid):
-        f.write(f"{regtype}{regid}V")
-    elif hex_common.is_single(regid):
-        if hex_common.is_old_val(regtype, regid, tag):
-            f.write(f"{regtype}{regid}V")
-        elif hex_common.is_new_val(regtype, regid, tag):
-            f.write(f"{regtype}{regid}N")
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_decl_imm(f, immlett):
-    f.write(
-        f"    TCGv tcgv_{hex_common.imm_name(immlett)} = "
-        f"tcg_constant_tl({hex_common.imm_name(immlett)});\n"
-    )
-
-
-def gen_helper_call_imm(f, immlett):
-    f.write(f", tcgv_{hex_common.imm_name(immlett)}")
-
-
-def genptr_dst_write_pair(f, tag, regtype, regid):
-    f.write(f"    gen_log_reg_write_pair(ctx, {regtype}{regid}N, "
-            f"{regtype}{regid}V);\n")
-
-
-def genptr_dst_write(f, tag, regtype, regid):
-    if regtype == "R":
-        if regid in {"dd", "xx", "yy"}:
-            genptr_dst_write_pair(f, tag, regtype, regid)
-        elif regid in {"d", "e", "x", "y"}:
-            f.write(
-                f"    gen_log_reg_write(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid in {"d", "e", "x"}:
-            f.write(
-                f"    gen_log_pred_write(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "C":
-        if regid == "dd":
-            f.write(
-                f"    gen_write_ctrl_reg_pair(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        elif regid == "d":
-            f.write(
-                f"    gen_write_ctrl_reg(ctx, {regtype}{regid}N, "
-                f"{regtype}{regid}V);\n"
-            )
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"):
-    if regtype == "V":
-        if regid in {"xx"}:
-            f.write(
-                f"    gen_log_vreg_write_pair(ctx, {regtype}{regid}V_off, "
-                f"{regtype}{regid}N, {newv});\n"
-            )
-        elif regid in {"y"}:
-            f.write(
-                f"    gen_log_vreg_write(ctx, {regtype}{regid}V_off, "
-                f"{regtype}{regid}N, {newv});\n"
-            )
-        elif regid not in {"dd", "d", "x"}:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "Q":
-        if regid not in {"d", "e", "x"}:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def genptr_dst_write_opn(f, regtype, regid, tag):
-    if hex_common.is_pair(regid):
-        if hex_common.is_hvx_reg(regtype):
-            if hex_common.is_tmp_result(tag):
-                genptr_dst_write_ext(f, tag, regtype, regid, "EXT_TMP")
-            else:
-                genptr_dst_write_ext(f, tag, regtype, regid)
-        else:
-            genptr_dst_write(f, tag, regtype, regid)
-    elif hex_common.is_single(regid):
-        if hex_common.is_hvx_reg(regtype):
-            if hex_common.is_new_result(tag):
-                genptr_dst_write_ext(f, tag, regtype, regid, "EXT_NEW")
-            elif hex_common.is_tmp_result(tag):
-                genptr_dst_write_ext(f, tag, regtype, regid, "EXT_TMP")
-            else:
-                genptr_dst_write_ext(f, tag, regtype, regid, "EXT_DFL")
-        else:
-            genptr_dst_write(f, tag, regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
 ##
 ## 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(DisasContext *ctx)
 ##    {
-##        Insn *insn __attribute__((unused)) = ctx->insn;
+##        Insn *insn G_GNUC_UNUSED = ctx->insn;
 ##        const int RdN = insn->regno[0];
 ##        TCGv RdV = get_result_gpr(ctx, RdN);
 ##        TCGv RsV = hex_gpr[insn->regno[1]];
@@ -501,44 +48,27 @@ def gen_tcg_func(f, tag, regs, imms):
     f.write(f"static void generate_{tag}(DisasContext *ctx)\n")
     f.write("{\n")
 
-    f.write("    Insn *insn __attribute__((unused)) = ctx->insn;\n")
+    f.write("    Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
 
     if hex_common.need_ea(tag):
-        gen_decl_ea_tcg(f, tag)
-    i = 0
+        f.write("    TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
+
     ## Declare all the operands (regs and immediates)
+    i = 0
     for regtype, regid in regs:
-        genptr_decl_opn(f, tag, regtype, regid, i)
+        reg = hex_common.get_register(tag, regtype, regid)
+        reg.decl_tcg(f, tag, i)
         i += 1
     for immlett, bits, immshift in imms:
-        genptr_decl_imm(f, immlett)
-
-    if "A_PRIV" in hex_common.attribdict[tag]:
-        f.write("    fCHECKFORPRIV();\n")
-    if "A_GUEST" in hex_common.attribdict[tag]:
-        f.write("    fCHECKFORGUEST();\n")
-
-    ## Read all the inputs
-    for regtype, regid in regs:
-        if hex_common.is_read(regid):
-            genptr_src_read_opn(f, regtype, regid, tag)
+        i = 1 if immlett.isupper() else 0
+        f.write(f"    int {hex_common.imm_name(immlett)} = insn->immed[{i}];\n")
 
     if hex_common.is_idef_parser_enabled(tag):
         declared = []
         ## Handle registers
         for regtype, regid in regs:
-            if hex_common.is_pair(regid) or (
-                hex_common.is_single(regid)
-                and hex_common.is_old_val(regtype, regid, tag)
-            ):
-                declared.append(f"{regtype}{regid}V")
-                if regtype == "M":
-                    declared.append("CS")
-            elif hex_common.is_new_val(regtype, regid, tag):
-                declared.append(f"{regtype}{regid}N")
-            else:
-                hex_common.bad_register(regtype, regid)
-
+            reg = hex_common.get_register(tag, regtype, regid)
+            reg.idef_arg(declared)
         ## Handle immediates
         for immlett, bits, immshift in imms:
             declared.append(hex_common.imm_name(immlett))
@@ -550,76 +80,22 @@ def gen_tcg_func(f, tag, regs, imms):
         f.write(f"    fGEN_TCG_{tag}({hex_common.semdict[tag]});\n")
     else:
         ## 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_pkt_need_commit(tag):
-            f.write("    TCGv pkt_need_commit = ")
-            f.write("tcg_constant_tl(ctx->need_commit);\n")
-        if hex_common.need_part1(tag):
-            f.write("    TCGv part1 = tcg_constant_tl(insn->part1);\n")
-        if hex_common.need_slot(tag):
-            f.write("    TCGv slotval = gen_slotval(ctx);\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(f"    gen_helper_{tag}(")
-        i = 0
-        ## If there is a scalar result, it is the return type
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if hex_common.is_hvx_reg(regtype):
-                    continue
-                gen_helper_call_opn(f, tag, regtype, regid, i)
-                i += 1
-        if i > 0:
-            f.write(", ")
-        f.write("tcg_env")
-        i = 1
-        ## For conditional instructions, we pass in the destination register
-        if "A_CONDEXEC" in hex_common.attribdict[tag]:
-            for regtype, regid in regs:
-                if hex_common.is_writeonly(regid) and not hex_common.is_hvx_reg(
-                    regtype
-                ):
-                    gen_helper_call_opn(f, tag, regtype, regid, i)
-                    i += 1
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if not hex_common.is_hvx_reg(regtype):
-                    continue
-                gen_helper_call_opn(f, tag, regtype, regid, i)
-                i += 1
-        for regtype, regid in regs:
-            if hex_common.is_read(regid):
-                if hex_common.is_hvx_reg(regtype) and hex_common.is_readwrite(regid):
-                    continue
-                gen_helper_call_opn(f, tag, regtype, regid, i)
-                i += 1
-        for immlett, bits, immshift in imms:
-            gen_helper_call_imm(f, immlett)
+        declared = []
+        ret_type = hex_common.helper_ret_type(tag, regs).call_arg
+        if ret_type != "void":
+            declared.append(ret_type)
 
-        if hex_common.need_pkt_has_multi_cof(tag):
-            f.write(", pkt_has_multi_cof")
-        if hex_common.need_pkt_need_commit(tag):
-            f.write(", pkt_need_commit")
-        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(", slotval")
-        if hex_common.need_part1(tag):
-            f.write(", part1")
-        f.write(");\n")
+        for arg in hex_common.helper_args(tag, regs, imms):
+            declared.append(arg.call_arg)
+
+        arguments = ", ".join(declared)
+        f.write(f"    gen_helper_{tag}({arguments});\n")
 
     ## Write all the outputs
     for regtype, regid in regs:
-        if hex_common.is_written(regid):
-            genptr_dst_write_opn(f, regtype, regid, tag)
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written():
+            reg.log_write(f, tag)
 
     f.write("}\n\n")
 
@@ -637,6 +113,7 @@ def main():
     hex_common.read_overrides_file(sys.argv[3])
     hex_common.read_overrides_file(sys.argv[4])
     hex_common.calculate_attribs()
+    hex_common.init_registers()
     ## Whether or not idef-parser is enabled is
     ## determined by the number of arguments to
     ## this script:
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 0da65d6dd6..979f198a30 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -20,12 +20,15 @@
 import sys
 import re
 import string
+import textwrap
 
 behdict = {}  # tag ->behavior
 semdict = {}  # tag -> semantics
 attribdict = {}  # tag -> attributes
 macros = {}  # macro -> macro information...
 attribinfo = {}  # Register information and misc
+registers = {}  # register -> register functions
+new_registers = {}
 tags = []  # list of all tags
 overrides = {}  # tags with helper overrides
 idef_parser_enabled = {}  # tags enabled for idef-parser
@@ -276,6 +279,10 @@ def helper_needs_next_PC(tag):
     return "A_CALL" in attribdict[tag]
 
 
+def need_next_PC(tag):
+    return "A_CALL" in attribdict[tag]
+
+
 def need_pkt_has_multi_cof(tag):
     return "A_COF" in attribdict[tag]
 
@@ -350,3 +357,655 @@ def read_idef_parser_enabled_file(name):
     with open(name, "r") as idef_parser_enabled_file:
         lines = idef_parser_enabled_file.read().strip().split("\n")
         idef_parser_enabled = set(lines)
+
+
+def is_predicated(tag):
+    return "A_CONDEXEC" in attribdict[tag]
+
+
+def code_fmt(txt):
+    return textwrap.indent(textwrap.dedent(txt), "    ")
+
+
+def hvx_newv(tag):
+    if "A_CVI_NEW" in attribdict[tag]:
+        return "EXT_NEW"
+    elif "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
+        return "EXT_TMP"
+    else:
+        return "EXT_DFL"
+
+def vreg_offset_func(tag):
+    if "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
+        return "ctx_tmp_vreg_off"
+    else:
+        return "ctx_future_vreg_off"
+
+class HelperArg:
+    def __init__(self, proto_arg, call_arg, func_arg):
+        self.proto_arg = proto_arg
+        self.call_arg = call_arg
+        self.func_arg = func_arg
+
+class Register:
+    def __init__(self, regtype, regid):
+        self.regtype = regtype
+        self.regid = regid
+        self.reg_num = f"{regtype}{regid}N"
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}];
+        """))
+    def idef_arg(self, declared):
+        declared.append(self.reg_tcg())
+    def helper_arg(self):
+        return HelperArg(
+            self.helper_proto_type(),
+            self.reg_tcg(),
+            f"{self.helper_arg_type()} {self.helper_arg_name()}"
+        )
+
+#
+# Every register is either Single or Pair or Hvx
+#
+class Scalar:
+    def is_scalar_reg(self):
+        return True
+    def is_hvx_reg(self):
+        return False
+    def helper_arg_name(self):
+        return self.reg_tcg()
+
+class Single(Scalar):
+    def helper_proto_type(self):
+        return "s32"
+    def helper_arg_type(self):
+        return "int32_t"
+
+class Pair(Scalar):
+    def helper_proto_type(self):
+        return "s64"
+    def helper_arg_type(self):
+        return "int64_t"
+
+class Hvx:
+    def is_scalar_reg(self):
+        return False
+    def is_hvx_reg(self):
+        return True
+    def hvx_off(self):
+        return f"{self.reg_tcg()}_off"
+    def helper_proto_type(self):
+        return "ptr"
+    def helper_arg_type(self):
+        return "void *"
+    def helper_arg_name(self):
+        return f"{self.reg_tcg()}_void"
+
+#
+# Every register is either Dest or OldSource or NewSource or ReadWrite
+#
+class Dest:
+    def reg_tcg(self):
+        return f"{self.regtype}{self.regid}V"
+    def is_written(self):
+        return True
+    def is_writeonly(self):
+        return True
+    def is_read(self):
+        return False
+    def is_readwrite(self):
+        return False
+
+class Source:
+    def is_written(self):
+        return False
+    def is_writeonly(self):
+        return False
+    def is_read(self):
+        return True
+    def is_readwrite(self):
+        return False
+
+class OldSource(Source):
+    def reg_tcg(self):
+        return f"{self.regtype}{self.regid}V"
+
+class NewSource(Source):
+    def reg_tcg(self):
+        return f"{self.regtype}{self.regid}N"
+
+class ReadWrite:
+    def reg_tcg(self):
+        return f"{self.regtype}{self.regid}V"
+    def is_written(self):
+        return True
+    def is_writeonly(self):
+        return False
+    def is_read(self):
+        return True
+    def is_readwrite(self):
+        return True
+
+class GprDest(Register, Single, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class GprSource(Register, Single, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
+        """))
+
+class GprNewSource(Register, Single, NewSource):
+    def decl_tcg(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]);
+        """))
+
+class GprReadWrite(Register, Single, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
+        """))
+        ## For read/write registers, we need to get the original value into
+        ## the result TCGv.  For predicated instructions, this is done in
+        ## gen_start_packet.  For un-predicated instructions, we do it here.
+        if not is_predicated(tag):
+            f.write(code_fmt(f"""\
+                tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]);
+            """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class ControlDest(Register, Single, Dest):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}]  + HEX_REG_SA0;
+        """))
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class ControlSource(Register, Single, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}]  + HEX_REG_SA0;
+        """))
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno);
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = tcg_temp_new();
+            gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class ModifierSource(Register, Single, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0;
+        """))
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
+            TCGv CS G_GNUC_UNUSED =
+                hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0];
+        """))
+    def idef_arg(self, declared):
+        declared.append(self.reg_tcg())
+        declared.append("CS")
+
+class PredDest(Register, Single, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = tcg_temp_new();
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class PredSource(Register, Single, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}];
+        """))
+
+class PredNewSource(Register, Single, NewSource):
+    def decl_tcg(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]);
+        """))
+
+class PredReadWrite(Register, Single, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv {self.reg_tcg()} = tcg_temp_new();
+            tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]);
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class PairDest(Register, Pair, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} =
+                get_result_gpr_pair(ctx, {self.reg_num});
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class PairSource(Register, Pair, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+            tcg_gen_concat_i32_i64({self.reg_tcg()},
+                                    hex_gpr[{self.reg_num}],
+                                    hex_gpr[{self.reg_num} + 1]);
+        """))
+
+class PairReadWrite(Register, Pair, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} =
+                get_result_gpr_pair(ctx, {self.reg_num});
+            tcg_gen_concat_i32_i64({self.reg_tcg()},
+                                   hex_gpr[{self.reg_num}],
+                                   hex_gpr[{self.reg_num} + 1]);
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class ControlPairDest(Register, Pair, Dest):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
+        """))
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} =
+                get_result_gpr_pair(ctx, {self.reg_num});
+        """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class ControlPairSource(Register, Pair, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
+        """))
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+            gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+
+class VRegDest(Register, Hvx, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        pass
+
+class VRegSource(Register, Hvx, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num});
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+
+class VRegNewSource(Register, Hvx, NewSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        if skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                const intptr_t {self.hvx_off()} =
+                    ctx_future_vreg_off(ctx, {self.reg_num}, 1, true);
+            """))
+
+class VRegReadWrite(Register, Hvx, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
+                             vreg_src_off(ctx, {self.reg_num}),
+                             sizeof(MMVector), sizeof(MMVector));
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        pass
+
+class VRegTmp(Register, Hvx, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp);
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+                tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
+                                 vreg_src_off(ctx, {self.reg_num}),
+                                 sizeof(MMVector), sizeof(MMVector));
+            """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num},
+                               {hvx_newv(tag)});
+        """))
+
+class VRegPairDest(Register, Hvx, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true);
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        pass
+
+class VRegPairSource(Register, Hvx, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                offsetof(CPUHexagonState, {self.reg_tcg()});
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
+                             vreg_src_off(ctx, {self.reg_num}),
+                             sizeof(MMVector), sizeof(MMVector));
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
+                             vreg_src_off(ctx, {self.reg_num} ^ 1),
+                             sizeof(MMVector), sizeof(MMVector));
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+
+class VRegPairReadWrite(Register, Hvx, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                offsetof(CPUHexagonState, {self.reg_tcg()});
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
+                             vreg_src_off(ctx, {self.reg_num}),
+                             sizeof(MMVector), sizeof(MMVector));
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
+                             vreg_src_off(ctx, {self.reg_num} ^ 1),
+                             sizeof(MMVector), sizeof(MMVector));
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num},
+                                    {hvx_newv(tag)});
+        """))
+
+class QRegDest(Register, Hvx, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                get_result_qreg(ctx, {self.reg_num});
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        pass
+
+class QRegSource(Register, Hvx, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                offsetof(CPUHexagonState, QRegs[{self.reg_num}]);
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+
+class QRegReadWrite(Register, Hvx, ReadWrite):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            const intptr_t {self.hvx_off()} =
+                get_result_qreg(ctx, {self.reg_num});
+            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
+                             offsetof(CPUHexagonState, QRegs[{self.reg_num}]),
+                             sizeof(MMQReg), sizeof(MMQReg));
+        """))
+        if not skip_qemu_helper(tag):
+            f.write(code_fmt(f"""\
+                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
+                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
+            """))
+    def log_write(self, f, tag):
+        pass
+
+def init_registers():
+    regs = {
+        GprDest("R", "d"),
+        GprDest("R", "e"),
+        GprSource("R", "s"),
+        GprSource("R", "t"),
+        GprSource("R", "u"),
+        GprSource("R", "v"),
+        GprReadWrite("R", "x"),
+        GprReadWrite("R", "y"),
+        ControlDest("C", "d"),
+        ControlSource("C", "s"),
+        ModifierSource("M", "u"),
+        PredDest("P", "d"),
+        PredDest("P", "e"),
+        PredSource("P", "s"),
+        PredSource("P", "t"),
+        PredSource("P", "u"),
+        PredSource("P", "v"),
+        PredReadWrite("P", "x"),
+        PairDest("R", "dd"),
+        PairDest("R", "ee"),
+        PairSource("R", "ss"),
+        PairSource("R", "tt"),
+        PairReadWrite("R", "xx"),
+        PairReadWrite("R", "yy"),
+        ControlPairDest("C", "dd"),
+        ControlPairSource("C", "ss"),
+        VRegDest("V", "d"),
+        VRegSource("V", "s"),
+        VRegSource("V", "u"),
+        VRegSource("V", "v"),
+        VRegSource("V", "w"),
+        VRegReadWrite("V", "x"),
+        VRegTmp("V", "y"),
+        VRegPairDest("V", "dd"),
+        VRegPairSource("V", "uu"),
+        VRegPairSource("V", "vv"),
+        VRegPairReadWrite("V", "xx"),
+        QRegDest("Q", "d"),
+        QRegDest("Q", "e"),
+        QRegSource("Q", "s"),
+        QRegSource("Q", "t"),
+        QRegSource("Q", "u"),
+        QRegSource("Q", "v"),
+        QRegReadWrite("Q", "x"),
+    }
+    for reg in regs:
+        registers[f"{reg.regtype}{reg.regid}"] = reg
+
+    new_regs = {
+        GprNewSource("N", "s"),
+        GprNewSource("N", "t"),
+        PredNewSource("P", "t"),
+        PredNewSource("P", "u"),
+        PredNewSource("P", "v"),
+        VRegNewSource("O", "s"),
+    }
+    for reg in new_regs:
+        new_registers[f"{reg.regtype}{reg.regid}"] = reg
+
+def get_register(tag, regtype, regid):
+    if f"{regtype}{regid}V" in semdict[tag]:
+        return registers[f"{regtype}{regid}"]
+    else:
+        return new_registers[f"{regtype}{regid}"]
+
+def helper_ret_type(tag, regs):
+    ## If there is a scalar result, it is the return type
+    return_type = HelperArg( "void", "void", "void")
+    numscalarresults = 0
+    for regtype, regid in regs:
+        reg = get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_scalar_reg():
+            return_type = HelperArg(
+                reg.helper_proto_type(),
+                reg.reg_tcg(),
+                reg.helper_arg_type()
+            )
+    if numscalarresults > 1:
+        raise Exception("numscalarresults > 1")
+    return return_type
+
+def helper_args(tag, regs, imms):
+    args = []
+
+    ## First argument is the CPU state
+    args.append(HelperArg(
+        "env",
+        "tcg_env",
+        "CPUHexagonState *env"
+    ))
+
+    ## For predicated instructions, we pass in the destination register
+    if is_predicated(tag):
+        for regtype, regid in regs:
+            reg = get_register(tag, regtype, regid)
+            if reg.is_writeonly() and not reg.is_hvx_reg():
+                args.append(reg.helper_arg())
+
+    ## Pass the HVX destination registers
+    for regtype, regid in regs:
+        reg = get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_hvx_reg():
+            args.append(reg.helper_arg())
+
+    ## Pass the source registers
+    for regtype, regid in regs:
+        reg = get_register(tag, regtype, regid)
+        if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
+            args.append(reg.helper_arg())
+
+    ## Pass the immediates
+    for immlett, bits, immshift in imms:
+        args.append(HelperArg(
+            "s32",
+            f"tcg_constant_tl({imm_name(immlett)})",
+            f"int32_t {imm_name(immlett)}"
+        ))
+
+    ## Other stuff the helper might need
+    if need_pkt_has_multi_cof(tag):
+        args.append(HelperArg(
+            "i32",
+            "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
+            "uint32_t pkt_has_multi_cof"
+        ))
+    if need_pkt_need_commit(tag):
+        args.append(HelperArg(
+            "i32",
+            "tcg_constant_tl(ctx->need_commit)",
+            "uint32_t pkt_need_commit"
+        ))
+    if need_PC(tag):
+        args.append(HelperArg(
+            "i32",
+            "tcg_constant_tl(ctx->pkt->pc)",
+            "target_ulong PC"
+        ))
+    if need_next_PC(tag):
+        args.append(HelperArg(
+            "i32",
+            "tcg_constant_tl(ctx->next_PC)",
+            "target_ulong next_PC"
+        ))
+    if need_slot(tag):
+        args.append(HelperArg(
+            "i32",
+            "gen_slotval(ctx)",
+            "uint32_t slotval"
+        ))
+    if need_part1(tag):
+        args.append(HelperArg(
+            "i32",
+            "tcg_constant_tl(insn->part1)"
+            "uint32_t part1"
+        ))
+    return args
-- 
2.25.1


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

* [PULL 05/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (3 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 04/15] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 06/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Brian Cain
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-4-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_helper_protos.py | 149 ++--------------------------
 target/hexagon/hex_common.py        |   7 --
 2 files changed, 8 insertions(+), 148 deletions(-)

diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 131043795a..c82b0f54e4 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -22,39 +22,6 @@
 import string
 import hex_common
 
-##
-## Helpers for gen_helper_prototype
-##
-def_helper_types = {
-    "N": "s32",
-    "O": "s32",
-    "P": "s32",
-    "M": "s32",
-    "C": "s32",
-    "R": "s32",
-    "V": "ptr",
-    "Q": "ptr",
-}
-
-def_helper_types_pair = {
-    "R": "s64",
-    "C": "s64",
-    "S": "s64",
-    "G": "s64",
-    "V": "ptr",
-    "Q": "ptr",
-}
-
-
-def gen_def_helper_opn(f, tag, regtype, regid, i):
-    if hex_common.is_pair(regid):
-        f.write(f", {def_helper_types_pair[regtype]}")
-    elif hex_common.is_single(regid):
-        f.write(f", {def_helper_types[regtype]}")
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
 ##
 ## Generate the DEF_HELPER prototype for an instruction
 ##     For A2_add: Rd32=add(Rs32,Rt32)
@@ -65,116 +32,15 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
     regs = tagregs[tag]
     imms = tagimms[tag]
 
-    numresults = 0
-    numscalarresults = 0
-    numscalarreadwrite = 0
-    for regtype, regid in regs:
-        if hex_common.is_written(regid):
-            numresults += 1
-            if hex_common.is_scalar_reg(regtype):
-                numscalarresults += 1
-        if hex_common.is_readwrite(regid):
-            if hex_common.is_scalar_reg(regtype):
-                numscalarreadwrite += 1
+    declared = []
+    ret_type = hex_common.helper_ret_type(tag, regs).proto_arg
+    declared.append(ret_type)
 
-    if numscalarresults > 1:
-        ## The helper is bogus when there is more than one result
-        f.write(f"DEF_HELPER_1({tag}, void, env)\n")
-    else:
-        ## 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_pkt_need_commit(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
-            if hex_common.helper_needs_next_PC(tag):
-                def_helper_size += 1
-            if hex_common.need_condexec_reg(tag, regs):
-                def_helper_size += 1
-            f.write(f"DEF_HELPER_{def_helper_size}({tag}")
-            ## The return type is void
-            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_pkt_need_commit(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
-            if hex_common.need_condexec_reg(tag, regs):
-                def_helper_size += 1
-            if hex_common.helper_needs_next_PC(tag):
-                def_helper_size += 1
-            f.write(f"DEF_HELPER_{def_helper_size}({tag}")
+    for arg in hex_common.helper_args(tag, regs, imms):
+        declared.append(arg.proto_arg)
 
-        ## Generate the qemu DEF_HELPER type for each result
-        ## Iterate over this list twice
-        ## - Emit the scalar result
-        ## - Emit the vector result
-        i = 0
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if not hex_common.is_hvx_reg(regtype):
-                    gen_def_helper_opn(f, tag, regtype, regid, i)
-                i += 1
-
-        ## Put the env between the outputs and inputs
-        f.write(", env")
-        i += 1
-
-        # Second pass
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if hex_common.is_hvx_reg(regtype):
-                    gen_def_helper_opn(f, tag, regtype, regid, i)
-                    i += 1
-
-        ## For conditional instructions, we pass in the destination register
-        if "A_CONDEXEC" in hex_common.attribdict[tag]:
-            for regtype, regid in regs:
-                if hex_common.is_writeonly(regid) and not hex_common.is_hvx_reg(
-                    regtype
-                ):
-                    gen_def_helper_opn(f, tag, regtype, regid, i)
-                    i += 1
-
-        ## Generate the qemu type for each input operand (regs and immediates)
-        for regtype, regid in regs:
-            if hex_common.is_read(regid):
-                if hex_common.is_hvx_reg(regtype) and hex_common.is_readwrite(regid):
-                    continue
-                gen_def_helper_opn(f, tag, regtype, regid, i)
-                i += 1
-        for immlett, bits, immshift in imms:
-            f.write(", s32")
-
-        ## Add the arguments for the instruction pkt_has_multi_cof,
-        ## pkt_needs_commit, PC, next_PC, slot, and part1 (if needed)
-        if hex_common.need_pkt_has_multi_cof(tag):
-            f.write(", i32")
-        if hex_common.need_pkt_need_commit(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")
+    arguments = ", ".join(declared)
+    f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
 
 
 def main():
@@ -195,6 +61,7 @@ def main():
     if is_idef_parser_enabled:
         hex_common.read_idef_parser_enabled_file(sys.argv[5])
     hex_common.calculate_attribs()
+    hex_common.init_registers()
     tagregs = hex_common.get_tagregs()
     tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 979f198a30..2abd653e6d 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -290,13 +290,6 @@ def need_pkt_has_multi_cof(tag):
 def need_pkt_need_commit(tag):
     return 'A_IMPLICIT_WRITES_USR' in attribdict[tag]
 
-def need_condexec_reg(tag, regs):
-    if "A_CONDEXEC" in attribdict[tag]:
-        for regtype, regid in regs:
-            if is_writeonly(regid) and not is_hvx_reg(regtype):
-                return True
-    return False
-
 
 def skip_qemu_helper(tag):
     return tag in overrides.keys()
-- 
2.25.1


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

* [PULL 06/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (4 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 05/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 07/15] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Brian Cain
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-5-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_helper_funcs.py | 370 +++++------------------------
 target/hexagon/hex_common.py       |  48 +++-
 2 files changed, 104 insertions(+), 314 deletions(-)

diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index ce21d3b688..9cc3d69c49 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -23,181 +23,14 @@
 import hex_common
 
 
-##
-## Helpers for gen_helper_function
-##
-def gen_decl_ea(f):
-    f.write("    uint32_t EA;\n")
-
-
-def gen_helper_return_type(f, regtype, regid, regno):
-    if regno > 1:
-        f.write(", ")
-    f.write("int32_t")
-
-
-def gen_helper_return_type_pair(f, regtype, regid, regno):
-    if regno > 1:
-        f.write(", ")
-    f.write("int64_t")
-
-
-def gen_helper_arg(f, regtype, regid, regno):
-    if regno > 0:
-        f.write(", ")
-    f.write(f"int32_t {regtype}{regid}V")
-
-
-def gen_helper_arg_new(f, regtype, regid, regno):
-    if regno >= 0:
-        f.write(", ")
-    f.write(f"int32_t {regtype}{regid}N")
-
-
-def gen_helper_arg_pair(f, regtype, regid, regno):
-    if regno >= 0:
-        f.write(", ")
-    f.write(f"int64_t {regtype}{regid}V")
-
-
-def gen_helper_arg_ext(f, regtype, regid, regno):
-    if regno > 0:
-        f.write(", ")
-    f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_ext_pair(f, regtype, regid, regno):
-    if regno > 0:
-        f.write(", ")
-    f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_opn(f, regtype, regid, i, tag):
-    if hex_common.is_pair(regid):
-        if hex_common.is_hvx_reg(regtype):
-            gen_helper_arg_ext_pair(f, regtype, regid, i)
-        else:
-            gen_helper_arg_pair(f, regtype, regid, i)
-    elif hex_common.is_single(regid):
-        if hex_common.is_old_val(regtype, regid, tag):
-            if hex_common.is_hvx_reg(regtype):
-                gen_helper_arg_ext(f, regtype, regid, i)
-            else:
-                gen_helper_arg(f, regtype, regid, i)
-        elif hex_common.is_new_val(regtype, regid, tag):
-            gen_helper_arg_new(f, regtype, regid, i)
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_arg_imm(f, immlett):
-    f.write(f", int32_t {hex_common.imm_name(immlett)}")
-
-
-def gen_helper_dest_decl(f, regtype, regid, regno, subfield=""):
-    f.write(f"    int32_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_pair(f, regtype, regid, regno, subfield=""):
-    f.write(f"    int64_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_ext(f, regtype, regid):
-    if regtype == "Q":
-        f.write(
-            f"    /* {regtype}{regid}V is *(MMQReg *)" f"({regtype}{regid}V_void) */\n"
-        )
-    else:
-        f.write(
-            f"    /* {regtype}{regid}V is *(MMVector *)"
-            f"({regtype}{regid}V_void) */\n"
-        )
-
-
-def gen_helper_dest_decl_ext_pair(f, regtype, regid, regno):
-    f.write(
-        f"    /* {regtype}{regid}V is *(MMVectorPair *))"
-        f"{regtype}{regid}V_void) */\n"
-    )
-
-
-def gen_helper_dest_decl_opn(f, regtype, regid, i):
-    if hex_common.is_pair(regid):
-        if hex_common.is_hvx_reg(regtype):
-            gen_helper_dest_decl_ext_pair(f, regtype, regid, i)
-        else:
-            gen_helper_dest_decl_pair(f, regtype, regid, i)
-    elif hex_common.is_single(regid):
-        if hex_common.is_hvx_reg(regtype):
-            gen_helper_dest_decl_ext(f, regtype, regid)
-        else:
-            gen_helper_dest_decl(f, regtype, regid, i)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_src_var_ext(f, regtype, regid):
-    if regtype == "Q":
-        f.write(
-            f"    /* {regtype}{regid}V is *(MMQReg *)" f"({regtype}{regid}V_void) */\n"
-        )
-    else:
-        f.write(
-            f"    /* {regtype}{regid}V is *(MMVector *)"
-            f"({regtype}{regid}V_void) */\n"
-        )
-
-
-def gen_helper_src_var_ext_pair(f, regtype, regid, regno):
-    f.write(
-        f"    /* {regtype}{regid}V{regno} is *(MMVectorPair *)"
-        f"({regtype}{regid}V{regno}_void) */\n"
-    )
-
-
-def gen_helper_return(f, regtype, regid, regno):
-    f.write(f"    return {regtype}{regid}V;\n")
-
-
-def gen_helper_return_pair(f, regtype, regid, regno):
-    f.write(f"    return {regtype}{regid}V;\n")
-
-
-def gen_helper_dst_write_ext(f, regtype, regid):
-    return
-
-
-def gen_helper_dst_write_ext_pair(f, regtype, regid):
-    return
-
-
-def gen_helper_return_opn(f, regtype, regid, i):
-    if hex_common.is_pair(regid):
-        if hex_common.is_hvx_reg(regtype):
-            gen_helper_dst_write_ext_pair(f, regtype, regid)
-        else:
-            gen_helper_return_pair(f, regtype, regid, i)
-    elif hex_common.is_single(regid):
-        if hex_common.is_hvx_reg(regtype):
-            gen_helper_dst_write_ext(f, regtype, regid)
-        else:
-            gen_helper_return(f, regtype, regid, i)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
 ##
 ## Generate the TCG code to call the helper
 ##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
 ##     We produce:
 ##       int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
 ##       {
-##           uint32_t slot __attribute__(unused)) = 4;
 ##           int32_t RdV = 0;
 ##           { RdV=RsV+RtV;}
-##           COUNT_HELPER(A2_add);
 ##           return RdV;
 ##       }
 ##
@@ -205,151 +38,67 @@ def gen_helper_function(f, tag, tagregs, tagimms):
     regs = tagregs[tag]
     imms = tagimms[tag]
 
-    numresults = 0
-    numscalarresults = 0
-    numscalarreadwrite = 0
-    for regtype, regid in regs:
-        if hex_common.is_written(regid):
-            numresults += 1
-            if hex_common.is_scalar_reg(regtype):
-                numscalarresults += 1
-        if hex_common.is_readwrite(regid):
-            if hex_common.is_scalar_reg(regtype):
-                numscalarreadwrite += 1
-
-    if numscalarresults > 1:
-        ## The helper is bogus when there is more than one result
-        f.write(
-            f"void HELPER({tag})(CPUHexagonState *env) " f"{{ BOGUS_HELPER({tag}); }}\n"
-        )
-    else:
-        ## The return type of the function is the type of the destination
-        ## register (if scalar)
-        i = 0
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if hex_common.is_pair(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        continue
-                    else:
-                        gen_helper_return_type_pair(f, regtype, regid, i)
-                elif hex_common.is_single(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        continue
-                    else:
-                        gen_helper_return_type(f, regtype, regid, i)
-                else:
-                    hex_common.bad_register(regtype, regid)
-            i += 1
-
-        if numscalarresults == 0:
-            f.write("void")
-        f.write(f" HELPER({tag})(CPUHexagonState *env")
-
-        ## Arguments include the vector destination operands
-        i = 1
+    ret_type = hex_common.helper_ret_type(tag, regs).func_arg
+
+    declared = []
+    for arg in hex_common.helper_args(tag, regs, imms):
+        declared.append(arg.func_arg)
+
+    arguments = ", ".join(declared)
+    f.write(f"{ret_type} HELPER({tag})({arguments})\n")
+    f.write("{\n")
+    if hex_common.need_ea(tag):
+        f.write(hex_common.code_fmt(f"""\
+            uint32_t EA;
+        """))
+    ## Declare the return variable
+    if not hex_common.is_predicated(tag):
         for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                if hex_common.is_pair(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        gen_helper_arg_ext_pair(f, regtype, regid, i)
-                    else:
-                        continue
-                elif hex_common.is_single(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        gen_helper_arg_ext(f, regtype, regid, i)
-                    else:
-                        # This is the return value of the function
-                        continue
-                else:
-                    hex_common.bad_register(regtype, regid)
-                i += 1
-
-        ## For conditional instructions, we pass in the destination register
-        if "A_CONDEXEC" in hex_common.attribdict[tag]:
-            for regtype, regid in regs:
-                if hex_common.is_writeonly(regid) and not hex_common.is_hvx_reg(
-                    regtype
-                ):
-                    gen_helper_arg_opn(f, regtype, regid, i, tag)
-                    i += 1
-
-        ## Arguments to the helper function are the source regs and immediates
-        for regtype, regid in regs:
-            if hex_common.is_read(regid):
-                if hex_common.is_hvx_reg(regtype) and hex_common.is_readwrite(regid):
-                    continue
-                gen_helper_arg_opn(f, regtype, regid, i, tag)
-                i += 1
-        for immlett, bits, immshift in imms:
-            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_pkt_need_commit(tag)):
-            f.write(", uint32_t pkt_need_commit")
-
-        if hex_common.need_PC(tag):
-            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 slotval")
-            i += 1
-        if hex_common.need_part1(tag):
-            if i > 0:
-                f.write(", ")
-            f.write("uint32_t part1")
-        f.write(")\n{\n")
-        if hex_common.need_ea(tag):
-            gen_decl_ea(f)
-        ## Declare the return variable
-        i = 0
-        if "A_CONDEXEC" not in hex_common.attribdict[tag]:
-            for regtype, regid in regs:
-                if hex_common.is_writeonly(regid):
-                    gen_helper_dest_decl_opn(f, regtype, regid, i)
-                i += 1
+            reg = hex_common.get_register(tag, regtype, regid)
+            if reg.is_writeonly() and not reg.is_hvx_reg():
+                f.write(hex_common.code_fmt(f"""\
+                    {reg.helper_arg_type()} {reg.helper_arg_name()} = 0;
+                """))
 
-        for regtype, regid in regs:
-            if hex_common.is_read(regid):
-                if hex_common.is_pair(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        gen_helper_src_var_ext_pair(f, regtype, regid, i)
-                elif hex_common.is_single(regid):
-                    if hex_common.is_hvx_reg(regtype):
-                        gen_helper_src_var_ext(f, regtype, regid)
-                else:
-                    hex_common.bad_register(regtype, regid)
-
-        if hex_common.need_slot(tag):
-            if "A_LOAD" in hex_common.attribdict[tag]:
-                f.write("    bool pkt_has_store_s1 = slotval & 0x1;\n")
-            f.write("    uint32_t slot = slotval >> 1;\n")
-
-        if "A_FPOP" in hex_common.attribdict[tag]:
-            f.write("    arch_fpop_start(env);\n")
-
-        f.write(f"    {hex_common.semdict[tag]}\n")
-
-        if "A_FPOP" in hex_common.attribdict[tag]:
-            f.write("    arch_fpop_end(env);\n")
-
-        ## Save/return the return variable
-        for regtype, regid in regs:
-            if hex_common.is_written(regid):
-                gen_helper_return_opn(f, regtype, regid, i)
-        f.write("}\n\n")
-        ## End of the helper definition
+    ## Print useful information about HVX registers
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_hvx_reg():
+            reg.helper_hvx_desc(f)
+
+    if hex_common.need_slot(tag):
+        if "A_LOAD" in hex_common.attribdict[tag]:
+            f.write(hex_common.code_fmt(f"""\
+                bool pkt_has_store_s1 = slotval & 0x1;
+            """))
+        f.write(hex_common.code_fmt(f"""\
+            uint32_t slot = slotval >> 1;
+        """))
+
+    if "A_FPOP" in hex_common.attribdict[tag]:
+        f.write(hex_common.code_fmt(f"""\
+            arch_fpop_start(env);
+        """))
+
+    f.write(hex_common.code_fmt(f"""\
+        {hex_common.semdict[tag]}
+    """))
+
+    if "A_FPOP" in hex_common.attribdict[tag]:
+        f.write(hex_common.code_fmt(f"""\
+            arch_fpop_end(env);
+        """))
+
+    ## Return the scalar result
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written() and not reg.is_hvx_reg():
+            f.write(hex_common.code_fmt(f"""\
+                return {reg.helper_arg_name()};
+            """))
+
+    f.write("}\n\n")
+    ## End of the helper definition
 
 
 def main():
@@ -370,6 +119,7 @@ def main():
     if is_idef_parser_enabled:
         hex_common.read_idef_parser_enabled_file(sys.argv[5])
     hex_common.calculate_attribs()
+    hex_common.init_registers()
     tagregs = hex_common.get_tagregs()
     tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 2abd653e6d..fc9ce4e2b0 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -275,10 +275,6 @@ 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_next_PC(tag):
     return "A_CALL" in attribdict[tag]
 
@@ -680,6 +676,10 @@ def decl_tcg(self, f, tag, regno):
             """))
     def log_write(self, f, tag):
         pass
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
+        """))
 
 class VRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -692,6 +692,10 @@ def decl_tcg(self, f, tag, regno):
                 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
                 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
             """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
+        """))
 
 class VRegNewSource(Register, Hvx, NewSource):
     def decl_tcg(self, f, tag, regno):
@@ -701,6 +705,10 @@ def decl_tcg(self, f, tag, regno):
                 const intptr_t {self.hvx_off()} =
                     ctx_future_vreg_off(ctx, {self.reg_num}, 1, true);
             """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
+        """))
 
 class VRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -719,6 +727,10 @@ def decl_tcg(self, f, tag, regno):
             """))
     def log_write(self, f, tag):
         pass
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
+        """))
 
 class VRegTmp(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -739,6 +751,10 @@ def log_write(self, f, tag):
             gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num},
                                {hvx_newv(tag)});
         """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
+        """))
 
 class VRegPairDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -754,6 +770,10 @@ def decl_tcg(self, f, tag, regno):
             """))
     def log_write(self, f, tag):
         pass
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
+        """))
 
 class VRegPairSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -773,6 +793,10 @@ def decl_tcg(self, f, tag, regno):
                 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
                 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
             """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
+        """))
 
 class VRegPairReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -797,6 +821,10 @@ def log_write(self, f, tag):
             gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num},
                                     {hvx_newv(tag)});
         """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
+        """))
 
 class QRegDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -812,6 +840,10 @@ def decl_tcg(self, f, tag, regno):
             """))
     def log_write(self, f, tag):
         pass
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
+        """))
 
 class QRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -825,6 +857,10 @@ def decl_tcg(self, f, tag, regno):
                 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
                 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
             """))
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
+        """))
 
 class QRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -843,6 +879,10 @@ def decl_tcg(self, f, tag, regno):
             """))
     def log_write(self, f, tag):
         pass
+    def helper_hvx_desc(self, f):
+        f.write(code_fmt(f"""\
+            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
+        """))
 
 def init_registers():
     regs = {
-- 
2.25.1


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

* [PULL 07/15] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (5 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 06/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 08/15] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Brian Cain
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-6-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_idef_parser_funcs.py | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_idef_parser_funcs.py
index f4518e653f..550a48cb7b 100644
--- a/target/hexagon/gen_idef_parser_funcs.py
+++ b/target/hexagon/gen_idef_parser_funcs.py
@@ -46,6 +46,7 @@ def main():
     hex_common.read_semantics_file(sys.argv[1])
     hex_common.read_attribs_file(sys.argv[2])
     hex_common.calculate_attribs()
+    hex_common.init_registers()
     tagregs = hex_common.get_tagregs()
     tagimms = hex_common.get_tagimms()
 
@@ -132,22 +133,9 @@ def main():
 
             arguments = []
             for regtype, regid in regs:
-                prefix = "in " if hex_common.is_read(regid) else ""
-
-                is_pair = hex_common.is_pair(regid)
-                is_single_old = hex_common.is_single(regid) and hex_common.is_old_val(
-                    regtype, regid, tag
-                )
-                is_single_new = hex_common.is_single(regid) and hex_common.is_new_val(
-                    regtype, regid, tag
-                )
-
-                if is_pair or is_single_old:
-                    arguments.append(f"{prefix}{regtype}{regid}V")
-                elif is_single_new:
-                    arguments.append(f"{prefix}{regtype}{regid}N")
-                else:
-                    hex_common.bad_register(regtype, regid)
+                reg = hex_common.get_register(tag, regtype, regid)
+                prefix = "in " if reg.is_read() else ""
+                arguments.append(f"{prefix}{reg.reg_tcg()}")
 
             for immlett, bits, immshift in imms:
                 arguments.append(hex_common.imm_name(immlett))
-- 
2.25.1


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

* [PULL 08/15] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (6 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 07/15] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 09/15] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Brian Cain
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Reviewed-by: Brian Cain <bcain@quicinc.com>
Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Message-Id: <20231210220712.491494-7-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_op_regs.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py
index a8a7712129..7b7b33895a 100755
--- a/target/hexagon/gen_op_regs.py
+++ b/target/hexagon/gen_op_regs.py
@@ -70,6 +70,7 @@ def strip_reg_prefix(x):
 def main():
     hex_common.read_semantics_file(sys.argv[1])
     hex_common.read_attribs_file(sys.argv[2])
+    hex_common.init_registers()
     tagregs = hex_common.get_tagregs(full=True)
     tagimms = hex_common.get_tagimms()
 
@@ -80,11 +81,12 @@ def main():
             wregs = []
             regids = ""
             for regtype, regid, _, numregs in regs:
-                if hex_common.is_read(regid):
+                reg = hex_common.get_register(tag, regtype, regid)
+                if reg.is_read():
                     if regid[0] not in regids:
                         regids += regid[0]
                     rregs.append(regtype + regid + numregs)
-                if hex_common.is_written(regid):
+                if reg.is_written():
                     wregs.append(regtype + regid + numregs)
                     if regid[0] not in regids:
                         regids += regid[0]
-- 
2.25.1


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

* [PULL 09/15] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (7 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 08/15] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 10/15] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Brian Cain
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

This patch conflicts with
https://lists.gnu.org/archive/html/qemu-devel/2023-11/msg00729.html
If that series goes in first, we'll rework this patch and vice versa.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-8-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/gen_analyze_funcs.py | 163 +---------------------------
 target/hexagon/hex_common.py        | 151 ++++++++++++++++++++++++++
 2 files changed, 157 insertions(+), 157 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py
index c3b521abef..a9af666cef 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -23,162 +23,6 @@
 import hex_common
 
 
-##
-## Helpers for gen_analyze_func
-##
-def is_predicated(tag):
-    return "A_CONDEXEC" in hex_common.attribdict[tag]
-
-
-def analyze_opn_old(f, tag, regtype, regid, regno):
-    regN = f"{regtype}{regid}N"
-    predicated = "true" if is_predicated(tag) else "false"
-    if regtype == "R":
-        if regid in {"ss", "tt"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_read_pair(ctx, {regN});\n")
-        elif regid in {"dd", "ee", "xx", "yy"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_write_pair(ctx, {regN}, {predicated});\n")
-        elif regid in {"s", "t", "u", "v"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_read(ctx, {regN});\n")
-        elif regid in {"d", "e", "x", "y"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid in {"s", "t", "u", "v"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_pred_read(ctx, {regN});\n")
-        elif regid in {"d", "e", "x"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_pred_write(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "C":
-        if regid == "ss":
-            f.write(
-                f"    const int {regN} = insn->regno[{regno}] "
-                "+ HEX_REG_SA0;\n"
-            )
-            f.write(f"    ctx_log_reg_read_pair(ctx, {regN});\n")
-        elif regid == "dd":
-            f.write(f"    const int {regN} = insn->regno[{regno}] " "+ HEX_REG_SA0;\n")
-            f.write(f"    ctx_log_reg_write_pair(ctx, {regN}, {predicated});\n")
-        elif regid == "s":
-            f.write(
-                f"    const int {regN} = insn->regno[{regno}] "
-                "+ HEX_REG_SA0;\n"
-            )
-            f.write(f"    ctx_log_reg_read(ctx, {regN});\n")
-        elif regid == "d":
-            f.write(f"    const int {regN} = insn->regno[{regno}] " "+ HEX_REG_SA0;\n")
-            f.write(f"    ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "M":
-        if regid == "u":
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_read(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "V":
-        newv = "EXT_DFL"
-        if hex_common.is_new_result(tag):
-            newv = "EXT_NEW"
-        elif hex_common.is_tmp_result(tag):
-            newv = "EXT_TMP"
-        if regid in {"dd", "xx"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(
-                f"    ctx_log_vreg_write_pair(ctx, {regN}, {newv}, " f"{predicated});\n"
-            )
-        elif regid in {"uu", "vv"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_vreg_read_pair(ctx, {regN});\n")
-        elif regid in {"s", "u", "v", "w"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_vreg_read(ctx, {regN});\n")
-        elif regid in {"d", "x", "y"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_vreg_write(ctx, {regN}, {newv}, " f"{predicated});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "Q":
-        if regid in {"d", "e", "x"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_qreg_write(ctx, {regN});\n")
-        elif regid in {"s", "t", "u", "v"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_qreg_read(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "G":
-        if regid in {"dd"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"d"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"ss"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"s"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "S":
-        if regid in {"dd"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"d"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"ss"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        elif regid in {"s"}:
-            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def analyze_opn_new(f, tag, regtype, regid, regno):
-    regN = f"{regtype}{regid}N"
-    if regtype == "N":
-        if regid in {"s", "t"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_reg_read(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "P":
-        if regid in {"t", "u", "v"}:
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_pred_read(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    elif regtype == "O":
-        if regid == "s":
-            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
-            f.write(f"    ctx_log_vreg_read(ctx, {regN});\n")
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
-def analyze_opn(f, tag, regtype, regid, i):
-    if hex_common.is_pair(regid):
-        analyze_opn_old(f, tag, regtype, regid, i)
-    elif hex_common.is_single(regid):
-        if hex_common.is_old_val(regtype, regid, tag):
-            analyze_opn_old(f, tag, regtype, regid, i)
-        elif hex_common.is_new_val(regtype, regid, tag):
-            analyze_opn_new(f, tag, regtype, regid, i)
-        else:
-            hex_common.bad_register(regtype, regid)
-    else:
-        hex_common.bad_register(regtype, regid)
-
-
 ##
 ## Generate the code to analyze the instruction
 ##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
@@ -203,7 +47,11 @@ def gen_analyze_func(f, tag, regs, imms):
     i = 0
     ## Analyze all the registers
     for regtype, regid in regs:
-        analyze_opn(f, tag, regtype, regid, i)
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written():
+            reg.analyze_write(f, tag, i)
+        else:
+            reg.analyze_read(f, i)
         i += 1
 
     has_generated_helper = not hex_common.skip_qemu_helper(
@@ -236,6 +84,7 @@ def main():
     if is_idef_parser_enabled:
         hex_common.read_idef_parser_enabled_file(sys.argv[5])
     hex_common.calculate_attribs()
+    hex_common.init_registers()
     tagregs = hex_common.get_tagregs()
     tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index fc9ce4e2b0..4565dd1953 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -486,6 +486,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
+        """))
 
 class GprSource(Register, Single, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -493,12 +499,22 @@ def decl_tcg(self, f, tag, regno):
         f.write(code_fmt(f"""\
             TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read(ctx, {self.reg_num});
+        """))
 
 class GprNewSource(Register, Single, NewSource):
     def decl_tcg(self, f, tag, regno):
         f.write(code_fmt(f"""\
             TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]);
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read(ctx, {self.reg_num});
+        """))
 
 class GprReadWrite(Register, Single, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -517,6 +533,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
+        """))
 
 class ControlDest(Register, Single, Dest):
     def decl_reg_num(self, f, regno):
@@ -532,6 +554,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
+        """))
 
 class ControlSource(Register, Single, OldSource):
     def decl_reg_num(self, f, regno):
@@ -544,6 +572,11 @@ def decl_tcg(self, f, tag, regno):
             TCGv {self.reg_tcg()} = tcg_temp_new();
             gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read(ctx, {self.reg_num});
+        """))
 
 class ModifierSource(Register, Single, OldSource):
     def decl_reg_num(self, f, regno):
@@ -560,6 +593,11 @@ def decl_tcg(self, f, tag, regno):
     def idef_arg(self, declared):
         declared.append(self.reg_tcg())
         declared.append("CS")
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read(ctx, {self.reg_num});
+        """))
 
 class PredDest(Register, Single, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -571,6 +609,11 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_pred_write(ctx, {self.reg_num});
+        """))
 
 class PredSource(Register, Single, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -578,12 +621,22 @@ def decl_tcg(self, f, tag, regno):
         f.write(code_fmt(f"""\
             TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}];
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_pred_read(ctx, {self.reg_num});
+        """))
 
 class PredNewSource(Register, Single, NewSource):
     def decl_tcg(self, f, tag, regno):
         f.write(code_fmt(f"""\
             TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]);
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_pred_read(ctx, {self.reg_num});
+        """))
 
 class PredReadWrite(Register, Single, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -596,6 +649,11 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_pred_write(ctx, {self.reg_num});
+        """))
 
 class PairDest(Register, Pair, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -608,6 +666,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
+        """))
 
 class PairSource(Register, Pair, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -618,6 +682,11 @@ def decl_tcg(self, f, tag, regno):
                                     hex_gpr[{self.reg_num}],
                                     hex_gpr[{self.reg_num} + 1]);
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read_pair(ctx, {self.reg_num});
+        """))
 
 class PairReadWrite(Register, Pair, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -633,6 +702,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
+        """))
 
 class ControlPairDest(Register, Pair, Dest):
     def decl_reg_num(self, f, regno):
@@ -649,6 +724,12 @@ def log_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
+        """))
 
 class ControlPairSource(Register, Pair, OldSource):
     def decl_reg_num(self, f, regno):
@@ -661,6 +742,11 @@ def decl_tcg(self, f, tag, regno):
             TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
             gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_reg_read_pair(ctx, {self.reg_num});
+        """))
 
 class VRegDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -680,6 +766,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        newv = hvx_newv(tag)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
+        """))
 
 class VRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -696,6 +789,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_read(ctx, {self.reg_num});
+        """))
 
 class VRegNewSource(Register, Hvx, NewSource):
     def decl_tcg(self, f, tag, regno):
@@ -709,6 +807,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_read(ctx, {self.reg_num});
+        """))
 
 class VRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -731,6 +834,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        newv = hvx_newv(tag)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
+        """))
 
 class VRegTmp(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -755,6 +865,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        newv = hvx_newv(tag)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
+        """))
 
 class VRegPairDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -774,6 +891,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        newv = hvx_newv(tag)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated});
+        """))
 
 class VRegPairSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -797,6 +921,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_read_pair(ctx, {self.reg_num});
+        """))
 
 class VRegPairReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -825,6 +954,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        newv = hvx_newv(tag)
+        predicated = "true" if is_predicated(tag) else "false"
+        f.write(code_fmt(f"""\
+            ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated});
+        """))
 
 class QRegDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -844,6 +980,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_qreg_write(ctx, {self.reg_num});
+        """))
 
 class QRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -861,6 +1002,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
         """))
+    def analyze_read(self, f, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_qreg_read(ctx, {self.reg_num});
+        """))
 
 class QRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -883,6 +1029,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
         """))
+    def analyze_write(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            ctx_log_qreg_write(ctx, {self.reg_num});
+        """))
 
 def init_registers():
     regs = {
-- 
2.25.1


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

* [PULL 10/15] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (8 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 09/15] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 11/15] Hexagon (target/hexagon) Remove dead functions from hex_common.py Brian Cain
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

This is the only remaining use of the is_written function.  We will
remove it in the subsequent commit.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-9-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/attribs_def.h.inc |  1 -
 target/hexagon/hex_common.py     | 11 -----------
 2 files changed, 12 deletions(-)

diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 21d457fa4a..87942d46f4 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -117,7 +117,6 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
-DEF_ATTRIB(WRITES_PRED_REG, "Writes a predicate register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 4565dd1953..ca5e9630c1 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -94,10 +94,6 @@ def is_cond_call(tag):
 def calculate_attribs():
     add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC")
     add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
-    add_qemu_macro_attrib("fWRITE_P0", "A_WRITES_PRED_REG")
-    add_qemu_macro_attrib("fWRITE_P1", "A_WRITES_PRED_REG")
-    add_qemu_macro_attrib("fWRITE_P2", "A_WRITES_PRED_REG")
-    add_qemu_macro_attrib("fWRITE_P3", "A_WRITES_PRED_REG")
     add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
     add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
     add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
@@ -122,13 +118,6 @@ def calculate_attribs():
                 continue
             macro = macros[macname]
             attribdict[tag] |= set(macro.attribs)
-    # Figure out which instructions write predicate registers
-    tagregs = get_tagregs()
-    for tag in tags:
-        regs = tagregs[tag]
-        for regtype, regid 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:
-- 
2.25.1


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

* [PULL 11/15] Hexagon (target/hexagon) Remove dead functions from hex_common.py
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (9 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 10/15] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 12/15] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions) Brian Cain
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

These functions are no longer used after making the generators
object oriented.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20231210220712.491494-10-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/hex_common.py | 51 ------------------------------------
 1 file changed, 51 deletions(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index ca5e9630c1..195620c7ec 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -33,9 +33,6 @@
 overrides = {}  # tags with helper overrides
 idef_parser_enabled = {}  # tags enabled for idef-parser
 
-def bad_register(regtype, regid):
-    raise Exception(f"Bad register parse: regtype '{regtype}' regid '{regid}'")
-
 # We should do this as a hash for performance,
 # but to keep order let's keep it as a list.
 def uniquify(seq):
@@ -200,46 +197,6 @@ def get_tagimms():
     return dict(zip(tags, list(map(compute_tag_immediates, tags))))
 
 
-def is_pair(regid):
-    return len(regid) == 2
-
-
-def is_single(regid):
-    return len(regid) == 1
-
-
-def is_written(regid):
-    return regid[0] in "dexy"
-
-
-def is_writeonly(regid):
-    return regid[0] in "de"
-
-
-def is_read(regid):
-    return regid[0] in "stuvwxy"
-
-
-def is_readwrite(regid):
-    return regid[0] in "xy"
-
-
-def is_scalar_reg(regtype):
-    return regtype in "RPC"
-
-
-def is_hvx_reg(regtype):
-    return regtype in "VQ"
-
-
-def is_old_val(regtype, regid, tag):
-    return regtype + regid + "V" in semdict[tag]
-
-
-def is_new_val(regtype, regid, tag):
-    return regtype + regid + "N" in semdict[tag]
-
-
 def need_slot(tag):
     if (
         "A_CVI_SCATTER" not in attribdict[tag]
@@ -280,14 +237,6 @@ def skip_qemu_helper(tag):
     return tag in overrides.keys()
 
 
-def is_tmp_result(tag):
-    return "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]
-
-
-def is_new_result(tag):
-    return "A_CVI_NEW" in attribdict[tag]
-
-
 def is_idef_parser_enabled(tag):
     return tag in idef_parser_enabled
 
-- 
2.25.1


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

* [PULL 12/15] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (10 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 11/15] Hexagon (target/hexagon) Remove dead functions from hex_common.py Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:34 ` [PULL 13/15] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions) Brian Cain
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

The Decodetree Specification can be found here
https://www.qemu.org/docs/master/devel/decodetree.html

Covers all 32-bit instructions, including HVX

We generate separate decoders for each instruction class.  The reason
will be more apparent in the next patch in this series.

We add 2 new scripts
    gen_decodetree.py        Generate the input to decodetree.py
    gen_trans_funcs.py       Generate the trans_* functions used by the
                             output of decodetree.py

Since the functions generated by decodetree.py take DisasContext * as an
argument, we add the argument to a couple of functions that didn't need
it previously.  We also set the insn field in DisasContext during decode
because it is used by the trans_* functions.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 32-bit instructions

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20240115221443.365287-2-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/README             |  13 +-
 target/hexagon/decode.c           |  54 ++++++++-
 target/hexagon/decode.h           |   5 +-
 target/hexagon/gen_decodetree.py  | 190 ++++++++++++++++++++++++++++++
 target/hexagon/gen_trans_funcs.py | 132 +++++++++++++++++++++
 target/hexagon/meson.build        |  55 +++++++++
 target/hexagon/translate.c        |   4 +-
 7 files changed, 439 insertions(+), 14 deletions(-)
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

diff --git a/target/hexagon/README b/target/hexagon/README
index 69b2ffe9bb..1b2a4d0eac 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -189,11 +189,16 @@ the packet, and we mark the implicit writes.  After the analysis is performed,
 we initialize the result register for each of the predicated assignments.
 
 In addition to instruction semantics, we use a generator to create the decode
-tree.  This generation is also a two step process.  The first step is to run
-target/hexagon/gen_dectree_import.c to produce
+tree.  This generation is a four step process.
+Step 1 is to run target/hexagon/gen_dectree_import.c to produce
     <BUILD_DIR>/target/hexagon/iset.py
-This file is imported by target/hexagon/dectree.py to produce
-    <BUILD_DIR>/target/hexagon/dectree_generated.h.inc
+Step 2 is to import iset.py into target/hexagon/gen_decodetree.py to produce
+    <BUILD_DIR>/target/hexagon/normal_decode_generated
+    <BUILD_DIR>/target/hexagon/hvx_decode_generated
+Step 3 is to process the above files with QEMU's decodetree.py to produce
+    <BUILD_DIR>/target/hexagon/decode_*_generated.c.inc
+Step 4 is to import iset.py into target/hexagon/gen_trans_funcs.py to produce
+    <BUILD_DIR>/target/hexagon/decodetree_trans_funcs_generated.c.inc
 
 *** Key Files ***
 
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 946c55cc71..bddad1f75e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -52,6 +52,34 @@ DEF_REGMAP(R_8,   8,  0, 1, 2, 3, 4, 5, 6, 7)
 #define DECODE_MAPPED_REG(OPNUM, NAME) \
     insn->regno[OPNUM] = DECODE_REGISTER_##NAME[insn->regno[OPNUM]];
 
+/* Helper functions for decode_*_generated.c.inc */
+#define DECODE_MAPPED(NAME) \
+static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) \
+{ \
+    return DECODE_REGISTER_##NAME[x]; \
+}
+DECODE_MAPPED(R_16)
+DECODE_MAPPED(R_8)
+
+/* Helper function for decodetree_trans_funcs_generated.c.inc */
+static int shift_left(DisasContext *ctx, int x, int n, int immno)
+{
+    int ret = x;
+    Insn *insn = ctx->insn;
+    if (!insn->extension_valid ||
+        insn->which_extended != immno) {
+        ret <<= n;
+    }
+    return ret;
+}
+
+/* Include the generated decoder for 32 bit insn */
+#include "decode_normal_generated.c.inc"
+#include "decode_hvx_generated.c.inc"
+
+/* Include the generated helpers for the decoder */
+#include "decodetree_trans_funcs_generated.c.inc"
+
 typedef struct {
     const struct DectreeTable *table_link;
     const struct DectreeTable *table_link_b;
@@ -550,7 +578,8 @@ apply_extender(Packet *pkt, int i, uint32_t extender)
     int immed_num;
     uint32_t base_immed;
 
-    immed_num = opcode_which_immediate_is_extended(pkt->insn[i].opcode);
+    immed_num = pkt->insn[i].which_extended;
+    g_assert(immed_num == opcode_which_immediate_is_extended(pkt->insn[i].opcode));
     base_immed = pkt->insn[i].immed[immed_num];
 
     pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
@@ -762,12 +791,19 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable *table,
 }
 
 static unsigned int
-decode_insns(Insn *insn, uint32_t encoding)
+decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
     const DectreeTable *table;
     if (parse_bits(encoding) != 0) {
+        if (decode_normal(ctx, encoding) ||
+            decode_hvx(ctx, encoding)) {
+            insn->generate = opcode_genptr[insn->opcode];
+            insn->iclass = iclass_bits(encoding);
+            return 1;
+        }
         /* Start with PP table - 32 bit instructions */
         table = &dectree_table_DECODE_ROOT_32;
+        g_assert_not_reached();
     } else {
         /* start with EE table - duplex instructions */
         table = &dectree_table_DECODE_ROOT_EE;
@@ -916,8 +952,8 @@ decode_set_slot_number(Packet *pkt)
  * or number of words used on success
  */
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-                  bool disas_only)
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+                  Packet *pkt, bool disas_only)
 {
     int num_insns = 0;
     int words_read = 0;
@@ -930,9 +966,11 @@ int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
     memset(pkt, 0, sizeof(*pkt));
     /* Try to build packet */
     while (!end_of_packet && (words_read < max_words)) {
+        Insn *insn = &pkt->insn[num_insns];
+        ctx->insn = insn;
         encoding32 = words[words_read];
         end_of_packet = is_packet_end(encoding32);
-        new_insns = decode_insns(&pkt->insn[num_insns], encoding32);
+        new_insns = decode_insns(ctx, insn, encoding32);
         g_assert(new_insns > 0);
         /*
          * If we saw an extender, mark next word extended so immediate
@@ -1006,9 +1044,13 @@ int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
 int disassemble_hexagon(uint32_t *words, int nwords, bfd_vma pc,
                         GString *buf)
 {
+    DisasContext ctx;
     Packet pkt;
 
-    if (decode_packet(nwords, words, &pkt, true) > 0) {
+    memset(&ctx, 0, sizeof(DisasContext));
+    ctx.pkt = &pkt;
+
+    if (decode_packet(&ctx, nwords, words, &pkt, true) > 0) {
         snprint_a_pkt_disas(buf, &pkt, words, pc);
         return pkt.encod_pkt_size_in_bytes;
     } else {
diff --git a/target/hexagon/decode.h b/target/hexagon/decode.h
index c66f5ea64d..3f3012b978 100644
--- a/target/hexagon/decode.h
+++ b/target/hexagon/decode.h
@@ -21,12 +21,13 @@
 #include "cpu.h"
 #include "opcodes.h"
 #include "insn.h"
+#include "translate.h"
 
 void decode_init(void);
 
 void decode_send_insn_to(Packet *packet, int start, int newloc);
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-                  bool disas_only);
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+                  Packet *pkt, bool disas_only);
 
 #endif
diff --git a/target/hexagon/gen_decodetree.py b/target/hexagon/gen_decodetree.py
new file mode 100755
index 0000000000..9634554142
--- /dev/null
+++ b/target/hexagon/gen_decodetree.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+
+##
+##  Copyright (c) 2024 Taylor Simpson <ltaylorsimpson@gmail.com>
+##
+##  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
+##  the Free Software Foundation; either version 2 of the License, or
+##  (at your option) any later version.
+##
+##  This program is distributed in the hope that it will be useful,
+##  but WITHOUT ANY WARRANTY; without even the implied warranty of
+##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+##  GNU General Public License for more details.
+##
+##  You should have received a copy of the GNU General Public License
+##  along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+import io
+import re
+
+import sys
+import textwrap
+import iset
+import hex_common
+
+encs = {
+    tag: "".join(reversed(iset.iset[tag]["enc"].replace(" ", "")))
+    for tag in iset.tags
+    if iset.iset[tag]["enc"] != "MISSING ENCODING"
+}
+
+
+regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
+immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
+
+
+def ordered_unique(l):
+    return sorted(set(l), key=l.index)
+
+num_registers = {"R": 32, "V": 32}
+
+operand_letters = {
+    "P",
+    "i",
+    "I",
+    "r",
+    "s",
+    "t",
+    "u",
+    "v",
+    "w",
+    "x",
+    "y",
+    "z",
+    "d",
+    "e",
+    "f",
+    "g",
+}
+
+#
+# These instructions have unused operand letters in their encoding
+# They don't correspond to actual operands in the instruction semantics
+# We will mark them as ignored in QEMU decodetree
+#
+tags_with_unused_d_encoding = {
+    "R6_release_at_vi",
+    "R6_release_st_vi",
+    "S4_stored_rl_at_vi",
+    "S4_stored_rl_st_vi",
+    "S2_storew_rl_at_vi",
+    "S2_stored_rl_at_vi",
+    "S2_storew_rl_st_vi",
+}
+
+tags_with_unused_t_encoding = {
+    "R6_release_at_vi",
+    "R6_release_st_vi",
+}
+
+def skip_tag(tag, class_to_decode):
+    enc_class = iset.iset[tag]["enc_class"]
+    return enc_class != class_to_decode
+
+
+##
+## Generate the QEMU decodetree file for each instruction in class_to_decode
+##     For A2_add: Rd32=add(Rs32,Rt32)
+##     We produce:
+##     %A2_add_Rd   0:5
+##     %A2_add_Rs   16:5
+##     %A2_add_Rt   8:5
+##     @A2_add  11110011000.......-.....---..... Rd=%A2_add_Rd Rs=%A2_add_Rs Rt=%A2_add_Rt %PP
+##     A2_add   ..................-.....---..... @A2_add
+##
+def gen_decodetree_file(f, class_to_decode):
+    f.write(f"## DO NOT MODIFY - This file is generated by {sys.argv[0]}\n\n")
+    f.write("%PP\t14:2\n\n")
+    for tag in sorted(encs.keys(), key=iset.tags.index):
+        if skip_tag(tag, class_to_decode):
+            continue
+
+        enc = encs[tag]
+        enc_str = "".join(reversed(encs[tag]))
+        f.write(("#" * 80) + "\n"
+                f"## {tag}:\t{enc_str}\n"
+                "##\n")
+
+
+        regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
+        imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
+
+        # Write the field definitions for the registers
+        for regno, reg in enumerate(regs):
+            reg_type, reg_id, _, reg_enc_size = reg
+            reg_letter = reg_id[0]
+            reg_num_choices = int(reg_enc_size.rstrip("S"))
+            reg_mapping = reg_type + "".join("_" for letter in reg_id) + \
+                          reg_enc_size
+            reg_enc_fields = re.findall(reg_letter + "+", enc)
+
+            # Check for some errors
+            if len(reg_enc_fields) == 0:
+                raise Exception(f"{tag} missing register field!")
+            if len(reg_enc_fields) > 1:
+                raise Exception(f"{tag} has split register field!")
+            reg_enc_field = reg_enc_fields[0]
+            if 2 ** len(reg_enc_field) != reg_num_choices:
+                raise Exception(f"{tag} has incorrect register field width!")
+
+            f.write(f"%{tag}_{reg_type}{reg_id}\t"
+                    f"{enc.index(reg_enc_field)}:{len(reg_enc_field)}")
+
+            if (reg_type in num_registers and
+                reg_num_choices != num_registers[reg_type]):
+                f.write(f"\t!function=decode_mapped_reg_{reg_mapping}")
+            f.write("\n")
+
+        # Write the field definitions for the immediates
+        for imm in imms:
+            immno = 1 if imm[0].isupper() else 0
+            imm_type = imm[0]
+            imm_width = int(imm[1])
+            imm_letter = "i" if imm_type.islower() else "I"
+            fields = []
+            sign_mark = "s" if imm_type.lower() in "sr" else ""
+            for m in reversed(list(re.finditer(imm_letter + "+", enc))):
+                fields.append(f"{m.start()}:{sign_mark}{m.end() - m.start()}")
+                sign_mark = ""
+            field_str = " ".join(fields)
+            f.write(f"%{tag}_{imm_type}{imm_letter}\t{field_str}\n")
+
+        ## Handle instructions with unused encoding letters
+        ## Change the unused letters to ignored
+        if tag in tags_with_unused_d_encoding:
+            enc_str = enc_str.replace("d", "-")
+        if tag in tags_with_unused_t_encoding:
+            enc_str = enc_str.replace("t", "-")
+
+        # Replace the operand letters with .
+        for x in operand_letters:
+            enc_str = enc_str.replace(x, ".")
+
+        # Write the instruction format
+        f.write(f"@{tag}\t{enc_str}")
+        for reg in regs:
+            reg_type = reg[0]
+            reg_id = reg[1]
+            f.write(f" {reg_type}{reg_id}=%{tag}_{reg_type}{reg_id}")
+        for imm in imms:
+            imm_type = imm[0]
+            imm_letter = "i" if imm_type.islower() else "I"
+            f.write(f" {imm_type}{imm_letter}=%{tag}_{imm_type}{imm_letter}")
+
+        f.write(" %PP\n")
+
+         # Replace the 0s and 1s with .
+        enc_str = enc_str.replace("0", ".").replace("1", ".")
+
+        # Write the instruction pattern
+        f.write(f"{tag}\t{enc_str} @{tag}\n")
+
+
+if __name__ == "__main__":
+    hex_common.read_semantics_file(sys.argv[1])
+    class_to_decode = sys.argv[2]
+    with open(sys.argv[3], "w") as f:
+        gen_decodetree_file(f, class_to_decode)
diff --git a/target/hexagon/gen_trans_funcs.py b/target/hexagon/gen_trans_funcs.py
new file mode 100755
index 0000000000..c907131009
--- /dev/null
+++ b/target/hexagon/gen_trans_funcs.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+
+##
+##  Copyright (c) 2024 Taylor Simpson <ltaylorsimpson@gmail.com>
+##
+##  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
+##  the Free Software Foundation; either version 2 of the License, or
+##  (at your option) any later version.
+##
+##  This program is distributed in the hope that it will be useful,
+##  but WITHOUT ANY WARRANTY; without even the implied warranty of
+##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+##  GNU General Public License for more details.
+##
+##  You should have received a copy of the GNU General Public License
+##  along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+import io
+import re
+
+import sys
+import textwrap
+import iset
+import hex_common
+
+encs = {
+    tag: "".join(reversed(iset.iset[tag]["enc"].replace(" ", "")))
+    for tag in iset.tags
+    if iset.iset[tag]["enc"] != "MISSING ENCODING"
+}
+
+
+regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
+immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
+
+
+def ordered_unique(l):
+    return sorted(set(l), key=l.index)
+
+
+def skip_tag(tag, classes):
+    enc_class = iset.iset[tag]["enc_class"]
+    return enc_class not in classes
+
+
+def code_fmt(txt):
+    return textwrap.indent(textwrap.dedent(txt), "    ")
+
+open_curly = "{"
+close_curly = "}"
+
+def mark_which_imm_extended(f, tag):
+    immre = re.compile(r"IMMEXT\([rRsSuUm]")
+    imm = immre.findall(hex_common.semdict[tag])
+    if len(imm) == 0:
+        # No extended operand found
+        return
+    letter = re.split("\\(", imm[0])[1]
+    f.write(code_fmt(f"""\
+        insn->which_extended = {0 if letter.islower() else 1};
+    """))
+
+##
+## Generate the QEMU decodetree trans_<tag> function for each instruction
+##     For A2_add: Rd32=add(Rs32,Rt32)
+##     We produce:
+##     static bool trans_A2_add(DisasContext *ctx, arg_A2_add *args)
+##     {
+##         Insn *insn = ctx->insn;
+##         insn->opcode = A2_add;
+##         insn->regno[0] = args->Rd;
+##         insn->regno[1] = args->Rs;
+##         insn->regno[2] = args->Rt;
+##         return true;
+##     }
+##
+def gen_trans_funcs(f, classes):
+    f.write(f"/* DO NOT MODIFY - This file is generated by {sys.argv[0]} */\n\n")
+    for tag in sorted(encs.keys(), key=iset.tags.index):
+        if skip_tag(tag, classes):
+            continue
+
+        regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
+        imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
+
+        f.write(textwrap.dedent(f"""\
+            static bool trans_{tag}(DisasContext *ctx, arg_{tag} *args)
+            {open_curly}
+                Insn *insn = ctx->insn;
+                insn->opcode = {tag};
+        """))
+
+        regno = 0
+        for reg in regs:
+            reg_type = reg[0]
+            reg_id = reg[1]
+            f.write(code_fmt(f"""\
+                insn->regno[{regno}] = args->{reg_type}{reg_id};
+            """))
+            regno += 1
+
+        if len(imms) != 0:
+            mark_which_imm_extended(f, tag)
+
+        for imm in imms:
+            imm_type = imm[0]
+            imm_letter = "i" if imm_type.islower() else "I"
+            immno = 0 if imm_type.islower() else 1
+            imm_shift = int(imm[2]) if imm[2] else 0
+            if imm_shift:
+                f.write(code_fmt(f"""\
+                    insn->immed[{immno}] =
+                        shift_left(ctx, args->{imm_type}{imm_letter},
+                                   {imm_shift}, {immno});
+                """))
+            else:
+                f.write(code_fmt(f"""\
+                    insn->immed[{immno}] = args->{imm_type}{imm_letter};
+                """))
+
+        f.write(textwrap.dedent(f"""\
+                return true;
+            {close_curly}
+        """))
+
+
+if __name__ == "__main__":
+    hex_common.read_semantics_file(sys.argv[1])
+    with open(sys.argv[2], "w") as f:
+        gen_trans_funcs(f, { "NORMAL", "EXT_mmvec" })
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index da8e608d00..831bd5716a 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -133,6 +133,61 @@ dectree_generated = custom_target(
 )
 hexagon_ss.add(dectree_generated)
 
+#
+# Generate the input to the QEMU decodetree.py script
+#
+normal_decode_generated = custom_target(
+    'normal_decode_generated',
+    output: 'normal_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'NORMAL', '@OUTPUT@'],
+)
+hexagon_ss.add(normal_decode_generated)
+
+hvx_decode_generated = custom_target(
+    'hvx_decode_generated',
+    output: 'hvx_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'EXT_mmvec', '@OUTPUT@'],
+)
+hexagon_ss.add(hvx_decode_generated)
+
+#
+# Run the QEMU decodetree.py script to produce the instruction decoder
+#
+decodetree_py = meson.current_source_dir() / '../../scripts/decodetree.py'
+decode_normal_generated = custom_target(
+    'decode_normal_generated.c.inc',
+    output: 'decode_normal_generated.c.inc',
+    input: normal_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), normal_decode_generated, '--static-decode=decode_normal', '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_normal_generated)
+
+decode_hvx_generated = custom_target(
+    'decode_hvx_generated.c.inc',
+    output: 'decode_hvx_generated.c.inc',
+    input: hvx_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), hvx_decode_generated, '--static-decode=decode_hvx', '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_hvx_generated)
+
+#
+# Generate the trans_* functions that the decoder will use
+#
+decodetree_trans_funcs_generated = custom_target(
+    'decodetree_trans_funcs_generated.c.inc',
+    output: 'decodetree_trans_funcs_generated.c.inc',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_trans_funcs.py'), semantics_generated, '@OUTPUT@'],
+)
+hexagon_ss.add(decodetree_trans_funcs_generated)
+
 hexagon_ss.add(files(
     'cpu.c',
     'translate.c',
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 666c061180..95579ae243 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -1033,10 +1033,10 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
         return;
     }
 
-    if (decode_packet(nwords, words, &pkt, false) > 0) {
+    ctx->pkt = &pkt;
+    if (decode_packet(ctx, nwords, words, &pkt, false) > 0) {
         pkt.pc = ctx->base.pc_next;
         HEX_DEBUG_PRINT_PKT(&pkt);
-        ctx->pkt = &pkt;
         gen_start_packet(ctx);
         for (i = 0; i < pkt.num_insns; i++) {
             ctx->insn = &pkt.insn[i];
-- 
2.25.1


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

* [PULL 13/15] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (11 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 12/15] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions) Brian Cain
@ 2024-01-22  6:34 ` Brian Cain
  2024-01-22  6:35 ` [PULL 14/15] Hexagon (target/hexagon) Remove old dectree.py Brian Cain
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Section 10.3 of the Hexagon V73 Programmer's Reference Manual

A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
The sub-instructions that comprise a duplex are encoded as 13-bit fields
in the duplex.

Create a decoder for each subinstruction class (a, l1, l2, s1, s2).

Extend gen_trans_funcs.py to handle all instructions rather than
filter by instruction class.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 16-bit instructions.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20240115221443.365287-3-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/README             |  1 +
 target/hexagon/decode.c           | 85 +++++++++++++++++++++++++++++
 target/hexagon/gen_decodetree.py  | 12 ++++-
 target/hexagon/gen_trans_funcs.py | 12 +----
 target/hexagon/meson.build        | 90 +++++++++++++++++++++++++++++++
 5 files changed, 188 insertions(+), 12 deletions(-)

diff --git a/target/hexagon/README b/target/hexagon/README
index 1b2a4d0eac..746ebec378 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -195,6 +195,7 @@ Step 1 is to run target/hexagon/gen_dectree_import.c to produce
 Step 2 is to import iset.py into target/hexagon/gen_decodetree.py to produce
     <BUILD_DIR>/target/hexagon/normal_decode_generated
     <BUILD_DIR>/target/hexagon/hvx_decode_generated
+    <BUILD_DIR>/target/hexagon/subinsn_*_decode_generated
 Step 3 is to process the above files with QEMU's decodetree.py to produce
     <BUILD_DIR>/target/hexagon/decode_*_generated.c.inc
 Step 4 is to import iset.py into target/hexagon/gen_trans_funcs.py to produce
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index bddad1f75e..160b23a895 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -60,6 +60,7 @@ static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) \
 }
 DECODE_MAPPED(R_16)
 DECODE_MAPPED(R_8)
+DECODE_MAPPED(R__8)
 
 /* Helper function for decodetree_trans_funcs_generated.c.inc */
 static int shift_left(DisasContext *ctx, int x, int n, int immno)
@@ -77,6 +78,13 @@ static int shift_left(DisasContext *ctx, int x, int n, int immno)
 #include "decode_normal_generated.c.inc"
 #include "decode_hvx_generated.c.inc"
 
+/* Include the generated decoder for 16 bit insn */
+#include "decode_subinsn_a_generated.c.inc"
+#include "decode_subinsn_l1_generated.c.inc"
+#include "decode_subinsn_l2_generated.c.inc"
+#include "decode_subinsn_s1_generated.c.inc"
+#include "decode_subinsn_s2_generated.c.inc"
+
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
@@ -790,6 +798,63 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable *table,
     }
 }
 
+/*
+ * Section 10.3 of the Hexagon V73 Programmer's Reference Manual
+ *
+ * A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
+ * The sub-instructions that comprise a duplex are encoded as 13-bit fields
+ * in the duplex.
+ *
+ * Per table 10-4, the 4-bit duplex iclass is encoded in bits 31:29, 13
+ */
+static uint32_t get_duplex_iclass(uint32_t encoding)
+{
+    uint32_t iclass = extract32(encoding, 13, 1);
+    iclass = deposit32(iclass, 1, 3, extract32(encoding, 29, 3));
+    return iclass;
+}
+
+/*
+ * Per table 10-5, the duplex ICLASS field values that specify the group of
+ * each sub-instruction in a duplex
+ *
+ * This table points to the decode instruction for each entry in the table
+ */
+typedef bool (*subinsn_decode_func)(DisasContext *ctx, uint16_t insn);
+typedef struct {
+    subinsn_decode_func decode_slot0_subinsn;
+    subinsn_decode_func decode_slot1_subinsn;
+} subinsn_decode_groups;
+
+static const subinsn_decode_groups decode_groups[16] = {
+    [0x0] = { decode_subinsn_l1, decode_subinsn_l1 },
+    [0x1] = { decode_subinsn_l2, decode_subinsn_l1 },
+    [0x2] = { decode_subinsn_l2, decode_subinsn_l2 },
+    [0x3] = { decode_subinsn_a,  decode_subinsn_a },
+    [0x4] = { decode_subinsn_l1, decode_subinsn_a },
+    [0x5] = { decode_subinsn_l2, decode_subinsn_a },
+    [0x6] = { decode_subinsn_s1, decode_subinsn_a },
+    [0x7] = { decode_subinsn_s2, decode_subinsn_a },
+    [0x8] = { decode_subinsn_s1, decode_subinsn_l1 },
+    [0x9] = { decode_subinsn_s1, decode_subinsn_l2 },
+    [0xa] = { decode_subinsn_s1, decode_subinsn_s1 },
+    [0xb] = { decode_subinsn_s2, decode_subinsn_s1 },
+    [0xc] = { decode_subinsn_s2, decode_subinsn_l1 },
+    [0xd] = { decode_subinsn_s2, decode_subinsn_l2 },
+    [0xe] = { decode_subinsn_s2, decode_subinsn_s2 },
+    [0xf] = { NULL,              NULL },              /* Reserved */
+};
+
+static uint16_t get_slot0_subinsn(uint32_t encoding)
+{
+    return extract32(encoding, 0, 13);
+}
+
+static uint16_t get_slot1_subinsn(uint32_t encoding)
+{
+    return extract32(encoding, 16, 13);
+}
+
 static unsigned int
 decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
@@ -805,8 +870,28 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
         table = &dectree_table_DECODE_ROOT_32;
         g_assert_not_reached();
     } else {
+        uint32_t iclass = get_duplex_iclass(encoding);
+        unsigned int slot0_subinsn = get_slot0_subinsn(encoding);
+        unsigned int slot1_subinsn = get_slot1_subinsn(encoding);
+        subinsn_decode_func decode_slot0_subinsn =
+            decode_groups[iclass].decode_slot0_subinsn;
+        subinsn_decode_func decode_slot1_subinsn =
+            decode_groups[iclass].decode_slot1_subinsn;
+
+        /* The slot1 subinsn needs to be in the packet first */
+        if (decode_slot1_subinsn(ctx, slot1_subinsn)) {
+            insn->generate = opcode_genptr[insn->opcode];
+            insn->iclass = iclass_bits(encoding);
+            ctx->insn = ++insn;
+            if (decode_slot0_subinsn(ctx, slot0_subinsn)) {
+                insn->generate = opcode_genptr[insn->opcode];
+                insn->iclass = iclass_bits(encoding);
+                return 2;
+            }
+        }
         /* start with EE table - duplex instructions */
         table = &dectree_table_DECODE_ROOT_EE;
+        g_assert_not_reached();
     }
     return decode_insns_tablewalk(insn, table, encoding);
 }
diff --git a/target/hexagon/gen_decodetree.py b/target/hexagon/gen_decodetree.py
index 9634554142..a4fcd622c5 100755
--- a/target/hexagon/gen_decodetree.py
+++ b/target/hexagon/gen_decodetree.py
@@ -96,8 +96,10 @@ def skip_tag(tag, class_to_decode):
 ##     A2_add   ..................-.....---..... @A2_add
 ##
 def gen_decodetree_file(f, class_to_decode):
+    is_subinsn = class_to_decode.startswith("SUBINSN_")
     f.write(f"## DO NOT MODIFY - This file is generated by {sys.argv[0]}\n\n")
-    f.write("%PP\t14:2\n\n")
+    if not is_subinsn:
+        f.write("%PP\t14:2\n\n")
     for tag in sorted(encs.keys(), key=iset.tags.index):
         if skip_tag(tag, class_to_decode):
             continue
@@ -108,6 +110,10 @@ def gen_decodetree_file(f, class_to_decode):
                 f"## {tag}:\t{enc_str}\n"
                 "##\n")
 
+        # The subinstructions come with a 13-bit encoding, but
+        # decodetree.py needs 16 bits
+        if is_subinsn:
+            enc_str = "---" + enc_str
 
         regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
         imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
@@ -174,7 +180,9 @@ def gen_decodetree_file(f, class_to_decode):
             imm_letter = "i" if imm_type.islower() else "I"
             f.write(f" {imm_type}{imm_letter}=%{tag}_{imm_type}{imm_letter}")
 
-        f.write(" %PP\n")
+        if not is_subinsn:
+            f.write(" %PP")
+        f.write("\n")
 
          # Replace the 0s and 1s with .
         enc_str = enc_str.replace("0", ".").replace("1", ".")
diff --git a/target/hexagon/gen_trans_funcs.py b/target/hexagon/gen_trans_funcs.py
index c907131009..53e844a44b 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -40,11 +40,6 @@ def ordered_unique(l):
     return sorted(set(l), key=l.index)
 
 
-def skip_tag(tag, classes):
-    enc_class = iset.iset[tag]["enc_class"]
-    return enc_class not in classes
-
-
 def code_fmt(txt):
     return textwrap.indent(textwrap.dedent(txt), "    ")
 
@@ -76,12 +71,9 @@ def mark_which_imm_extended(f, tag):
 ##         return true;
 ##     }
 ##
-def gen_trans_funcs(f, classes):
+def gen_trans_funcs(f):
     f.write(f"/* DO NOT MODIFY - This file is generated by {sys.argv[0]} */\n\n")
     for tag in sorted(encs.keys(), key=iset.tags.index):
-        if skip_tag(tag, classes):
-            continue
-
         regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
         imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
 
@@ -129,4 +121,4 @@ def gen_trans_funcs(f, classes):
 if __name__ == "__main__":
     hex_common.read_semantics_file(sys.argv[1])
     with open(sys.argv[2], "w") as f:
-        gen_trans_funcs(f, { "NORMAL", "EXT_mmvec" })
+        gen_trans_funcs(f)
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index 831bd5716a..1bd1ebcba1 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -154,6 +154,51 @@ hvx_decode_generated = custom_target(
 )
 hexagon_ss.add(hvx_decode_generated)
 
+subinsn_a_decode_generated = custom_target(
+    'subinsn_a_decode_generated',
+    output: 'subinsn_a_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_A', '@OUTPUT@'],
+)
+hexagon_ss.add(subinsn_a_decode_generated)
+
+subinsn_l1_decode_generated = custom_target(
+    'subinsn_l1_decode_generated',
+    output: 'subinsn_l1_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_L1', '@OUTPUT@'],
+)
+hexagon_ss.add(subinsn_l1_decode_generated)
+
+subinsn_l2_decode_generated = custom_target(
+    'subinsn_l2_decode_generated',
+    output: 'subinsn_l2_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_L2', '@OUTPUT@'],
+)
+hexagon_ss.add(subinsn_l2_decode_generated)
+
+subinsn_s1_decode_generated = custom_target(
+    'subinsn_s1_decode_generated',
+    output: 'subinsn_s1_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_S1', '@OUTPUT@'],
+)
+hexagon_ss.add(subinsn_s1_decode_generated)
+
+subinsn_s2_decode_generated = custom_target(
+    'subinsn_s2_decode_generated',
+    output: 'subinsn_s2_decode_generated',
+    depends: [iset_py, semantics_generated],
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_S2', '@OUTPUT@'],
+)
+hexagon_ss.add(subinsn_s2_decode_generated)
+
 #
 # Run the QEMU decodetree.py script to produce the instruction decoder
 #
@@ -176,6 +221,51 @@ decode_hvx_generated = custom_target(
 )
 hexagon_ss.add(decode_hvx_generated)
 
+decode_subinsn_a_generated = custom_target(
+    'decode_subinsn_a_generated.c.inc',
+    output: 'decode_subinsn_a_generated.c.inc',
+    input: subinsn_a_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), subinsn_a_decode_generated, ['--static-decode=decode_subinsn_a', '--insnwidth=16'], '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_subinsn_a_generated)
+
+decode_subinsn_l1_generated = custom_target(
+    'decode_subinsn_l1_generated.c.inc',
+    output: 'decode_subinsn_l1_generated.c.inc',
+    input: subinsn_l1_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), subinsn_l1_decode_generated, ['--static-decode=decode_subinsn_l1', '--insnwidth=16'], '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_subinsn_l1_generated)
+
+decode_subinsn_l2_generated = custom_target(
+    'decode_subinsn_l2_generated.c.inc',
+    output: 'decode_subinsn_l2_generated.c.inc',
+    input: subinsn_l2_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), subinsn_l2_decode_generated, ['--static-decode=decode_subinsn_l2', '--insnwidth=16'], '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_subinsn_l2_generated)
+
+decode_subinsn_s1_generated = custom_target(
+    'decode_subinsn_s1_generated.c.inc',
+    output: 'decode_subinsn_s1_generated.c.inc',
+    input: subinsn_s1_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), subinsn_s1_decode_generated, ['--static-decode=decode_subinsn_s1', '--insnwidth=16'], '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_subinsn_s1_generated)
+
+decode_subinsn_s2_generated = custom_target(
+    'decode_subinsn_s2_generated.c.inc',
+    output: 'decode_subinsn_s2_generated.c.inc',
+    input: subinsn_s2_decode_generated,
+    env: {'PYTHONPATH': meson.current_build_dir()},
+    command: [python, files(decodetree_py), subinsn_s2_decode_generated, ['--static-decode=decode_subinsn_s2', '--insnwidth=16'], '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_subinsn_s2_generated)
+
 #
 # Generate the trans_* functions that the decoder will use
 #
-- 
2.25.1


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

* [PULL 14/15] Hexagon (target/hexagon) Remove old dectree.py
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (12 preceding siblings ...)
  2024-01-22  6:34 ` [PULL 13/15] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions) Brian Cain
@ 2024-01-22  6:35 ` Brian Cain
  2024-01-22  6:35 ` [PULL 15/15] target/hexagon: reduce scope of def_regnum, remove dead assignment Brian Cain
  2024-01-23 16:37 ` [PULL 00/15] target-hexagon queue, hexagon docker Peter Maydell
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

From: Taylor Simpson <ltaylorsimpson@gmail.com>

Now that we are using QEMU decodetree.py, remove the old decoder

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20240115221443.365287-4-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
---
 target/hexagon/decode.c             | 344 ------------------------
 target/hexagon/dectree.py           | 403 ----------------------------
 target/hexagon/gen_dectree_import.c |  49 ----
 target/hexagon/meson.build          |  12 -
 target/hexagon/opcodes.c            |  29 --
 target/hexagon/opcodes.h            |   2 -
 6 files changed, 839 deletions(-)
 delete mode 100755 target/hexagon/dectree.py

diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 160b23a895..a40210ca1e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -88,175 +88,6 @@ static int shift_left(DisasContext *ctx, int x, int n, int immno)
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
-typedef struct {
-    const struct DectreeTable *table_link;
-    const struct DectreeTable *table_link_b;
-    Opcode opcode;
-    enum {
-        DECTREE_ENTRY_INVALID,
-        DECTREE_TABLE_LINK,
-        DECTREE_SUBINSNS,
-        DECTREE_EXTSPACE,
-        DECTREE_TERMINAL
-    } type;
-} DectreeEntry;
-
-typedef struct DectreeTable {
-    unsigned int (*lookup_function)(int startbit, int width, uint32_t opcode);
-    unsigned int size;
-    unsigned int startbit;
-    unsigned int width;
-    const DectreeEntry table[];
-} DectreeTable;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-    static const DectreeTable dectree_table_##TAG;
-#define TABLE_LINK(TABLE)                     /* NOTHING */
-#define TERMINAL(TAG, ENC)                    /* NOTHING */
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)    /* NOTHING */
-#define EXTSPACE(TAG, ENC)                    /* NOTHING */
-#define INVALID()                             /* NOTHING */
-#define DECODE_END_TABLE(...)                 /* NOTHING */
-#define DECODE_MATCH_INFO(...)                /* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...)         /* NOTHING */
-#define DECODE_OPINFO(...)                    /* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_SEPARATOR_BITS
-
-#define DECODE_SEPARATOR_BITS(START, WIDTH) NULL, START, WIDTH
-#define DECODE_NEW_TABLE_HELPER(TAG, SIZE, FN, START, WIDTH) \
-    static const DectreeTable dectree_table_##TAG = { \
-        .size = SIZE, \
-        .lookup_function = FN, \
-        .startbit = START, \
-        .width = WIDTH, \
-        .table = {
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-    DECODE_NEW_TABLE_HELPER(TAG, SIZE, WHATNOT)
-
-#define TABLE_LINK(TABLE) \
-    { .type = DECTREE_TABLE_LINK, .table_link = &dectree_table_##TABLE },
-#define TERMINAL(TAG, ENC) \
-    { .type = DECTREE_TERMINAL, .opcode = TAG  },
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) \
-    { \
-        .type = DECTREE_SUBINSNS, \
-        .table_link = &dectree_table_DECODE_SUBINSN_##CLASSA, \
-        .table_link_b = &dectree_table_DECODE_SUBINSN_##CLASSB \
-    },
-#define EXTSPACE(TAG, ENC) { .type = DECTREE_EXTSPACE },
-#define INVALID() { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-
-#define DECODE_END_TABLE(...) } };
-
-#define DECODE_MATCH_INFO(...)                /* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...)         /* NOTHING */
-#define DECODE_OPINFO(...)                    /* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_NEW_TABLE_HELPER
-#undef DECODE_SEPARATOR_BITS
-
-static const DectreeTable dectree_table_DECODE_EXT_EXT_noext = {
-    .size = 1, .lookup_function = NULL, .startbit = 0, .width = 0,
-    .table = {
-        { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-    }
-};
-
-static const DectreeTable *ext_trees[XX_LAST_EXT_IDX];
-
-static void decode_ext_init(void)
-{
-    int i;
-    for (i = EXT_IDX_noext; i < EXT_IDX_noext_AFTER; i++) {
-        ext_trees[i] = &dectree_table_DECODE_EXT_EXT_noext;
-    }
-    for (i = EXT_IDX_mmvec; i < EXT_IDX_mmvec_AFTER; i++) {
-        ext_trees[i] = &dectree_table_DECODE_EXT_EXT_mmvec;
-    }
-}
-
-typedef struct {
-    uint32_t mask;
-    uint32_t match;
-} DecodeITableEntry;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)  /* NOTHING */
-#define TABLE_LINK(TABLE)                     /* NOTHING */
-#define TERMINAL(TAG, ENC)                    /* NOTHING */
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)    /* NOTHING */
-#define EXTSPACE(TAG, ENC)                    /* NOTHING */
-#define INVALID()                             /* NOTHING */
-#define DECODE_END_TABLE(...)                 /* NOTHING */
-#define DECODE_OPINFO(...)                    /* NOTHING */
-
-#define DECODE_MATCH_INFO_NORMAL(TAG, MASK, MATCH) \
-    [TAG] = { \
-        .mask = MASK, \
-        .match = MATCH, \
-    },
-
-#define DECODE_MATCH_INFO_NULL(TAG, MASK, MATCH) \
-    [TAG] = { .match = ~0 },
-
-#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
-#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
-
-static const DecodeITableEntry decode_itable[XX_LAST_OPCODE] = {
-#include "dectree_generated.h.inc"
-};
-
-#undef DECODE_MATCH_INFO
-#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NULL(__VA_ARGS__)
-
-#undef DECODE_LEGACY_MATCH_INFO
-#define DECODE_LEGACY_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
-
-static const DecodeITableEntry decode_legacy_itable[XX_LAST_OPCODE] = {
-#include "dectree_generated.h.inc"
-};
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_SEPARATOR_BITS
-
-void decode_init(void)
-{
-    decode_ext_init();
-}
-
 void decode_send_insn_to(Packet *packet, int start, int newloc)
 {
     Insn tmpinsn;
@@ -587,7 +418,6 @@ apply_extender(Packet *pkt, int i, uint32_t extender)
     uint32_t base_immed;
 
     immed_num = pkt->insn[i].which_extended;
-    g_assert(immed_num == opcode_which_immediate_is_extended(pkt->insn[i].opcode));
     base_immed = pkt->insn[i].immed[immed_num];
 
     pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
@@ -630,174 +460,6 @@ static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot)
     }
 }
 
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)     /* NOTHING */
-#define TABLE_LINK(TABLE)                        /* NOTHING */
-#define TERMINAL(TAG, ENC)                       /* NOTHING */
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)       /* NOTHING */
-#define EXTSPACE(TAG, ENC)                       /* NOTHING */
-#define INVALID()                                /* NOTHING */
-#define DECODE_END_TABLE(...)                    /* NOTHING */
-#define DECODE_MATCH_INFO(...)                   /* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...)            /* NOTHING */
-
-#define DECODE_REG(REGNO, WIDTH, STARTBIT) \
-    insn->regno[REGNO] = ((encoding >> STARTBIT) & ((1 << WIDTH) - 1));
-
-#define DECODE_IMPL_REG(REGNO, VAL) \
-    insn->regno[REGNO] = VAL;
-
-#define DECODE_IMM(IMMNO, WIDTH, STARTBIT, VALSTART) \
-    insn->immed[IMMNO] |= (((encoding >> STARTBIT) & ((1 << WIDTH) - 1))) << \
-                          (VALSTART);
-
-#define DECODE_IMM_SXT(IMMNO, WIDTH) \
-    insn->immed[IMMNO] = ((((int32_t)insn->immed[IMMNO]) << (32 - WIDTH)) >> \
-                          (32 - WIDTH));
-
-#define DECODE_IMM_NEG(IMMNO, WIDTH) \
-    insn->immed[IMMNO] = -insn->immed[IMMNO];
-
-#define DECODE_IMM_SHIFT(IMMNO, SHAMT)                                 \
-    if ((!insn->extension_valid) || \
-        (insn->which_extended != IMMNO)) { \
-        insn->immed[IMMNO] <<= SHAMT; \
-    }
-
-#define DECODE_OPINFO(TAG, BEH) \
-    case TAG: \
-        { BEH  } \
-        break; \
-
-/*
- * Fill in the operands of the instruction
- * dectree_generated.h.inc has a DECODE_OPINFO entry for each opcode
- * For example,
- *     DECODE_OPINFO(A2_addi,
- *          DECODE_REG(0,5,0)
- *          DECODE_REG(1,5,16)
- *          DECODE_IMM(0,7,21,9)
- *          DECODE_IMM(0,9,5,0)
- *          DECODE_IMM_SXT(0,16)
- * with the macros defined above, we'll fill in a switch statement
- * where each case is an opcode tag.
- */
-static void
-decode_op(Insn *insn, Opcode tag, uint32_t encoding)
-{
-    insn->immed[0] = 0;
-    insn->immed[1] = 0;
-    insn->opcode = tag;
-    if (insn->extension_valid) {
-        insn->which_extended = opcode_which_immediate_is_extended(tag);
-    }
-
-    switch (tag) {
-#include "dectree_generated.h.inc"
-    default:
-        break;
-    }
-
-    insn->generate = opcode_genptr[tag];
-
-    insn->iclass = iclass_bits(encoding);
-}
-
-#undef DECODE_REG
-#undef DECODE_IMPL_REG
-#undef DECODE_IMM
-#undef DECODE_IMM_SHIFT
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_SEPARATOR_BITS
-
-static unsigned int
-decode_subinsn_tablewalk(Insn *insn, const DectreeTable *table,
-                         uint32_t encoding)
-{
-    unsigned int i;
-    Opcode opc;
-    if (table->lookup_function) {
-        i = table->lookup_function(table->startbit, table->width, encoding);
-    } else {
-        i = extract32(encoding, table->startbit, table->width);
-    }
-    if (table->table[i].type == DECTREE_TABLE_LINK) {
-        return decode_subinsn_tablewalk(insn, table->table[i].table_link,
-                                        encoding);
-    } else if (table->table[i].type == DECTREE_TERMINAL) {
-        opc = table->table[i].opcode;
-        if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
-            return 0;
-        }
-        decode_op(insn, opc, encoding);
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static unsigned int get_insn_a(uint32_t encoding)
-{
-    return extract32(encoding, 0, 13);
-}
-
-static unsigned int get_insn_b(uint32_t encoding)
-{
-    return extract32(encoding, 16, 13);
-}
-
-static unsigned int
-decode_insns_tablewalk(Insn *insn, const DectreeTable *table,
-                       uint32_t encoding)
-{
-    unsigned int i;
-    unsigned int a, b;
-    Opcode opc;
-    if (table->lookup_function) {
-        i = table->lookup_function(table->startbit, table->width, encoding);
-    } else {
-        i = extract32(encoding, table->startbit, table->width);
-    }
-    if (table->table[i].type == DECTREE_TABLE_LINK) {
-        return decode_insns_tablewalk(insn, table->table[i].table_link,
-                                      encoding);
-    } else if (table->table[i].type == DECTREE_SUBINSNS) {
-        a = get_insn_a(encoding);
-        b = get_insn_b(encoding);
-        b = decode_subinsn_tablewalk(insn, table->table[i].table_link_b, b);
-        a = decode_subinsn_tablewalk(insn + 1, table->table[i].table_link, a);
-        if ((a == 0) || (b == 0)) {
-            return 0;
-        }
-        return 2;
-    } else if (table->table[i].type == DECTREE_TERMINAL) {
-        opc = table->table[i].opcode;
-        if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
-            if ((encoding & decode_legacy_itable[opc].mask) !=
-                decode_legacy_itable[opc].match) {
-                return 0;
-            }
-        }
-        decode_op(insn, opc, encoding);
-        return 1;
-    } else if (table->table[i].type == DECTREE_EXTSPACE) {
-        /*
-         * For now, HVX will be the only coproc
-         */
-        return decode_insns_tablewalk(insn, ext_trees[EXT_IDX_mmvec], encoding);
-    } else {
-        return 0;
-    }
-}
-
 /*
  * Section 10.3 of the Hexagon V73 Programmer's Reference Manual
  *
@@ -858,7 +520,6 @@ static uint16_t get_slot1_subinsn(uint32_t encoding)
 static unsigned int
 decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
-    const DectreeTable *table;
     if (parse_bits(encoding) != 0) {
         if (decode_normal(ctx, encoding) ||
             decode_hvx(ctx, encoding)) {
@@ -866,8 +527,6 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
             insn->iclass = iclass_bits(encoding);
             return 1;
         }
-        /* Start with PP table - 32 bit instructions */
-        table = &dectree_table_DECODE_ROOT_32;
         g_assert_not_reached();
     } else {
         uint32_t iclass = get_duplex_iclass(encoding);
@@ -889,11 +548,8 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
                 return 2;
             }
         }
-        /* start with EE table - duplex instructions */
-        table = &dectree_table_DECODE_ROOT_EE;
         g_assert_not_reached();
     }
-    return decode_insns_tablewalk(insn, table, encoding);
 }
 
 static void decode_add_endloop_insn(Insn *insn, int loopnum)
diff --git a/target/hexagon/dectree.py b/target/hexagon/dectree.py
deleted file mode 100755
index 3b32948a04..0000000000
--- a/target/hexagon/dectree.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/env python3
-
-##
-##  Copyright(c) 2019-2023 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
-##  the Free Software Foundation; either version 2 of the License, or
-##  (at your option) any later version.
-##
-##  This program is distributed in the hope that it will be useful,
-##  but WITHOUT ANY WARRANTY; without even the implied warranty of
-##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-##  GNU General Public License for more details.
-##
-##  You should have received a copy of the GNU General Public License
-##  along with this program; if not, see <http://www.gnu.org/licenses/>.
-##
-
-import io
-import re
-
-import sys
-import iset
-
-encs = {
-    tag: "".join(reversed(iset.iset[tag]["enc"].replace(" ", "")))
-    for tag in iset.tags
-    if iset.iset[tag]["enc"] != "MISSING ENCODING"
-}
-
-enc_classes = set([iset.iset[tag]["enc_class"] for tag in encs.keys()])
-subinsn_enc_classes = set(
-    [enc_class for enc_class in enc_classes if enc_class.startswith("SUBINSN_")]
-)
-ext_enc_classes = set(
-    [
-        enc_class
-        for enc_class in enc_classes
-        if enc_class not in ("NORMAL", "16BIT") and not enc_class.startswith("SUBINSN_")
-    ]
-)
-
-try:
-    subinsn_groupings = iset.subinsn_groupings
-except AttributeError:
-    subinsn_groupings = {}
-
-for tag, subinsn_grouping in subinsn_groupings.items():
-    encs[tag] = "".join(reversed(subinsn_grouping["enc"].replace(" ", "")))
-
-dectree_normal = {"leaves": set()}
-dectree_16bit = {"leaves": set()}
-dectree_subinsn_groupings = {"leaves": set()}
-dectree_subinsns = {name: {"leaves": set()} for name in subinsn_enc_classes}
-dectree_extensions = {name: {"leaves": set()} for name in ext_enc_classes}
-
-for tag in encs.keys():
-    if tag in subinsn_groupings:
-        dectree_subinsn_groupings["leaves"].add(tag)
-        continue
-    enc_class = iset.iset[tag]["enc_class"]
-    if enc_class.startswith("SUBINSN_"):
-        if len(encs[tag]) != 32:
-            encs[tag] = encs[tag] + "0" * (32 - len(encs[tag]))
-        dectree_subinsns[enc_class]["leaves"].add(tag)
-    elif enc_class == "16BIT":
-        if len(encs[tag]) != 16:
-            raise Exception(
-                'Tag "{}" has enc_class "{}" and not an encoding '
-                + "width of 16 bits!".format(tag, enc_class)
-            )
-        dectree_16bit["leaves"].add(tag)
-    else:
-        if len(encs[tag]) != 32:
-            raise Exception(
-                'Tag "{}" has enc_class "{}" and not an encoding '
-                + "width of 32 bits!".format(tag, enc_class)
-            )
-        if enc_class == "NORMAL":
-            dectree_normal["leaves"].add(tag)
-        else:
-            dectree_extensions[enc_class]["leaves"].add(tag)
-
-faketags = set()
-for tag, enc in iset.enc_ext_spaces.items():
-    faketags.add(tag)
-    encs[tag] = "".join(reversed(enc.replace(" ", "")))
-    dectree_normal["leaves"].add(tag)
-
-faketags |= set(subinsn_groupings.keys())
-
-
-def every_bit_counts(bitset):
-    for i in range(1, len(next(iter(bitset)))):
-        if len(set([bits[:i] + bits[i + 1 :] for bits in bitset])) == len(bitset):
-            return False
-    return True
-
-
-def auto_separate(node):
-    tags = node["leaves"]
-    if len(tags) <= 1:
-        return
-    enc_width = len(encs[next(iter(tags))])
-    opcode_bit_for_all = [
-        all([encs[tag][i] in "01" for tag in tags]) for i in range(enc_width)
-    ]
-    opcode_bit_is_0_for_all = [
-        opcode_bit_for_all[i] and all([encs[tag][i] == "0" for tag in tags])
-        for i in range(enc_width)
-    ]
-    opcode_bit_is_1_for_all = [
-        opcode_bit_for_all[i] and all([encs[tag][i] == "1" for tag in tags])
-        for i in range(enc_width)
-    ]
-    differentiator_opcode_bit = [
-        opcode_bit_for_all[i]
-        and not (opcode_bit_is_0_for_all[i] or opcode_bit_is_1_for_all[i])
-        for i in range(enc_width)
-    ]
-    best_width = 0
-    for width in range(4, 0, -1):
-        for lsb in range(enc_width - width, -1, -1):
-            bitset = set([encs[tag][lsb : lsb + width] for tag in tags])
-            if all(differentiator_opcode_bit[lsb : lsb + width]) and (
-                len(bitset) == len(tags) or every_bit_counts(bitset)
-            ):
-                best_width = width
-                best_lsb = lsb
-                caught_all_tags = len(bitset) == len(tags)
-                break
-        if best_width != 0:
-            break
-    if best_width == 0:
-        raise Exception(
-            "Could not find a way to differentiate the encodings "
-            + "of the following tags:\n{}".format("\n".join(tags))
-        )
-    if caught_all_tags:
-        for width in range(1, best_width):
-            for lsb in range(enc_width - width, -1, -1):
-                bitset = set([encs[tag][lsb : lsb + width] for tag in tags])
-                if all(differentiator_opcode_bit[lsb : lsb + width]) and len(
-                    bitset
-                ) == len(tags):
-                    best_width = width
-                    best_lsb = lsb
-                    break
-            else:
-                continue
-            break
-    node["separator_lsb"] = best_lsb
-    node["separator_width"] = best_width
-    node["children"] = []
-    for value in range(2**best_width):
-        child = {}
-        bits = "".join(reversed("{:0{}b}".format(value, best_width)))
-        child["leaves"] = set(
-            [tag for tag in tags if encs[tag][best_lsb : best_lsb + best_width] == bits]
-        )
-        node["children"].append(child)
-    for child in node["children"]:
-        auto_separate(child)
-
-
-auto_separate(dectree_normal)
-auto_separate(dectree_16bit)
-if subinsn_groupings:
-    auto_separate(dectree_subinsn_groupings)
-for dectree_subinsn in dectree_subinsns.values():
-    auto_separate(dectree_subinsn)
-for dectree_ext in dectree_extensions.values():
-    auto_separate(dectree_ext)
-
-for tag in faketags:
-    del encs[tag]
-
-
-def table_name(parents, node):
-    path = parents + [node]
-    root = path[0]
-    tag = next(iter(node["leaves"]))
-    if tag in subinsn_groupings:
-        enc_width = len(subinsn_groupings[tag]["enc"].replace(" ", ""))
-    else:
-        tag = next(iter(node["leaves"] - faketags))
-        enc_width = len(encs[tag])
-    determining_bits = ["_"] * enc_width
-    for parent, child in zip(path[:-1], path[1:]):
-        lsb = parent["separator_lsb"]
-        width = parent["separator_width"]
-        value = parent["children"].index(child)
-        determining_bits[lsb : lsb + width] = list(
-            reversed("{:0{}b}".format(value, width))
-        )
-    if tag in subinsn_groupings:
-        name = "DECODE_ROOT_EE"
-    else:
-        enc_class = iset.iset[tag]["enc_class"]
-        if enc_class in ext_enc_classes:
-            name = "DECODE_EXT_{}".format(enc_class)
-        elif enc_class in subinsn_enc_classes:
-            name = "DECODE_SUBINSN_{}".format(enc_class)
-        else:
-            name = "DECODE_ROOT_{}".format(enc_width)
-    if node != root:
-        name += "_" + "".join(reversed(determining_bits))
-    return name
-
-
-def print_node(f, node, parents):
-    if len(node["leaves"]) <= 1:
-        return
-    name = table_name(parents, node)
-    lsb = node["separator_lsb"]
-    width = node["separator_width"]
-    print(
-        "DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format(
-            name, 2**width, lsb, width
-        ),
-        file=f,
-    )
-    for child in node["children"]:
-        if len(child["leaves"]) == 0:
-            print("INVALID()", file=f)
-        elif len(child["leaves"]) == 1:
-            (tag,) = child["leaves"]
-            if tag in subinsn_groupings:
-                class_a = subinsn_groupings[tag]["class_a"]
-                class_b = subinsn_groupings[tag]["class_b"]
-                enc = subinsn_groupings[tag]["enc"].replace(" ", "")
-                if "RESERVED" in tag:
-                    print("INVALID()", file=f)
-                else:
-                    print(
-                        'SUBINSNS({},{},{},"{}")'.format(tag, class_a, class_b, enc),
-                        file=f,
-                    )
-            elif tag in iset.enc_ext_spaces:
-                enc = iset.enc_ext_spaces[tag].replace(" ", "")
-                print('EXTSPACE({},"{}")'.format(tag, enc), file=f)
-            else:
-                enc = "".join(reversed(encs[tag]))
-                print('TERMINAL({},"{}")'.format(tag, enc), file=f)
-        else:
-            print("TABLE_LINK({})".format(table_name(parents + [node], child)), file=f)
-    print(
-        "DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format(
-            name, 2**width, lsb, width
-        ),
-        file=f,
-    )
-    print(file=f)
-    parents.append(node)
-    for child in node["children"]:
-        print_node(f, child, parents)
-    parents.pop()
-
-
-def print_tree(f, tree):
-    print_node(f, tree, [])
-
-
-def print_match_info(f):
-    for tag in sorted(encs.keys(), key=iset.tags.index):
-        enc = "".join(reversed(encs[tag]))
-        mask = int(re.sub(r"[^1]", r"0", enc.replace("0", "1")), 2)
-        match = int(re.sub(r"[^01]", r"0", enc), 2)
-        suffix = ""
-        print(
-            "DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)".format(suffix, tag, mask, match),
-            file=f,
-        )
-
-
-regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
-immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
-
-
-def ordered_unique(l):
-    return sorted(set(l), key=l.index)
-
-
-implicit_registers = {"SP": 29, "FP": 30, "LR": 31}
-
-num_registers = {"R": 32, "V": 32}
-
-
-def print_op_info(f):
-    for tag in sorted(encs.keys(), key=iset.tags.index):
-        enc = encs[tag]
-        print(file=f)
-        print("DECODE_OPINFO({},".format(tag), file=f)
-        regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
-        imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
-        regno = 0
-        for reg in regs:
-            reg_type = reg[0]
-            reg_letter = reg[1][0]
-            reg_num_choices = int(reg[3].rstrip("S"))
-            reg_mapping = reg[0] + "".join(["_" for letter in reg[1]]) + reg[3]
-            reg_enc_fields = re.findall(reg_letter + "+", enc)
-            if len(reg_enc_fields) == 0:
-                raise Exception('Tag "{}" missing register field!'.format(tag))
-            if len(reg_enc_fields) > 1:
-                raise Exception('Tag "{}" has split register field!'.format(tag))
-            reg_enc_field = reg_enc_fields[0]
-            if 2 ** len(reg_enc_field) != reg_num_choices:
-                raise Exception(
-                    'Tag "{}" has incorrect register field width!'.format(tag)
-                )
-            print(
-                "        DECODE_REG({},{},{})".format(
-                    regno, len(reg_enc_field), enc.index(reg_enc_field)
-                ),
-                file=f,
-            )
-            if reg_type in num_registers and reg_num_choices != num_registers[reg_type]:
-                print(
-                    "        DECODE_MAPPED_REG({},{})".format(regno, reg_mapping),
-                    file=f,
-                )
-            regno += 1
-
-        def implicit_register_key(reg):
-            return implicit_registers[reg]
-
-        for reg in sorted(
-            set(
-                [
-                    r
-                    for r in (
-                        iset.iset[tag]["rregs"].split(",")
-                        + iset.iset[tag]["wregs"].split(",")
-                    )
-                    if r in implicit_registers
-                ]
-            ),
-            key=implicit_register_key,
-        ):
-            print(
-                "        DECODE_IMPL_REG({},{})".format(regno, implicit_registers[reg]),
-                file=f,
-            )
-            regno += 1
-        if imms and imms[0][0].isupper():
-            imms = reversed(imms)
-        for imm in imms:
-            if imm[0].isupper():
-                immno = 1
-            else:
-                immno = 0
-            imm_type = imm[0]
-            imm_width = int(imm[1])
-            imm_shift = imm[2]
-            if imm_shift:
-                imm_shift = int(imm_shift)
-            else:
-                imm_shift = 0
-            if imm_type.islower():
-                imm_letter = "i"
-            else:
-                imm_letter = "I"
-            remainder = imm_width
-            for m in reversed(list(re.finditer(imm_letter + "+", enc))):
-                remainder -= m.end() - m.start()
-                print(
-                    "        DECODE_IMM({},{},{},{})".format(
-                        immno, m.end() - m.start(), m.start(), remainder
-                    ),
-                    file=f,
-                )
-            if remainder != 0:
-                if imm[2]:
-                    imm[2] = ":" + imm[2]
-                raise Exception(
-                    'Tag "{}" has an incorrect number of '
-                    + 'encoding bits for immediate "{}"'.format(tag, "".join(imm))
-                )
-            if imm_type.lower() in "sr":
-                print("        DECODE_IMM_SXT({},{})".format(immno, imm_width), file=f)
-            if imm_type.lower() == "n":
-                print("        DECODE_IMM_NEG({},{})".format(immno, imm_width), file=f)
-            if imm_shift:
-                print(
-                    "        DECODE_IMM_SHIFT({},{})".format(immno, imm_shift), file=f
-                )
-        print(")", file=f)
-
-
-if __name__ == "__main__":
-    with open(sys.argv[1], "w") as f:
-        print_tree(f, dectree_normal)
-        print_tree(f, dectree_16bit)
-        if subinsn_groupings:
-            print_tree(f, dectree_subinsn_groupings)
-        for name, dectree_subinsn in sorted(dectree_subinsns.items()):
-            print_tree(f, dectree_subinsn)
-        for name, dectree_ext in sorted(dectree_extensions.items()):
-            print_tree(f, dectree_ext)
-        print_match_info(f)
-        print_op_info(f)
diff --git a/target/hexagon/gen_dectree_import.c b/target/hexagon/gen_dectree_import.c
index ee354677fd..87f20c14f1 100644
--- a/target/hexagon/gen_dectree_import.c
+++ b/target/hexagon/gen_dectree_import.c
@@ -56,24 +56,6 @@ const char * const opcode_syntax[XX_LAST_OPCODE] = {
 #undef EXTINSN
 };
 
-const char * const opcode_rregs[] = {
-#define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS,
-#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2)  /* nothing */
-#include "op_regs_generated.h.inc"
-    NULL
-#undef REGINFO
-#undef IMMINFO
-};
-
-const char * const opcode_wregs[] = {
-#define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS,
-#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2)  /* nothing */
-#include "op_regs_generated.h.inc"
-    NULL
-#undef REGINFO
-#undef IMMINFO
-};
-
 const OpcodeEncoding opcode_encodings[] = {
 #define DEF_ENC32(TAG, ENCSTR) \
     [TAG] = { .encoding = ENCSTR },
@@ -130,8 +112,6 @@ static void gen_iset_table(FILE *out)
         fprintf(out, "\t\'%s\' : {\n", opcode_names[i]);
         fprintf(out, "\t\t\'tag\' : \'%s\',\n", opcode_names[i]);
         fprintf(out, "\t\t\'syntax\' : \'%s\',\n", opcode_syntax[i]);
-        fprintf(out, "\t\t\'rregs\' : \'%s\',\n", opcode_rregs[i]);
-        fprintf(out, "\t\t\'wregs\' : \'%s\',\n", opcode_wregs[i]);
         fprintf(out, "\t\t\'enc\' : \'%s\',\n", get_opcode_enc(i));
         fprintf(out, "\t\t\'enc_class\' : \'%s\',\n", get_opcode_enc_class(i));
         fprintf(out, "\t},\n");
@@ -150,33 +130,6 @@ static void gen_tags_list(FILE *out)
     fprintf(out, "];\n\n");
 }
 
-static void gen_enc_ext_spaces_table(FILE *out)
-{
-    fprintf(out, "enc_ext_spaces = {\n");
-#define DEF_EXT_SPACE(SPACEID, ENCSTR) \
-    fprintf(out, "\t\'%s\' : \'%s\',\n", #SPACEID, ENCSTR);
-#include "imported/encode.def"
-#undef DEF_EXT_SPACE
-    fprintf(out, "};\n\n");
-}
-
-static void gen_subinsn_groupings_table(FILE *out)
-{
-    fprintf(out, "subinsn_groupings = {\n");
-#define DEF_PACKED32(TAG, TYPEA, TYPEB, ENCSTR) \
-    do { \
-        fprintf(out, "\t\'%s\' : {\n", #TAG); \
-        fprintf(out, "\t\t\'name\' : \'%s\',\n", #TAG); \
-        fprintf(out, "\t\t\'class_a\' : \'%s\',\n", #TYPEA); \
-        fprintf(out, "\t\t\'class_b\' : \'%s\',\n", #TYPEB); \
-        fprintf(out, "\t\t\'enc\' : \'%s\',\n", ENCSTR); \
-        fprintf(out, "\t},\n"); \
-    } while (0);
-#include "imported/encode.def"
-#undef DEF_PACKED32
-    fprintf(out, "};\n\n");
-}
-
 int main(int argc, char *argv[])
 {
     FILE *outfile;
@@ -193,8 +146,6 @@ int main(int argc, char *argv[])
 
     gen_iset_table(outfile);
     gen_tags_list(outfile);
-    gen_enc_ext_spaces_table(outfile);
-    gen_subinsn_groupings_table(outfile);
 
     fclose(outfile);
     return 0;
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index 1bd1ebcba1..fb480afc03 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -122,18 +122,6 @@ hexagon_ss.add(iset_py)
 
 #
 # Step 4
-# We use the dectree.py script to generate the decode tree header file
-#
-dectree_generated = custom_target(
-    'dectree_generated.h.inc',
-    output: 'dectree_generated.h.inc',
-    depends: [iset_py],
-    env: {'PYTHONPATH': meson.current_build_dir()},
-    command: [python, files('dectree.py'), '@OUTPUT@'],
-)
-hexagon_ss.add(dectree_generated)
-
-#
 # Generate the input to the QEMU decodetree.py script
 #
 normal_decode_generated = custom_target(
diff --git a/target/hexagon/opcodes.c b/target/hexagon/opcodes.c
index 35d790cdd5..1f7f3def38 100644
--- a/target/hexagon/opcodes.c
+++ b/target/hexagon/opcodes.c
@@ -111,33 +111,4 @@ void opcode_init(void)
 #include "op_attribs_generated.h.inc"
 #undef OP_ATTRIB
 #undef ATTRIBS
-
-    decode_init();
-}
-
-
-#define NEEDLE "IMMEXT("
-
-int opcode_which_immediate_is_extended(Opcode opcode)
-{
-    const char *p;
-
-    g_assert(opcode < XX_LAST_OPCODE);
-    g_assert(GET_ATTRIB(opcode, A_EXTENDABLE));
-
-    p = opcode_short_semantics[opcode];
-    p = strstr(p, NEEDLE);
-    g_assert(p);
-    p += strlen(NEEDLE);
-    while (isspace(*p)) {
-        p++;
-    }
-    /* lower is always imm 0, upper always imm 1. */
-    if (islower(*p)) {
-        return 0;
-    } else if (isupper(*p)) {
-        return 1;
-    } else {
-        g_assert_not_reached();
-    }
 }
diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index 6e90e00fe2..fa7e321950 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -53,6 +53,4 @@ extern const OpcodeEncoding opcode_encodings[XX_LAST_OPCODE];
 
 void opcode_init(void);
 
-int opcode_which_immediate_is_extended(Opcode opcode);
-
 #endif
-- 
2.25.1


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

* [PULL 15/15] target/hexagon: reduce scope of def_regnum, remove dead assignment
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (13 preceding siblings ...)
  2024-01-22  6:35 ` [PULL 14/15] Hexagon (target/hexagon) Remove old dectree.py Brian Cain
@ 2024-01-22  6:35 ` Brian Cain
  2024-01-23 16:37 ` [PULL 00/15] target-hexagon queue, hexagon docker Peter Maydell
  15 siblings, 0 replies; 17+ messages in thread
From: Brian Cain @ 2024-01-22  6:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, armbru, richard.henderson, philmd, peter.maydell,
	quic_mathbern, stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

This is intended to address a coverity finding: CID 1527408.

Signed-off-by: Brian Cain <bcain@quicinc.com>
Reviewed-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Message-Id: <20240114234453.4114587-1-bcain@quicinc.com>
---
 target/hexagon/mmvec/decode_ext_mmvec.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c b/target/hexagon/mmvec/decode_ext_mmvec.c
index 174eb3b78b..202d84c7c0 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -33,7 +33,6 @@ check_new_value(Packet *pkt)
     const char *dststr = NULL;
     uint16_t def_opcode;
     char letter;
-    int def_regnum;
 
     for (i = 1; i < pkt->num_insns; i++) {
         uint16_t use_opcode = pkt->insn[i].opcode;
@@ -78,7 +77,6 @@ check_new_value(Packet *pkt)
                 }
             }
             if ((dststr == NULL)  && GET_ATTRIB(def_opcode, A_CVI_GATHER)) {
-                def_regnum = 0;
                 pkt->insn[i].regno[use_regidx] = def_oreg;
                 pkt->insn[i].new_value_producer_slot = pkt->insn[def_idx].slot;
             } else {
@@ -86,7 +84,7 @@ check_new_value(Packet *pkt)
                     /* still not there, we have a bad packet */
                     g_assert_not_reached();
                 }
-                def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
+                int def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
                 /* Now patch up the consumer with the register number */
                 pkt->insn[i].regno[use_regidx] = def_regnum ^ def_oreg;
                 /* special case for (Vx,Vy) */
-- 
2.25.1


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

* Re: [PULL 00/15] target-hexagon queue, hexagon docker
  2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
                   ` (14 preceding siblings ...)
  2024-01-22  6:35 ` [PULL 15/15] target/hexagon: reduce scope of def_regnum, remove dead assignment Brian Cain
@ 2024-01-23 16:37 ` Peter Maydell
  15 siblings, 0 replies; 17+ messages in thread
From: Peter Maydell @ 2024-01-23 16:37 UTC (permalink / raw)
  To: Brian Cain
  Cc: qemu-devel, armbru, richard.henderson, philmd, quic_mathbern,
	stefanha, ale, anjo, quic_mliebel, ltaylorsimpson

On Mon, 22 Jan 2024 at 06:35, Brian Cain <bcain@quicinc.com> wrote:
>
> The following changes since commit 3f2a357b95845ea0bf7463eff6661e43b97d1afc:
>
>   Merge tag 'hw-cpus-20240119' of https://github.com/philmd/qemu into staging (2024-01-19 11:39:38 +0000)
>
> are available in the Git repository at:
>
>   https://github.com/quic/qemu tags/pull-hex-20240121
>
> for you to fetch changes up to bbe4209c8b4300d722f47791f9151e1a69cb0135:
>
>   target/hexagon: reduce scope of def_regnum, remove dead assignment (2024-01-21 22:02:48 -0800)
>
> ----------------------------------------------------------------
> Coverity fix, cross toolchain update, switch to decodetree
>
> ----------------------------------------------------------------
> Brian Cain (2):
>       tests/docker: Hexagon toolchain update
>       target/hexagon: reduce scope of def_regnum, remove dead assignment
>
> Taylor Simpson (13):
>       Hexagon (target/hexagon) Fix shadow variable when idef-parser is off
>       Hexagon (target/hexagon) Clean up handling of modifier registers
>       Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs
>       Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
>       Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs
>       Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs
>       Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
>       Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs
>       Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
>       Hexagon (target/hexagon) Remove dead functions from hex_common.py
>       Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)
>       Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)
>       Hexagon (target/hexagon) Remove old dectree.py


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/9.0
for any user-visible changes.

-- PMM


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

end of thread, other threads:[~2024-01-23 16:37 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-22  6:34 [PULL 00/15] target-hexagon queue, hexagon docker Brian Cain
2024-01-22  6:34 ` [PULL 01/15] tests/docker: Hexagon toolchain update Brian Cain
2024-01-22  6:34 ` [PULL 02/15] Hexagon (target/hexagon) Fix shadow variable when idef-parser is off Brian Cain
2024-01-22  6:34 ` [PULL 03/15] Hexagon (target/hexagon) Clean up handling of modifier registers Brian Cain
2024-01-22  6:34 ` [PULL 04/15] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Brian Cain
2024-01-22  6:34 ` [PULL 05/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Brian Cain
2024-01-22  6:34 ` [PULL 06/15] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Brian Cain
2024-01-22  6:34 ` [PULL 07/15] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Brian Cain
2024-01-22  6:34 ` [PULL 08/15] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Brian Cain
2024-01-22  6:34 ` [PULL 09/15] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Brian Cain
2024-01-22  6:34 ` [PULL 10/15] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Brian Cain
2024-01-22  6:34 ` [PULL 11/15] Hexagon (target/hexagon) Remove dead functions from hex_common.py Brian Cain
2024-01-22  6:34 ` [PULL 12/15] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions) Brian Cain
2024-01-22  6:34 ` [PULL 13/15] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions) Brian Cain
2024-01-22  6:35 ` [PULL 14/15] Hexagon (target/hexagon) Remove old dectree.py Brian Cain
2024-01-22  6:35 ` [PULL 15/15] target/hexagon: reduce scope of def_regnum, remove dead assignment Brian Cain
2024-01-23 16:37 ` [PULL 00/15] target-hexagon queue, hexagon docker Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).