All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented
@ 2023-12-05  1:52 Taylor Simpson
  2023-12-05  1:52 ` [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers Taylor Simpson
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

See commit message in second patch

Taylor Simpson (9):
  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

 target/hexagon/gen_tcg.h                    |   9 +-
 target/hexagon/macros.h                     |   3 +-
 target/hexagon/attribs_def.h.inc            |   1 -
 target/hexagon/idef-parser/parser-helpers.c |   8 +-
 target/hexagon/gen_analyze_funcs.py         | 163 +---
 target/hexagon/gen_helper_funcs.py          | 400 +++-------
 target/hexagon/gen_helper_protos.py         | 184 ++---
 target/hexagon/gen_idef_parser_funcs.py     |  20 +-
 target/hexagon/gen_op_regs.py               |   6 +-
 target/hexagon/gen_tcg_funcs.py             | 578 ++------------
 target/hexagon/hex_common.py                | 818 ++++++++++++++++++--
 11 files changed, 963 insertions(+), 1227 deletions(-)

-- 
2.34.1



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

* [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
@ 2023-12-05  1:52 ` Taylor Simpson
  2023-12-05  3:04   ` Brian Cain
  2023-12-05  1:52 ` [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Taylor Simpson
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

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.

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/gen_tcg.h                    |  9 ++++-----
 target/hexagon/macros.h                     |  3 +--
 target/hexagon/idef-parser/parser-helpers.c |  8 +++-----
 target/hexagon/gen_tcg_funcs.py             | 13 +++++++++----
 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/macros.h b/target/hexagon/macros.h
index 9a51b5709b..939f22e76b 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)
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/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:
-- 
2.34.1



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

