@@ -83,6 +83,11 @@ static inline bool is_preloaded(DisasContext *ctx, int num)
return test_bit(num, ctx->regs_written);
}
+static inline bool is_tmp_vreg_preloaded(DisasContext *ctx, int num)
+{
+ return test_bit(num, ctx->vregs_updated_tmp);
+}
+
intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
int num, bool alloc_ok);
intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
@@ -541,6 +541,43 @@ static void test_vshuff(void)
check_output_b(__LINE__, 1);
}
+static void test_load_tmp_predicated(void)
+{
+ void *p0 = buffer0;
+ void *p1 = buffer1;
+ void *pout = output;
+
+ for (int i = 0; i < BUFSIZE; i++) {
+ /*
+ * Load into v12 as .tmp with a false predicate, then
+ * use it in the next packet
+ * Should get old new value within the same packet and
+ * the old value in the next packet
+ */
+ asm("v3 = vmem(%0 + #0)\n\t"
+ "r1 = #1\n\t"
+ "v12 = vsplat(r1)\n\t"
+ "p1 = cmp.gt(r0, r0)\n\t"
+ "{\n\t"
+ " if (p1) v12.tmp = vmem(%1 + #0)\n\t"
+ " v4.w = vadd(v12.w, v3.w)\n\t"
+ "}\n\t"
+ "v4.w = vadd(v4.w, v12.w)\n\t"
+ "vmem(%2 + #0) = v4\n\t"
+ : : "r"(p0), "r"(p1), "r"(pout)
+ : "r1", "p1", "v12", "v3", "v4", "v6", "memory");
+ p0 += sizeof(MMVector);
+ p1 += sizeof(MMVector);
+ pout += sizeof(MMVector);
+
+ for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+ expect[i].w[j] = buffer0[i].w[j] + 2;
+ }
+ }
+
+ check_output_w(__LINE__, BUFSIZE);
+}
+
int main()
{
init_buffers();
@@ -578,6 +615,8 @@ int main()
test_vshuff();
+ test_load_tmp_predicated();
+
puts(err ? "FAIL" : "PASS");
return err ? 1 : 0;
}
@@ -169,6 +169,18 @@ def genptr_decl(f, tag, regtype, regid, regno):
elif (hex_common.is_tmp_result(tag)):
f.write(" ctx_tmp_vreg_off(ctx, %s%sN, 1, true);\n" % \
(regtype, regid))
+ if ('A_CONDEXEC' in hex_common.attribdict[tag]):
+ f.write(" if (!is_tmp_vreg_preloaded(ctx, %s)) {\n" % \
+ regN)
+ f.write(" intptr_t src_off =")
+ f.write(" offsetof(CPUHexagonState, VRegs[%s%sN]);\n"% \
+ (regtype, regid))
+ f.write(" tcg_gen_gvec_mov(MO_64, %s%sV_off,\n" % \
+ (regtype, regid))
+ f.write(" src_off,\n")
+ f.write(" sizeof(MMVector),\n")
+ f.write(" sizeof(MMVector));\n")
+ f.write(" }\n")
else:
f.write(" ctx_future_vreg_off(ctx, %s%sN," % \
(regtype, regid))
Here is an example of an instruction with a predicated assignment to a .tmp HVX register if (p1) v12.tmp = vmem(%1 + #0) Note that the .tmp indicates that references to v12 in the same packet take the result of the load. However, when the predicate is false, the value at the start of the packet should be used. To fix this bug, we preload the temporary with the value from the HVX register. Test case added to tests/tcg/hexagon/hvx_misc.c Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> --- target/hexagon/translate.h | 5 +++++ tests/tcg/hexagon/hvx_misc.c | 39 +++++++++++++++++++++++++++++++++ target/hexagon/gen_tcg_funcs.py | 12 ++++++++++ 3 files changed, 56 insertions(+)