mirror of https://github.com/xemu-project/xemu.git
target-arm: Handle UNDEF cases for Neon 3-regs-different-widths
Add missing UNDEF checks for instructions in the Neon "3 registers of different widths" data processing space. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
7d80fee5b9
commit
695272dcb9
|
@ -5174,31 +5174,47 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||||
int src1_wide;
|
int src1_wide;
|
||||||
int src2_wide;
|
int src2_wide;
|
||||||
int prewiden;
|
int prewiden;
|
||||||
/* prewiden, src1_wide, src2_wide */
|
/* undefreq: bit 0 : UNDEF if size != 0
|
||||||
static const int neon_3reg_wide[16][3] = {
|
* bit 1 : UNDEF if size == 0
|
||||||
{1, 0, 0}, /* VADDL */
|
* bit 2 : UNDEF if U == 1
|
||||||
{1, 1, 0}, /* VADDW */
|
* Note that [1:0] set implies 'always UNDEF'
|
||||||
{1, 0, 0}, /* VSUBL */
|
*/
|
||||||
{1, 1, 0}, /* VSUBW */
|
int undefreq;
|
||||||
{0, 1, 1}, /* VADDHN */
|
/* prewiden, src1_wide, src2_wide, undefreq */
|
||||||
{0, 0, 0}, /* VABAL */
|
static const int neon_3reg_wide[16][4] = {
|
||||||
{0, 1, 1}, /* VSUBHN */
|
{1, 0, 0, 0}, /* VADDL */
|
||||||
{0, 0, 0}, /* VABDL */
|
{1, 1, 0, 0}, /* VADDW */
|
||||||
{0, 0, 0}, /* VMLAL */
|
{1, 0, 0, 0}, /* VSUBL */
|
||||||
{0, 0, 0}, /* VQDMLAL */
|
{1, 1, 0, 0}, /* VSUBW */
|
||||||
{0, 0, 0}, /* VMLSL */
|
{0, 1, 1, 0}, /* VADDHN */
|
||||||
{0, 0, 0}, /* VQDMLSL */
|
{0, 0, 0, 0}, /* VABAL */
|
||||||
{0, 0, 0}, /* Integer VMULL */
|
{0, 1, 1, 0}, /* VSUBHN */
|
||||||
{0, 0, 0}, /* VQDMULL */
|
{0, 0, 0, 0}, /* VABDL */
|
||||||
{0, 0, 0} /* Polynomial VMULL */
|
{0, 0, 0, 0}, /* VMLAL */
|
||||||
|
{0, 0, 0, 6}, /* VQDMLAL */
|
||||||
|
{0, 0, 0, 0}, /* VMLSL */
|
||||||
|
{0, 0, 0, 6}, /* VQDMLSL */
|
||||||
|
{0, 0, 0, 0}, /* Integer VMULL */
|
||||||
|
{0, 0, 0, 2}, /* VQDMULL */
|
||||||
|
{0, 0, 0, 5}, /* Polynomial VMULL */
|
||||||
|
{0, 0, 0, 3}, /* Reserved: always UNDEF */
|
||||||
};
|
};
|
||||||
|
|
||||||
prewiden = neon_3reg_wide[op][0];
|
prewiden = neon_3reg_wide[op][0];
|
||||||
src1_wide = neon_3reg_wide[op][1];
|
src1_wide = neon_3reg_wide[op][1];
|
||||||
src2_wide = neon_3reg_wide[op][2];
|
src2_wide = neon_3reg_wide[op][2];
|
||||||
|
undefreq = neon_3reg_wide[op][3];
|
||||||
|
|
||||||
if (size == 0 && (op == 9 || op == 11 || op == 13))
|
if (((undefreq & 1) && (size != 0)) ||
|
||||||
|
((undefreq & 2) && (size == 0)) ||
|
||||||
|
((undefreq & 4) && u)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
if ((src1_wide && (rn & 1)) ||
|
||||||
|
(src2_wide && (rm & 1)) ||
|
||||||
|
(!src2_wide && (rd & 1))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Avoid overlapping operands. Wide source operands are
|
/* Avoid overlapping operands. Wide source operands are
|
||||||
always aligned so will never overlap with wide
|
always aligned so will never overlap with wide
|
||||||
|
@ -5279,8 +5295,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||||
tcg_temp_free_i32(tmp2);
|
tcg_temp_free_i32(tmp2);
|
||||||
tcg_temp_free_i32(tmp);
|
tcg_temp_free_i32(tmp);
|
||||||
break;
|
break;
|
||||||
default: /* 15 is RESERVED. */
|
default: /* 15 is RESERVED: caught earlier */
|
||||||
return 1;
|
abort();
|
||||||
}
|
}
|
||||||
if (op == 13) {
|
if (op == 13) {
|
||||||
/* VQDMULL */
|
/* VQDMULL */
|
||||||
|
|
Loading…
Reference in New Issue