* [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
  2023-12-05  1:52 ` [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers Taylor Simpson
@ 2023-12-05  1:52 ` Taylor Simpson
  2023-12-05  3:01   ` Brian Cain
  2023-12-05  1:52 ` [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Taylor Simpson
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

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>
---
 target/hexagon/gen_tcg_funcs.py | 583 +++-----------------------------
 target/hexagon/hex_common.py    | 542 +++++++++++++++++++++++++++++
 2 files changed, 589 insertions(+), 536 deletions(-)

diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 02d93bc5ce..8c2bc03c10 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,56 @@ 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
+        declared = []
         ## 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]:
+            reg = hex_common.get_register(tag, regtype, regid)
+            if reg.is_written() and not reg.is_hvx_reg():
+                declared.append(reg.reg_tcg())
+        declared.append("tcg_env")
+
+        ## For predicated instructions, we pass in the destination register
+        if hex_common.is_predicated(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
+                reg = hex_common.get_register(tag, regtype, regid)
+                if reg.is_writeonly() and not reg.is_hvx_reg():
+                    declared.append(reg.reg_tcg())
+        ## Pass the HVX destination registers
         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
+            reg = hex_common.get_register(tag, regtype, regid)
+            if reg.is_written() and reg.is_hvx_reg():
+                declared.append(reg.reg_tcg())
+        ## Pass the source registers
         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
+            reg = hex_common.get_register(tag, regtype, regid)
+            if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
+                declared.append(reg.reg_tcg())
+        ## Pass the immediates
         for immlett, bits, immshift in imms:
-            gen_helper_call_imm(f, immlett)
+            declared.append(f"tcg_constant_tl({hex_common.imm_name(immlett)})")
 
+        ## Other stuff the helper might need
         if hex_common.need_pkt_has_multi_cof(tag):
-            f.write(", pkt_has_multi_cof")
+            declared.append("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)")
         if hex_common.need_pkt_need_commit(tag):
-            f.write(", pkt_need_commit")
+            declared.append("tcg_constant_tl(ctx->need_commit)")
         if hex_common.need_PC(tag):
-            f.write(", PC")
-        if hex_common.helper_needs_next_PC(tag):
-            f.write(", next_PC")
+            declared.append("tcg_constant_tl(ctx->pkt->pc)")
+        if hex_common.need_next_PC(tag):
+            declared.append("tcg_constant_tl(ctx->next_PC)")
         if hex_common.need_slot(tag):
-            f.write(", slotval")
+            declared.append("gen_slotval(ctx)")
         if hex_common.need_part1(tag):
-            f.write(", part1")
-        f.write(");\n")
+            declared.append("tcg_constant_tl(insn->part1)")
+
+        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 +147,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..2f8963db59 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,538 @@ 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 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())
+
+#
+# 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
+
+class Single(Scalar):
+    pass
+
+class Pair(Scalar):
+    pass
+
+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"
+
+#
+# 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}"]
-- 
2.34.1



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

* [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
  2023-12-05  1:52 ` [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers Taylor Simpson
  2023-12-05  1:52 ` [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Taylor Simpson
@ 2023-12-05  1:52 ` Taylor Simpson
  2023-12-05  3:46   ` Brian Cain
  2023-12-05  1:52 ` [PATCH 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Taylor Simpson
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/gen_helper_protos.py | 184 ++++++++--------------------
 target/hexagon/hex_common.py        |  15 +--
 2 files changed, 55 insertions(+), 144 deletions(-)

diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 131043795a..9277199e1d 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,62 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
     regs = tagregs[tag]
     imms = tagimms[tag]
 
-    numresults = 0
+    ## If there is a scalar result, it is the return type
+    return_type = ""
     numscalarresults = 0
-    numscalarreadwrite = 0
     for regtype, regid in regs:
-        if hex_common.is_written(regid):
-            numresults += 1
-            if hex_common.is_scalar_reg(regtype):
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_scalar_reg():
+                return_type = reg.helper_proto_type()
                 numscalarresults += 1
-        if hex_common.is_readwrite(regid):
-            if hex_common.is_scalar_reg(regtype):
-                numscalarreadwrite += 1
+    if numscalarresults == 0:
+        return_type = "void"
 
     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}")
-
-        ## 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
+        raise Exception("numscalarresults > 1")
 
-        ## Put the env between the outputs and inputs
-        f.write(", env")
-        i += 1
+    declared = []
+    declared.append(return_type)
 
-        # 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)
+    ## Put the env between the outputs and inputs
+    declared.append("env")
+
+    ## For predicated instructions, we pass in the destination register
+    if hex_common.is_predicated(tag):
         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")
+            reg = hex_common.get_register(tag, regtype, regid)
+            if reg.is_writeonly() and not reg.is_hvx_reg():
+                declared.append(reg.helper_proto_type())
+    ## Pass the HVX destination registers
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_hvx_reg():
+            declared.append(reg.helper_proto_type())
+    ## Pass the source registers
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
+            declared.append(reg.helper_proto_type())
+    ## Pass the immediates
+    for immlett, bits, immshift in imms:
+        declared.append("s32")
+
+    ## Other stuff the helper might need
+    if hex_common.need_pkt_has_multi_cof(tag):
+        declared.append("i32")
+    if hex_common.need_pkt_need_commit(tag):
+        declared.append("i32")
+    if hex_common.need_PC(tag):
+        declared.append("i32")
+    if hex_common.need_next_PC(tag):
+        declared.append("i32")
+    if hex_common.need_slot(tag):
+        declared.append("i32")
+    if hex_common.need_part1(tag):
+        declared.append("i32")
+
+    arguments = ", ".join(declared)
+    f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
 
 
 def main():
@@ -195,6 +108,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 2f8963db59..4149c2ce91 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()
@@ -404,10 +397,12 @@ def is_hvx_reg(self):
         return False
 
 class Single(Scalar):
-    pass
+    def helper_proto_type(self):
+        return "s32"
 
 class Pair(Scalar):
-    pass
+    def helper_proto_type(self):
+        return "s64"
 
 class Hvx:
     def is_scalar_reg(self):
@@ -416,6 +411,8 @@ def is_hvx_reg(self):
         return True
     def hvx_off(self):
         return f"{self.reg_tcg()}_off"
+    def helper_proto_type(self):
+        return "ptr"
 
 #
 # Every register is either Dest or OldSource or NewSource or ReadWrite
-- 
2.34.1



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

* [PATCH 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (2 preceding siblings ...)
  2023-12-05  1:52 ` [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Taylor Simpson
@ 2023-12-05  1:52 ` Taylor Simpson
  2023-12-05  1:52 ` [PATCH 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Taylor Simpson
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/gen_helper_funcs.py | 400 +++++++----------------------
 target/hexagon/hex_common.py       |  58 ++++-
 2 files changed, 151 insertions(+), 307 deletions(-)

diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index ce21d3b688..60b7e95e8c 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,111 @@ def gen_helper_function(f, tag, tagregs, tagimms):
     regs = tagregs[tag]
     imms = tagimms[tag]
 
-    numresults = 0
+    ## If there is a scalar result, it is the return type
+    return_type = ""
     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
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_scalar_reg():
+            return_type = reg.helper_arg_type()
+            numscalarresults += 1
+    if numscalarresults == 0:
+        return_type = "void"
 
     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
+        raise Exception("numscalarresults > 1")
 
-        if numscalarresults == 0:
-            f.write("void")
-        f.write(f" HELPER({tag})(CPUHexagonState *env")
-
-        ## Arguments include the vector destination operands
-        i = 1
-        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
+    declared = []
+    declared.append("CPUHexagonState *env")
+    ## For predicated instructions, we pass in the destination register
+    if hex_common.is_predicated(tag):
         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():
+                declared.append(f"{reg.helper_arg_type()} {reg.helper_arg()}")
+    ## Pass the HVX destination operands
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_written() and reg.is_hvx_reg():
+            declared.append(f"{reg.helper_arg_type()} {reg.helper_arg()}")
+    ## Pass the source registers
+    for regtype, regid in regs:
+        reg = hex_common.get_register(tag, regtype, regid)
+        if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
+            declared.append(f"{reg.helper_arg_type()} {reg.helper_arg()}")
+    ## Pass the immediates
+    for immlett, bits, immshift in imms:
+        declared.append(f"int32_t {hex_common.imm_name(immlett)}")
+
+    ## Other sutff the helper might need
+    if hex_common.need_pkt_has_multi_cof(tag):
+        declared.append("uint32_t pkt_has_multi_cof")
+    if (hex_common.need_pkt_need_commit(tag)):
+        declared.append("uint32_t pkt_need_commit")
+    if hex_common.need_PC(tag):
+        declared.append("target_ulong PC")
+    if hex_common.need_next_PC(tag):
+        declared.append("target_ulong next_PC")
+    if hex_common.need_slot(tag):
+        declared.append("uint32_t slotval")
+    if hex_common.need_part1(tag):
+        declared.append("uint32_t part1")
+
+    arguments = ", ".join(declared)
+    f.write(f"{return_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_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")
+            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()} = 0;
+                """))
 
-        if "A_FPOP" in hex_common.attribdict[tag]:
-            f.write("    arch_fpop_end(env);\n")
+    ## 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()};
+            """))
 
-        ## 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
+    f.write("}\n\n")
+    ## End of the helper definition
 
 
 def main():
@@ -370,6 +163,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 4149c2ce91..384f377621 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]
 
@@ -395,14 +391,20 @@ def is_scalar_reg(self):
         return True
     def is_hvx_reg(self):
         return False
+    def helper_arg(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):
@@ -413,6 +415,10 @@ 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(self):
+        return f"{self.reg_tcg()}_void"
 
 #
 # Every register is either Dest or OldSource or NewSource or ReadWrite
@@ -659,6 +665,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()}) */
+        """))
 
 class VRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -671,6 +681,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()}) */
+        """))
 
 class VRegNewSource(Register, Hvx, NewSource):
     def decl_tcg(self, f, tag, regno):
@@ -680,6 +694,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()}) */
+        """))
 
 class VRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -698,6 +716,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()}) */
+        """))
 
 class VRegTmp(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -718,6 +740,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()}) */
+        """))
 
 class VRegPairDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -733,6 +759,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()}) */
+        """))
 
 class VRegPairSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -752,6 +782,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()}) */
+        """))
 
 class VRegPairReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -776,6 +810,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()}) */
+        """))
 
 class QRegDest(Register, Hvx, Dest):
     def decl_tcg(self, f, tag, regno):
@@ -791,6 +829,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()}) */
+        """))
 
 class QRegSource(Register, Hvx, OldSource):
     def decl_tcg(self, f, tag, regno):
@@ -804,6 +846,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()}) */
+        """))
 
 class QRegReadWrite(Register, Hvx, ReadWrite):
     def decl_tcg(self, f, tag, regno):
@@ -822,6 +868,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()}) */
+        """))
 
 def init_registers():
     regs = {
-- 
2.34.1



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

* [PATCH 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (3 preceding siblings ...)
  2023-12-05  1:52 ` [PATCH 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Taylor Simpson
@ 2023-12-05  1:52 ` Taylor Simpson
  2023-12-05  1:53 ` [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Taylor Simpson
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.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.34.1



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

* [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (4 preceding siblings ...)
  2023-12-05  1:52 ` [PATCH 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Taylor Simpson
@ 2023-12-05  1:53 ` Taylor Simpson
  2023-12-05  3:02   ` Brian Cain
  2023-12-05  1:53 ` [PATCH 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Taylor Simpson
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.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.34.1



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

* [PATCH 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (5 preceding siblings ...)
  2023-12-05  1:53 ` [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Taylor Simpson
@ 2023-12-05  1:53 ` Taylor Simpson
  2023-12-05  1:53 ` [PATCH 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Taylor Simpson
  2023-12-05  1:53 ` [PATCH 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py Taylor Simpson
  8 siblings, 0 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

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>
---
 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 384f377621..e64d114cf3 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -475,6 +475,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):
@@ -482,12 +488,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):
@@ -506,6 +522,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):
@@ -521,6 +543,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):
@@ -533,6 +561,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):
@@ -549,6 +582,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):
@@ -560,6 +598,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):
@@ -567,12 +610,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):
@@ -585,6 +638,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):
@@ -597,6 +655,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):
@@ -607,6 +671,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):
@@ -622,6 +691,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):
@@ -638,6 +713,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):
@@ -650,6 +731,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):
@@ -669,6 +755,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg()}) */
         """))
+    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):
@@ -685,6 +778,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg()}) */
         """))
+    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):
@@ -698,6 +796,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg()}) */
         """))
+    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):
@@ -720,6 +823,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg()}) */
         """))
+    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):
@@ -744,6 +854,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg()}) */
         """))
+    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):
@@ -763,6 +880,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg()}) */
         """))
+    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):
@@ -786,6 +910,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg()}) */
         """))
+    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):
@@ -814,6 +943,13 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg()}) */
         """))
+    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):
@@ -833,6 +969,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg()}) */
         """))
