HVX packets with Vx.tmp/Vx reg writes were incorrectly rejected.
Cc: Taylor Simpson <[email protected]>
Reviewed-by: Taylor Simpson <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
target/hexagon/translate.h | 20 ++++++++++++--------
target/hexagon/translate.c | 31 ++++++++++++++++++++-----------
target/hexagon/hex_common.py | 8 ++++++--
3 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index e17261761b2..696410d7c6f 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -81,6 +81,7 @@ typedef struct DisasContext {
int qreg_log_idx;
DECLARE_BITMAP(qregs_written, NUM_QREGS);
DECLARE_BITMAP(qregs_multi_write, NUM_QREGS);
+ DECLARE_BITMAP(qregs_uncond, NUM_QREGS);
DECLARE_BITMAP(insn_qregs_written, NUM_QREGS);
DECLARE_BITMAP(insn_qregs_read, NUM_QREGS);
bool pre_commit;
@@ -237,12 +238,13 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
ctx->has_hvx_overlap = true;
}
}
- if (!test_bit(rnum, ctx->vregs_written)) {
- set_bit(rnum, ctx->vregs_written);
- } else {
- set_bit(rnum, ctx->vregs_multi_write);
- }
+
if (type != EXT_TMP) {
+ if (!test_bit(rnum, ctx->vregs_written)) {
+ set_bit(rnum, ctx->vregs_written);
+ } else {
+ set_bit(rnum, ctx->vregs_multi_write);
+ }
if (!test_bit(rnum, ctx->vregs_updated)) {
ctx->vreg_log[ctx->vreg_log_idx] = rnum;
ctx->vreg_log_idx++;
@@ -263,8 +265,6 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
set_bit(rnum, ctx->vregs_updated_tmp);
if (is_predicated) {
set_bit(rnum, ctx->predicated_tmp_vregs);
- } else {
- set_bit(rnum, ctx->vregs_uncond);
}
}
}
@@ -317,7 +317,8 @@ static inline void ctx_log_vreg_read_pair(DisasContext
*ctx, int rnum,
}
static inline void ctx_log_qreg_write(DisasContext *ctx,
- int rnum, bool has_helper)
+ int rnum, bool predicated,
+ bool has_helper)
{
if (has_helper) {
set_bit(rnum, ctx->insn_qregs_written);
@@ -330,6 +331,9 @@ static inline void ctx_log_qreg_write(DisasContext *ctx,
} else {
set_bit(rnum, ctx->qregs_multi_write);
}
+ if (!predicated) {
+ set_bit(rnum, ctx->qregs_uncond);
+ }
ctx->qreg_log[ctx->qreg_log_idx] = rnum;
ctx->qreg_log_idx++;
}
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 827859e052c..5f1849c8926 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -609,6 +609,7 @@ static void clear_pkt_ctx(DisasContext *ctx)
bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
bitmap_zero(ctx->qregs_written, NUM_QREGS);
bitmap_zero(ctx->qregs_multi_write, NUM_QREGS);
+ bitmap_zero(ctx->qregs_uncond, NUM_QREGS);
ctx->qreg_log_idx = 0;
for (i = 0; i < STORES_MAX; i++) {
ctx->store_width[i] = 0;
@@ -626,7 +627,6 @@ static void clear_pkt_ctx(DisasContext *ctx)
static bool pkt_has_write_conflict(DisasContext *ctx)
{
DECLARE_BITMAP(gpr_conflict, TOTAL_PER_THREAD_REGS);
- DECLARE_BITMAP(vregs_conflict, NUM_VREGS);
bitmap_and(gpr_conflict, ctx->gpr_multi_write, ctx->gpr_uncond,
TOTAL_PER_THREAD_REGS);
@@ -634,16 +634,6 @@ static bool pkt_has_write_conflict(DisasContext *ctx)
return true;
}
- bitmap_and(vregs_conflict, ctx->vregs_multi_write, ctx->vregs_uncond,
- NUM_VREGS);
- if (!bitmap_empty(vregs_conflict, NUM_VREGS)) {
- return true;
- }
-
- if (!bitmap_empty(ctx->qregs_multi_write, NUM_QREGS)) {
- return true;
- }
-
#ifndef CONFIG_USER_ONLY
if (!bitmap_empty(ctx->gregs_multi_write, NUM_GREGS)) {
return true;
@@ -657,6 +647,19 @@ static bool pkt_has_write_conflict(DisasContext *ctx)
return false;
}
+static bool pkt_has_hvx_write_conflict(DisasContext *ctx)
+{
+ DECLARE_BITMAP(vregs_conflict, NUM_VREGS);
+ DECLARE_BITMAP(qregs_conflict, NUM_QREGS);
+
+ bitmap_and(vregs_conflict, ctx->vregs_multi_write, ctx->vregs_uncond,
+ NUM_VREGS);
+ bitmap_and(qregs_conflict, ctx->qregs_multi_write, ctx->qregs_uncond,
+ NUM_QREGS);
+ return !bitmap_empty(vregs_conflict, NUM_VREGS) ||
+ !bitmap_empty(qregs_conflict, NUM_QREGS);
+}
+
static void analyze_packet(DisasContext *ctx)
{
ctx->read_after_write = false;
@@ -1275,6 +1278,12 @@ static void decode_and_translate_packet(CPUHexagonState
*env, DisasContext *ctx)
clear_pkt_ctx(ctx);
analyze_packet(ctx);
+ if (pkt_has_hvx_write_conflict(ctx)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "multiple HVX register writes at PC 0x" TARGET_FMT_lx
+ "\n", ctx->pkt.pc);
+ }
+
if (pkt_has_write_conflict(ctx)) {
gen_exception_decode_fail(ctx, words_read,
HEX_CAUSE_REG_WRITE_CONFLICT);
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 02c54506145..d344284e8a2 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1069,8 +1069,10 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
"""))
def analyze_write(self, f, tag, regno):
+ predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
- ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
+ ctx_log_qreg_write(ctx, {self.reg_num}, {predicated},
+ insn_has_hvx_helper);
"""))
class QRegSource(Register, Hvx, OldSource):
@@ -1117,8 +1119,10 @@ def analyze_read(self, f, regno):
ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
"""))
def analyze_write(self, f, tag, regno):
+ predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
- ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
+ ctx_log_qreg_write(ctx, {self.reg_num}, {predicated},
+ insn_has_hvx_helper);
"""))
class GuestRegister(Register):
--
2.34.1