Hexagon (target/hexagon) Mark registers as read during packet analysis
Have gen_analyze_funcs mark the registers that are read by the
instruction. We also mark the implicit reads using instruction
attributes.
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230427230012.3800327-11-tsimpson@quicinc.com>
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 69da977..21d457f 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -112,6 +112,10 @@
DEF_ATTRIB(IMPLICIT_WRITES_P2, "Writes Predicate 1", "", "UREG.P2")
DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3")
DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the PC register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_P0, "Reads the P0 register", "", "")
+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", "", "")
diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py
index c74443d..86aec5a 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -35,12 +35,14 @@
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" 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" 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")
@@ -48,7 +50,8 @@
print("Bad register parse: ", 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" 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")
@@ -57,15 +60,19 @@
elif regtype == "C":
if regid == "ss":
f.write(
- f"// const int {regN} = insn->regno[{regno}] " "+ HEX_REG_SA0;\n"
+ 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" 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")
@@ -73,7 +80,8 @@
print("Bad register parse: ", regtype, regid)
elif regtype == "M":
if regid == "u":
- f.write(f"// const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" ctx_log_reg_read(ctx, {regN});\n")
else:
print("Bad register parse: ", regtype, regid)
elif regtype == "V":
@@ -88,9 +96,11 @@
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" 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" 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")
@@ -101,7 +111,8 @@
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" const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" ctx_log_qreg_read(ctx, {regN});\n")
else:
print("Bad register parse: ", regtype, regid)
elif regtype == "G":
@@ -134,17 +145,20 @@
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" const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" ctx_log_reg_read(ctx, {regN});\n")
else:
print("Bad register parse: ", regtype, regid)
elif regtype == "P":
if regid in {"t", "u", "v"}:
- f.write(f"// const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" ctx_log_pred_read(ctx, {regN});\n")
else:
print("Bad register parse: ", regtype, regid)
elif regtype == "O":
if regid == "s":
- f.write(f"// const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" const int {regN} = insn->regno[{regno}];\n")
+ f.write(f" ctx_log_vreg_read(ctx, {regN});\n")
else:
print("Bad register parse: ", regtype, regid)
else:
@@ -174,8 +188,10 @@
## Insn *insn G_GNUC_UNUSED = ctx->insn;
## const int RdN = insn->regno[0];
## ctx_log_reg_write(ctx, RdN, false);
-## // const int RsN = insn->regno[1];
-## // const int RtN = insn->regno[2];
+## const int RsN = insn->regno[1];
+## ctx_log_reg_read(ctx, RsN);
+## const int RtN = insn->regno[2];
+## ctx_log_reg_read(ctx, RtN);
## }
##
def gen_analyze_func(f, tag, regs, imms):
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 40f28ca..232c6e2 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -97,6 +97,12 @@
add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE")
+ add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0')
+ add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0')
+ add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0')
+ add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
+ add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
+ add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
# Recurse down macros, find attributes from sub-macros
macroValues = list(macros.values())
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 0b021b3..e84bd34 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -336,6 +336,21 @@
mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
}
+static void mark_implicit_pred_read(DisasContext *ctx, int attrib, int pnum)
+{
+ if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
+ ctx_log_pred_read(ctx, pnum);
+ }
+}
+
+static void mark_implicit_pred_reads(DisasContext *ctx)
+{
+ mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P0, 0);
+ mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P1, 1);
+ mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 2);
+ mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 3);
+}
+
static void analyze_packet(DisasContext *ctx)
{
Packet *pkt = ctx->pkt;
@@ -348,6 +363,7 @@
}
mark_implicit_reg_writes(ctx);
mark_implicit_pred_writes(ctx);
+ mark_implicit_pred_reads(ctx);
}
}
@@ -361,9 +377,11 @@
ctx->next_PC = next_PC;
ctx->reg_log_idx = 0;
bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
+ bitmap_zero(ctx->regs_read, TOTAL_PER_THREAD_REGS);
bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
ctx->preg_log_idx = 0;
bitmap_zero(ctx->pregs_written, NUM_PREGS);
+ bitmap_zero(ctx->pregs_read, NUM_PREGS);
ctx->future_vregs_idx = 0;
ctx->tmp_vregs_idx = 0;
ctx->vreg_log_idx = 0;
@@ -372,6 +390,8 @@
bitmap_zero(ctx->vregs_select, NUM_VREGS);
bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
+ bitmap_zero(ctx->vregs_read, NUM_VREGS);
+ bitmap_zero(ctx->qregs_read, NUM_QREGS);
ctx->qreg_log_idx = 0;
for (i = 0; i < STORES_MAX; i++) {
ctx->store_width[i] = 0;
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 4b9f21c..f722288 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -38,10 +38,12 @@
int reg_log[REG_WRITES_MAX];
int reg_log_idx;
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
+ DECLARE_BITMAP(regs_read, TOTAL_PER_THREAD_REGS);
DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
int preg_log[PRED_WRITES_MAX];
int preg_log_idx;
DECLARE_BITMAP(pregs_written, NUM_PREGS);
+ DECLARE_BITMAP(pregs_read, NUM_PREGS);
uint8_t store_width[STORES_MAX];
bool s1_store_processed;
int future_vregs_idx;
@@ -55,8 +57,10 @@
DECLARE_BITMAP(vregs_select, NUM_VREGS);
DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
+ DECLARE_BITMAP(vregs_read, NUM_VREGS);
int qreg_log[NUM_QREGS];
int qreg_log_idx;
+ DECLARE_BITMAP(qregs_read, NUM_QREGS);
bool pre_commit;
TCGCond branch_cond;
target_ulong branch_dest;
@@ -73,6 +77,11 @@
}
}
+static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
+{
+ set_bit(pnum, ctx->pregs_read);
+}
+
static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
bool is_predicated)
{
@@ -99,6 +108,17 @@
ctx_log_reg_write(ctx, rnum + 1, is_predicated);
}
+static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
+{
+ set_bit(rnum, ctx->regs_read);
+}
+
+static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
+{
+ ctx_log_reg_read(ctx, rnum);
+ ctx_log_reg_read(ctx, rnum + 1);
+}
+
intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
int num, bool alloc_ok);
intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
@@ -139,6 +159,17 @@
ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated);
}
+static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum)
+{
+ set_bit(rnum, ctx->vregs_read);
+}
+
+static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum)
+{
+ ctx_log_vreg_read(ctx, rnum ^ 0);
+ ctx_log_vreg_read(ctx, rnum ^ 1);
+}
+
static inline void ctx_log_qreg_write(DisasContext *ctx,
int rnum)
{
@@ -146,6 +177,11 @@
ctx->qreg_log_idx++;
}
+static inline void ctx_log_qreg_read(DisasContext *ctx, int qnum)
+{
+ set_bit(qnum, ctx->qregs_read);
+}
+
extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
extern TCGv hex_pred[NUM_PREGS];
extern TCGv hex_this_PC;