+    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):
@@ -850,6 +991,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg()}) */
         """))
+    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):
@@ -872,6 +1018,11 @@ def helper_hvx_desc(self, f):
         f.write(code_fmt(f"""\
             /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg()}) */
         """))
+    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.34.1



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

* [PATCH 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (6 preceding siblings ...)
  2023-12-05  1:53 ` [PATCH 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Taylor Simpson
@ 2023-12-05  1:53 ` Taylor Simpson
  2023-12-05  1:53 ` [PATCH 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py Taylor Simpson
  8 siblings, 0 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

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>
---
 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 e64d114cf3..59fed78ab0 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.34.1



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

* [PATCH 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py
  2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
                   ` (7 preceding siblings ...)
  2023-12-05  1:53 ` [PATCH 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Taylor Simpson
@ 2023-12-05  1:53 ` Taylor Simpson
  8 siblings, 0 replies; 16+ messages in thread
From: Taylor Simpson @ 2023-12-05  1:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: bcain, quic_mathbern, sidneym, quic_mliebel, richard.henderson,
	philmd, ale, anjo, ltaylorsimpson

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

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.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 59fed78ab0..90d61a1b16 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.34.1



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

* RE: [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs
  2023-12-05  1:52 ` [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Taylor Simpson
@ 2023-12-05  3:01   ` Brian Cain
  0 siblings, 0 replies; 16+ messages in thread
From: Brian Cain @ 2023-12-05  3:01 UTC (permalink / raw)
  To: Taylor Simpson, qemu-devel
  Cc: Matheus Bernardino (QUIC), Sid Manning, Marco Liebel (QUIC),
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: Taylor Simpson <ltaylorsimpson@gmail.com>
> Sent: Monday, December 4, 2023 7:53 PM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>; Marco
> Liebel (QUIC) <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng; ltaylorsimpson@gmail.com
> Subject: [PATCH 2/9] Hexagon (target/hexagon) Make generators object
> oriented - gen_tcg_funcs
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary of
> any links or attachments, and do not enable macros.
> 
> 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>
> ---
>  target/hexagon/gen_tcg_funcs.py | 583 +++-----------------------------
>  target/hexagon/hex_common.py    | 542 +++++++++++++++++++++++++++++
>  2 files changed, 589 insertions(+), 536 deletions(-)
> 
> diff --git a/target/hexagon/gen_tcg_funcs.py
> b/target/hexagon/gen_tcg_funcs.py
> index 02d93bc5ce..8c2bc03c10 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,56 @@ 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
> +        declared = []
>          ## 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]:
> +            reg = hex_common.get_register(tag, regtype, regid)
> +            if reg.is_written() and not reg.is_hvx_reg():
> +                declared.append(reg.reg_tcg())
> +        declared.append("tcg_env")
> +
> +        ## For predicated instructions, we pass in the destination register
> +        if hex_common.is_predicated(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
> +                reg = hex_common.get_register(tag, regtype, regid)
> +                if reg.is_writeonly() and not reg.is_hvx_reg():
> +                    declared.append(reg.reg_tcg())
> +        ## Pass the HVX destination registers
>          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
> +            reg = hex_common.get_register(tag, regtype, regid)
> +            if reg.is_written() and reg.is_hvx_reg():
> +                declared.append(reg.reg_tcg())
> +        ## Pass the source registers
>          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
> +            reg = hex_common.get_register(tag, regtype, regid)
> +            if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
> +                declared.append(reg.reg_tcg())
> +        ## Pass the immediates
>          for immlett, bits, immshift in imms:
> -            gen_helper_call_imm(f, immlett)
> +
> declared.append(f"tcg_constant_tl({hex_common.imm_name(immlett)})")
> 
> +        ## Other stuff the helper might need
>          if hex_common.need_pkt_has_multi_cof(tag):
> -            f.write(", pkt_has_multi_cof")
> +            declared.append("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)")
>          if hex_common.need_pkt_need_commit(tag):
> -            f.write(", pkt_need_commit")
> +            declared.append("tcg_constant_tl(ctx->need_commit)")
>          if hex_common.need_PC(tag):
> -            f.write(", PC")
> -        if hex_common.helper_needs_next_PC(tag):
> -            f.write(", next_PC")
> +            declared.append("tcg_constant_tl(ctx->pkt->pc)")
> +        if hex_common.need_next_PC(tag):
> +            declared.append("tcg_constant_tl(ctx->next_PC)")
>          if hex_common.need_slot(tag):
> -            f.write(", slotval")
> +            declared.append("gen_slotval(ctx)")
>          if hex_common.need_part1(tag):
> -            f.write(", part1")
> -        f.write(");\n")
> +            declared.append("tcg_constant_tl(insn->part1)")
> +
> +        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 +147,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..2f8963db59 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,538 @@ 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 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())
> +
> +#
> +# 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
> +
> +class Single(Scalar):
> +    pass
> +
> +class Pair(Scalar):
> +    pass
> +
> +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"
> +
> +#
> +# 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}"]
> --
> 2.34.1

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

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

* RE: [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
  2023-12-05  1:53 ` [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Taylor Simpson
@ 2023-12-05  3:02   ` Brian Cain
  0 siblings, 0 replies; 16+ messages in thread
From: Brian Cain @ 2023-12-05  3:02 UTC (permalink / raw)
  To: Taylor Simpson, qemu-devel
  Cc: Matheus Bernardino (QUIC), Sid Manning, Marco Liebel (QUIC),
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: Taylor Simpson <ltaylorsimpson@gmail.com>
> Sent: Monday, December 4, 2023 7:53 PM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>; Marco
> Liebel (QUIC) <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng; ltaylorsimpson@gmail.com
> Subject: [PATCH 6/9] Hexagon (target/hexagon) Make generators object
> oriented - gen_op_regs
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary of
> any links or attachments, and do not enable macros.
> 
> Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.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.34.1

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

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

* RE: [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers
  2023-12-05  1:52 ` [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers Taylor Simpson
@ 2023-12-05  3:04   ` Brian Cain
  0 siblings, 0 replies; 16+ messages in thread
From: Brian Cain @ 2023-12-05  3:04 UTC (permalink / raw)
  To: Taylor Simpson, qemu-devel
  Cc: Matheus Bernardino (QUIC), Sid Manning, Marco Liebel (QUIC),
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: Taylor Simpson <ltaylorsimpson@gmail.com>
> Sent: Monday, December 4, 2023 7:53 PM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>; Marco
> Liebel (QUIC) <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng; ltaylorsimpson@gmail.com
> Subject: [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier
> registers
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary of
> any links or attachments, and do not enable macros.
> 
> 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.
> 
> Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> ---
>  target/hexagon/gen_tcg.h                    |  9 ++++-----
>  target/hexagon/macros.h                     |  3 +--
>  target/hexagon/idef-parser/parser-helpers.c |  8 +++-----
>  target/hexagon/gen_tcg_funcs.py             | 13 +++++++++----
>  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/macros.h b/target/hexagon/macros.h
> index 9a51b5709b..939f22e76b 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)
> 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/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:
> --
> 2.34.1

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

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

* RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
  2023-12-05  1:52 ` [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Taylor Simpson
@ 2023-12-05  3:46   ` Brian Cain
  2023-12-05 17:08     ` ltaylorsimpson
  0 siblings, 1 reply; 16+ messages in thread
From: Brian Cain @ 2023-12-05  3:46 UTC (permalink / raw)
  To: Taylor Simpson, qemu-devel
  Cc: Matheus Bernardino (QUIC), Sid Manning, Marco Liebel (QUIC),
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: Taylor Simpson <ltaylorsimpson@gmail.com>
> Sent: Monday, December 4, 2023 7:53 PM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>; Marco
> Liebel (QUIC) <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng; ltaylorsimpson@gmail.com
> Subject: [PATCH 3/9] Hexagon (target/hexagon) Make generators object
> oriented - gen_helper_protos
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary of
> any links or attachments, and do not enable macros.
> 
> Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> ---
>  target/hexagon/gen_helper_protos.py | 184 ++++++++--------------------
>  target/hexagon/hex_common.py        |  15 +--
>  2 files changed, 55 insertions(+), 144 deletions(-)
> 
> diff --git a/target/hexagon/gen_helper_protos.py
> b/target/hexagon/gen_helper_protos.py
> index 131043795a..9277199e1d 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,62 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
>      regs = tagregs[tag]
>      imms = tagimms[tag]
> 
> -    numresults = 0
> +    ## If there is a scalar result, it is the return type
> +    return_type = ""

Should we use `return_type = None` here?

>      numscalarresults = 0
> -    numscalarreadwrite = 0
>      for regtype, regid in regs:
> -        if hex_common.is_written(regid):
> -            numresults += 1
> -            if hex_common.is_scalar_reg(regtype):
> +        reg = hex_common.get_register(tag, regtype, regid)
> +        if reg.is_written() and reg.is_scalar_reg():
> +                return_type = reg.helper_proto_type()
>                  numscalarresults += 1
> -        if hex_common.is_readwrite(regid):
> -            if hex_common.is_scalar_reg(regtype):
> -                numscalarreadwrite += 1
> +    if numscalarresults == 0:
> +        return_type = "void"

Should we use `return_type = None` here?

> 
>      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}")
> -
> -        ## 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
> +        raise Exception("numscalarresults > 1")
> 
> -        ## Put the env between the outputs and inputs
> -        f.write(", env")
> -        i += 1
> +    declared = []
> +    declared.append(return_type)
> 
> -        # 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)
> +    ## Put the env between the outputs and inputs
> +    declared.append("env")
> +
> +    ## For predicated instructions, we pass in the destination register
> +    if hex_common.is_predicated(tag):
>          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")
> +            reg = hex_common.get_register(tag, regtype, regid)
> +            if reg.is_writeonly() and not reg.is_hvx_reg():
> +                declared.append(reg.helper_proto_type())
> +    ## Pass the HVX destination registers
> +    for regtype, regid in regs:
> +        reg = hex_common.get_register(tag, regtype, regid)
> +        if reg.is_written() and reg.is_hvx_reg():
> +            declared.append(reg.helper_proto_type())
> +    ## Pass the source registers
> +    for regtype, regid in regs:
> +        reg = hex_common.get_register(tag, regtype, regid)
> +        if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
> +            declared.append(reg.helper_proto_type())
> +    ## Pass the immediates
> +    for immlett, bits, immshift in imms:
> +        declared.append("s32")
> +
> +    ## Other stuff the helper might need
> +    if hex_common.need_pkt_has_multi_cof(tag):
> +        declared.append("i32")
> +    if hex_common.need_pkt_need_commit(tag):
> +        declared.append("i32")
> +    if hex_common.need_PC(tag):
> +        declared.append("i32")
> +    if hex_common.need_next_PC(tag):
> +        declared.append("i32")
> +    if hex_common.need_slot(tag):
> +        declared.append("i32")
> +    if hex_common.need_part1(tag):
> +        declared.append("i32")

What do you think of this instead?  The delta below is on top of this patch.

--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -73,18 +73,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         declared.append("s32")
 
     ## Other stuff the helper might need
-    if hex_common.need_pkt_has_multi_cof(tag):
-        declared.append("i32")
-    if hex_common.need_pkt_need_commit(tag):
-        declared.append("i32")
-    if hex_common.need_PC(tag):
-        declared.append("i32")
-    if hex_common.need_next_PC(tag):
-        declared.append("i32")
-    if hex_common.need_slot(tag):
-        declared.append("i32")
-    if hex_common.need_part1(tag):
-        declared.append("i32")
+    for stuff in hex_common.other_stuff:
+        if stuff(tag):
+            declared.append('i32')
 
     arguments = ", ".join(declared)
     f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 8c2bc03c10..cb02d91886 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -109,18 +109,9 @@ def gen_tcg_func(f, tag, regs, imms):
             declared.append(f"tcg_constant_tl({hex_common.imm_name(immlett)})")
 
         ## Other stuff the helper might need
-        if hex_common.need_pkt_has_multi_cof(tag):
-            declared.append("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)")
-        if hex_common.need_pkt_need_commit(tag):
-            declared.append("tcg_constant_tl(ctx->need_commit)")
-        if hex_common.need_PC(tag):
-            declared.append("tcg_constant_tl(ctx->pkt->pc)")
-        if hex_common.need_next_PC(tag):
-            declared.append("tcg_constant_tl(ctx->next_PC)")
-        if hex_common.need_slot(tag):
-            declared.append("gen_slotval(ctx)")
-        if hex_common.need_part1(tag):
-            declared.append("tcg_constant_tl(insn->part1)")
+        for stuff, text in hex_common.other_stuff:
+            if stuff(tag):
+                declared.append(text)
 
         arguments = ", ".join(declared)
         f.write(f"    gen_helper_{tag}({arguments});\n")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 90d61a1b16..954532921d 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1028,3 +1028,13 @@ def get_register(tag, regtype, regid):
         return registers[f"{regtype}{regid}"]
     else:
         return new_registers[f"{regtype}{regid}"]
+
+
+other_stuff = {
+    need_pkt_has_multi_cof: "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
+    need_pkt_need_commit: "tcg_constant_tl(ctx->need_commit)",
+    need_PC: "tcg_constant_tl(ctx->pkt->pc)",
+    need_next_PC: "tcg_constant_tl(ctx->next_PC)",
+    need_slot: "gen_slotval(ctx)",
+    need_part1: "tcg_constant_tl(insn->part1)",
+}



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

* RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
  2023-12-05  3:46   ` Brian Cain
@ 2023-12-05 17:08     ` ltaylorsimpson
  2023-12-05 22:59       ` ltaylorsimpson
  0 siblings, 1 reply; 16+ messages in thread
From: ltaylorsimpson @ 2023-12-05 17:08 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: 'Matheus Bernardino (QUIC)', 'Sid Manning',
	'Marco Liebel (QUIC)',
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: Brian Cain <bcain@quicinc.com>
> Sent: Monday, December 4, 2023 9:46 PM
> To: Taylor Simpson <ltaylorsimpson@gmail.com>; qemu-devel@nongnu.org
> Cc: Matheus Bernardino (QUIC) <quic_mathbern@quicinc.com>; Sid
> Manning <sidneym@quicinc.com>; Marco Liebel (QUIC)
> <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng
> Subject: RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators object
> oriented - gen_helper_protos
> 
> 
> 
> > -----Original Message-----
> > From: Taylor Simpson <ltaylorsimpson@gmail.com>
> > Sent: Monday, December 4, 2023 7:53 PM
> > To: qemu-devel@nongnu.org
> > Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> > <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>;
> Marco
> > Liebel (QUIC) <quic_mliebel@quicinc.com>;
> > richard.henderson@linaro.org; philmd@linaro.org; ale@rev.ng;
> > anjo@rev.ng; ltaylorsimpson@gmail.com
> > Subject: [PATCH 3/9] Hexagon (target/hexagon) Make generators object
> > oriented - gen_helper_protos
> >
> > Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> > ---
> >  target/hexagon/gen_helper_protos.py | 184 ++++++++--------------------
> >  target/hexagon/hex_common.py        |  15 +--
> >  2 files changed, 55 insertions(+), 144 deletions(-)
> >
> > diff --git a/target/hexagon/gen_helper_protos.py
> > b/target/hexagon/gen_helper_protos.py
> > index 131043795a..9277199e1d 100755
> > --- a/target/hexagon/gen_helper_protos.py
> > +++ b/target/hexagon/gen_helper_protos.py
> >  ##
> >  ## Generate the DEF_HELPER prototype for an instruction
> >  ##     For A2_add: Rd32=add(Rs32,Rt32)
> > @@ -65,116 +32,62 @@ def gen_helper_prototype(f, tag, tagregs,
> tagimms):
> >      regs = tagregs[tag]
> >      imms = tagimms[tag]
> >
> > -    numresults = 0
> > +    ## If there is a scalar result, it is the return type
> > +    return_type = ""
> 
> Should we use `return_type = None` here?
> 
> >      numscalarresults = 0
> > -    numscalarreadwrite = 0
> >      for regtype, regid in regs:
> > -        if hex_common.is_written(regid):
> > -            numresults += 1
> > -            if hex_common.is_scalar_reg(regtype):
> > +        reg = hex_common.get_register(tag, regtype, regid)
> > +        if reg.is_written() and reg.is_scalar_reg():
> > +                return_type = reg.helper_proto_type()
> >                  numscalarresults += 1
> > -        if hex_common.is_readwrite(regid):
> > -            if hex_common.is_scalar_reg(regtype):
> > -                numscalarreadwrite += 1
> > +    if numscalarresults == 0:
> > +        return_type = "void"
> 
> Should we use `return_type = None` here?

I don't see a point of setting it to None.  By the time it gets to the use below, it will definitely have a value.  We could initialize it to void instead of "" and skip this check.


> > +
> > +    ## Other stuff the helper might need
> > +    if hex_common.need_pkt_has_multi_cof(tag):
> > +        declared.append("i32")
> > +    if hex_common.need_pkt_need_commit(tag):
> > +        declared.append("i32")
> > +    if hex_common.need_PC(tag):
> > +        declared.append("i32")
> > +    if hex_common.need_next_PC(tag):
> > +        declared.append("i32")
> > +    if hex_common.need_slot(tag):
> > +        declared.append("i32")
> > +    if hex_common.need_part1(tag):
> > +        declared.append("i32")
> 
> What do you think of this instead?  The delta below is on top of this patch.
> 
> --- a/target/hexagon/gen_helper_protos.py
> +++ b/target/hexagon/gen_helper_protos.py
> @@ -73,18 +73,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
>          declared.append("s32")
> 
>      ## Other stuff the helper might need
> -    if hex_common.need_pkt_has_multi_cof(tag):
> -        declared.append("i32")
> -    if hex_common.need_pkt_need_commit(tag):
> -        declared.append("i32")
> -    if hex_common.need_PC(tag):
> -        declared.append("i32")
> -    if hex_common.need_next_PC(tag):
> -        declared.append("i32")
> -    if hex_common.need_slot(tag):
> -        declared.append("i32")
> -    if hex_common.need_part1(tag):
> -        declared.append("i32")
> +    for stuff in hex_common.other_stuff:
> +        if stuff(tag):
> +            declared.append('i32')
> 
>      arguments = ", ".join(declared)
>      f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n") diff --git
> a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
> index 8c2bc03c10..cb02d91886 100755
> --- a/target/hexagon/gen_tcg_funcs.py
> +++ b/target/hexagon/gen_tcg_funcs.py
> @@ -109,18 +109,9 @@ def gen_tcg_func(f, tag, regs, imms):
> 
> declared.append(f"tcg_constant_tl({hex_common.imm_name(immlett)})")
> 
>          ## Other stuff the helper might need
> -        if hex_common.need_pkt_has_multi_cof(tag):
> -            declared.append("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)")
> -        if hex_common.need_pkt_need_commit(tag):
> -            declared.append("tcg_constant_tl(ctx->need_commit)")
> -        if hex_common.need_PC(tag):
> -            declared.append("tcg_constant_tl(ctx->pkt->pc)")
> -        if hex_common.need_next_PC(tag):
> -            declared.append("tcg_constant_tl(ctx->next_PC)")
> -        if hex_common.need_slot(tag):
> -            declared.append("gen_slotval(ctx)")
> -        if hex_common.need_part1(tag):
> -            declared.append("tcg_constant_tl(insn->part1)")
> +        for stuff, text in hex_common.other_stuff:
> +            if stuff(tag):
> +                declared.append(text)
> 
>          arguments = ", ".join(declared)
>          f.write(f"    gen_helper_{tag}({arguments});\n")
> diff --git a/target/hexagon/hex_common.py
> b/target/hexagon/hex_common.py index 90d61a1b16..954532921d 100755
> --- a/target/hexagon/hex_common.py
> +++ b/target/hexagon/hex_common.py
> @@ -1028,3 +1028,13 @@ def get_register(tag, regtype, regid):
>          return registers[f"{regtype}{regid}"]
>      else:
>          return new_registers[f"{regtype}{regid}"]
> +
> +
> +other_stuff = {
> +    need_pkt_has_multi_cof: "tcg_constant_tl(ctx->pkt-
> >pkt_has_multi_cof)",
> +    need_pkt_need_commit: "tcg_constant_tl(ctx->need_commit)",
> +    need_PC: "tcg_constant_tl(ctx->pkt->pc)",
> +    need_next_PC: "tcg_constant_tl(ctx->next_PC)",
> +    need_slot: "gen_slotval(ctx)",
> +    need_part1: "tcg_constant_tl(insn->part1)", }

Great idea to centralize these in hex_common.  There are three parts though.  There's the actual helper argument in gen_hepler_funcs.py.  I'll think about how best to cover the 3 parts.  Let me know if you have ideas as well.

Thanks,
Taylor





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

* RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos
  2023-12-05 17:08     ` ltaylorsimpson
@ 2023-12-05 22:59       ` ltaylorsimpson
  0 siblings, 0 replies; 16+ messages in thread
From: ltaylorsimpson @ 2023-12-05 22:59 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: 'Matheus Bernardino (QUIC)', 'Sid Manning',
	'Marco Liebel (QUIC)',
	richard.henderson, philmd, ale, anjo



> -----Original Message-----
> From: ltaylorsimpson@gmail.com <ltaylorsimpson@gmail.com>
> Sent: Tuesday, December 5, 2023 11:08 AM
> To: 'Brian Cain' <bcain@quicinc.com>; qemu-devel@nongnu.org
> Cc: 'Matheus Bernardino (QUIC)' <quic_mathbern@quicinc.com>; 'Sid
> Manning' <sidneym@quicinc.com>; 'Marco Liebel (QUIC)'
> <quic_mliebel@quicinc.com>; richard.henderson@linaro.org;
> philmd@linaro.org; ale@rev.ng; anjo@rev.ng
> Subject: RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators object
> oriented - gen_helper_protos
> 
> 
> 
> > -----Original Message-----
> > From: Brian Cain <bcain@quicinc.com>
> > Sent: Monday, December 4, 2023 9:46 PM
> > To: Taylor Simpson <ltaylorsimpson@gmail.com>; qemu-
> devel@nongnu.org
> > Cc: Matheus Bernardino (QUIC) <quic_mathbern@quicinc.com>; Sid
> Manning
> > <sidneym@quicinc.com>; Marco Liebel (QUIC)
> <quic_mliebel@quicinc.com>;
> > richard.henderson@linaro.org; philmd@linaro.org; ale@rev.ng;
> > anjo@rev.ng
> > Subject: RE: [PATCH 3/9] Hexagon (target/hexagon) Make generators
> > object oriented - gen_helper_protos
> >
> >
> >
> > > -----Original Message-----
> > > From: Taylor Simpson <ltaylorsimpson@gmail.com>
> > > Sent: Monday, December 4, 2023 7:53 PM
> > > To: qemu-devel@nongnu.org
> > > Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> > > <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>;
> > Marco
> > > Liebel (QUIC) <quic_mliebel@quicinc.com>;
> > > richard.henderson@linaro.org; philmd@linaro.org; ale@rev.ng;
> > > anjo@rev.ng; ltaylorsimpson@gmail.com
> > > Subject: [PATCH 3/9] Hexagon (target/hexagon) Make generators object
> > > oriented - gen_helper_protos
> > >
> > > Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> > > ---
> > >  target/hexagon/gen_helper_protos.py | 184 ++++++++--------------------
> > >  target/hexagon/hex_common.py        |  15 +--
> > >  2 files changed, 55 insertions(+), 144 deletions(-)
> > >
> > > diff --git a/target/hexagon/gen_helper_protos.py
> > > b/target/hexagon/gen_helper_protos.py
> > > index 131043795a..9277199e1d 100755
> > > --- a/target/hexagon/gen_helper_protos.py
> > > +++ b/target/hexagon/gen_helper_protos.py
> > >  ##
> > >  ## Generate the DEF_HELPER prototype for an instruction
> > >  ##     For A2_add: Rd32=add(Rs32,Rt32)
> > > @@ -65,116 +32,62 @@ def gen_helper_prototype(f, tag, tagregs,
> > tagimms):
> > >      regs = tagregs[tag]
> > >      imms = tagimms[tag]
> > >
> > > -    numresults = 0
> > > +    ## If there is a scalar result, it is the return type
> > > +    return_type = ""
> >
> > Should we use `return_type = None` here?
> >
> > >      numscalarresults = 0
> > > -    numscalarreadwrite = 0
> > >      for regtype, regid in regs:
> > > -        if hex_common.is_written(regid):
> > > -            numresults += 1
> > > -            if hex_common.is_scalar_reg(regtype):
> > > +        reg = hex_common.get_register(tag, regtype, regid)
> > > +        if reg.is_written() and reg.is_scalar_reg():
> > > +                return_type = reg.helper_proto_type()
> > >                  numscalarresults += 1
> > > -        if hex_common.is_readwrite(regid):
> > > -            if hex_common.is_scalar_reg(regtype):
> > > -                numscalarreadwrite += 1
> > > +    if numscalarresults == 0:
> > > +        return_type = "void"
> >
> > Should we use `return_type = None` here?
> 
> I don't see a point of setting it to None.  By the time it gets to the use below,
> it will definitely have a value.  We could initialize it to void instead of "" and
> skip this check.
> 
> 
> > > +
> > > +    ## Other stuff the helper might need
> > > +    if hex_common.need_pkt_has_multi_cof(tag):
> > > +        declared.append("i32")
> > > +    if hex_common.need_pkt_need_commit(tag):
> > > +        declared.append("i32")
> > > +    if hex_common.need_PC(tag):
> > > +        declared.append("i32")
> > > +    if hex_common.need_next_PC(tag):
> > > +        declared.append("i32")
> > > +    if hex_common.need_slot(tag):
> > > +        declared.append("i32")
> > > +    if hex_common.need_part1(tag):
> > > +        declared.append("i32")
> >
> > What do you think of this instead?  The delta below is on top of this patch.
> >
> > --- a/target/hexagon/gen_helper_protos.py
> > +++ b/target/hexagon/gen_helper_protos.py
> > @@ -73,18 +73,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
> >          declared.append("s32")
> >
> >      ## Other stuff the helper might need
> > -    if hex_common.need_pkt_has_multi_cof(tag):
> > -        declared.append("i32")
> > -    if hex_common.need_pkt_need_commit(tag):
> > -        declared.append("i32")
> > -    if hex_common.need_PC(tag):
> > -        declared.append("i32")
> > -    if hex_common.need_next_PC(tag):
> > -        declared.append("i32")
> > -    if hex_common.need_slot(tag):
> > -        declared.append("i32")
> > -    if hex_common.need_part1(tag):
> > -        declared.append("i32")
> > +    for stuff in hex_common.other_stuff:
> > +        if stuff(tag):
> > +            declared.append('i32')
> >
> >      arguments = ", ".join(declared)
> >      f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
> > diff --git a/target/hexagon/gen_tcg_funcs.py
> > b/target/hexagon/gen_tcg_funcs.py index 8c2bc03c10..cb02d91886 100755
> > --- a/target/hexagon/gen_tcg_funcs.py
> > +++ b/target/hexagon/gen_tcg_funcs.py
> > @@ -109,18 +109,9 @@ def gen_tcg_func(f, tag, regs, imms):
> >
> >
> declared.append(f"tcg_constant_tl({hex_common.imm_name(immlett)})")
> >
> >          ## Other stuff the helper might need
> > -        if hex_common.need_pkt_has_multi_cof(tag):
> > -            declared.append("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)")
> > -        if hex_common.need_pkt_need_commit(tag):
> > -            declared.append("tcg_constant_tl(ctx->need_commit)")
> > -        if hex_common.need_PC(tag):
> > -            declared.append("tcg_constant_tl(ctx->pkt->pc)")
> > -        if hex_common.need_next_PC(tag):
> > -            declared.append("tcg_constant_tl(ctx->next_PC)")
> > -        if hex_common.need_slot(tag):
> > -            declared.append("gen_slotval(ctx)")
> > -        if hex_common.need_part1(tag):
> > -            declared.append("tcg_constant_tl(insn->part1)")
> > +        for stuff, text in hex_common.other_stuff:
> > +            if stuff(tag):
> > +                declared.append(text)
> >
> >          arguments = ", ".join(declared)
> >          f.write(f"    gen_helper_{tag}({arguments});\n")
> > diff --git a/target/hexagon/hex_common.py
> > b/target/hexagon/hex_common.py index 90d61a1b16..954532921d 100755
> > --- a/target/hexagon/hex_common.py
> > +++ b/target/hexagon/hex_common.py
> > @@ -1028,3 +1028,13 @@ def get_register(tag, regtype, regid):
> >          return registers[f"{regtype}{regid}"]
> >      else:
> >          return new_registers[f"{regtype}{regid}"]
> > +
> > +
> > +other_stuff = {
> > +    need_pkt_has_multi_cof: "tcg_constant_tl(ctx->pkt-
> > >pkt_has_multi_cof)",
> > +    need_pkt_need_commit: "tcg_constant_tl(ctx->need_commit)",
> > +    need_PC: "tcg_constant_tl(ctx->pkt->pc)",
> > +    need_next_PC: "tcg_constant_tl(ctx->next_PC)",
> > +    need_slot: "gen_slotval(ctx)",
> > +    need_part1: "tcg_constant_tl(insn->part1)", }
> 
> Great idea to centralize these in hex_common.  There are three parts
> though.  There's the actual helper argument in gen_hepler_funcs.py.  I'll
> think about how best to cover the 3 parts.  Let me know if you have ideas as
> well.
> 
> Thanks,
> Taylor

How about this?

In hex_common.py
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

def extra_helper_args(tag):
    args = []
    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"
        ))
    ...
    return args

In gen_tcg_funcs.py
        for extra_arg in hex_common.extra_helper_args(tag):
            declared.append(extra_arg.call_arg)

In gen_helper_protos.py
    for extra_arg in hex_common.extra_helper_args(tag):
        declared.append(extra_arg.proto_arg)

In gen_helper_funcs.py
    for extra_arg in hex_common.extra_helper_args(tag):
        declared.append(extra_arg.func_arg)

A further refinement would be to have all the registers and immediates create a HelperArg.  Then, we could consolidate the logic to create the argument lists in hex_common.py.  For example, we pass the destination register as an input to the helper for predicated instructions, and the pointer to the destination for HVX.

Thanks,
Taylor




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

end of thread, other threads:[~2023-12-05 23:00 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-05  1:52 [PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented Taylor Simpson
2023-12-05  1:52 ` [PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers Taylor Simpson
2023-12-05  3:04   ` Brian Cain
2023-12-05  1:52 ` [PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs Taylor Simpson
2023-12-05  3:01   ` Brian Cain
2023-12-05  1:52 ` [PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos Taylor Simpson
2023-12-05  3:46   ` Brian Cain
2023-12-05 17:08     ` ltaylorsimpson
2023-12-05 22:59       ` ltaylorsimpson
2023-12-05  1:52 ` [PATCH 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs Taylor Simpson
2023-12-05  1:52 ` [PATCH 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs Taylor Simpson
2023-12-05  1:53 ` [PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs Taylor Simpson
2023-12-05  3:02   ` Brian Cain
2023-12-05  1:53 ` [PATCH 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs Taylor Simpson
2023-12-05  1:53 ` [PATCH 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute Taylor Simpson
2023-12-05  1:53 ` [PATCH 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py Taylor Simpson

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