mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-10 02:54:58 -06:00
Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur
Here are example instructions with a predicated .tmp/.cur assignment if (p1) v12.tmp = vmem(r7 + #0) if (p0) v12.cur = vmem(r9 + #0) The .tmp/.cur 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. After the packet commits, the .tmp value is dropped, but the .cur value is maintained. To fix this bug, we preload the original value from the HVX register into the temporary used for the result. Test cases added to tests/tcg/hexagon/hvx_misc.c Acked-by: Richard Henderson <richard.henderson@linaro.org> Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com> Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com> Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Message-Id: <20221108162906.3166-3-tsimpson@quicinc.com>
This commit is contained in:
parent
1e536334cc
commit
83853ea0ef
3 changed files with 90 additions and 0 deletions
|
@ -541,6 +541,75 @@ 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;
|
||||
bool pred = true;
|
||||
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
/*
|
||||
* Load into v12 as .tmp with a predicate
|
||||
* When the predicate is true, we get the vector from buffer1[i]
|
||||
* When the predicate is false, we get a vector of all 1's
|
||||
* Regardless of the predicate, the next packet should have
|
||||
* a vector of all 1's
|
||||
*/
|
||||
asm("v3 = vmem(%0 + #0)\n\t"
|
||||
"r1 = #1\n\t"
|
||||
"v12 = vsplat(r1)\n\t"
|
||||
"p1 = !cmp.eq(%3, #0)\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), "r"(pred)
|
||||
: "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] =
|
||||
pred ? buffer0[i].w[j] + buffer1[i].w[j] + 1
|
||||
: buffer0[i].w[j] + 2;
|
||||
}
|
||||
pred = !pred;
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
static void test_load_cur_predicated(void)
|
||||
{
|
||||
bool pred = true;
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
asm volatile("p0 = !cmp.eq(%3, #0)\n\t"
|
||||
"v3 = vmem(%0+#0)\n\t"
|
||||
/*
|
||||
* Preload v4 to make sure that the assignment from the
|
||||
* packet below is not being ignored when pred is false.
|
||||
*/
|
||||
"r0 = #0x01237654\n\t"
|
||||
"v4 = vsplat(r0)\n\t"
|
||||
"{\n\t"
|
||||
" if (p0) v3.cur = vmem(%1+#0)\n\t"
|
||||
" v4 = v3\n\t"
|
||||
"}\n\t"
|
||||
"vmem(%2+#0) = v4\n\t"
|
||||
:
|
||||
: "r"(&buffer0[i]), "r"(&buffer1[i]),
|
||||
"r"(&output[i]), "r"(pred)
|
||||
: "r0", "p0", "v3", "v4", "memory");
|
||||
expect[i] = pred ? buffer1[i] : buffer0[i];
|
||||
pred = !pred;
|
||||
}
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
init_buffers();
|
||||
|
@ -578,6 +647,9 @@ int main()
|
|||
|
||||
test_vshuff();
|
||||
|
||||
test_load_tmp_predicated();
|
||||
test_load_cur_predicated();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue