mirror of https://github.com/xemu-project/xemu.git
target/arm: Convert Neon 3-reg-diff polynomial VMULL
Convert the Neon 3-reg-diff insn polynomial VMULL. This is the last insn in this group to be converted. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
9546ca5998
commit
18fb58d588
|
@ -465,5 +465,7 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
|
|||
VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
|
||||
|
||||
VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
|
||||
|
||||
VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2304,3 +2304,46 @@ static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a)
|
|||
|
||||
return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
|
||||
}
|
||||
|
||||
static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
|
||||
{
|
||||
gen_helper_gvec_3 *fn_gvec;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UNDEF accesses to D16-D31 if they don't exist. */
|
||||
if (!dc_isar_feature(aa32_simd_r32, s) &&
|
||||
((a->vd | a->vn | a->vm) & 0x10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a->vd & 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (a->size) {
|
||||
case 0:
|
||||
fn_gvec = gen_helper_neon_pmull_h;
|
||||
break;
|
||||
case 2:
|
||||
if (!dc_isar_feature(aa32_pmull, s)) {
|
||||
return false;
|
||||
}
|
||||
fn_gvec = gen_helper_gvec_pmull_q;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
tcg_gen_gvec_3_ool(neon_reg_offset(a->vd, 0),
|
||||
neon_reg_offset(a->vn, 0),
|
||||
neon_reg_offset(a->vm, 0),
|
||||
16, 16, 0, fn_gvec);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5181,7 +5181,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
{
|
||||
int op;
|
||||
int q;
|
||||
int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
|
||||
int rd, rn, rm, rd_ofs, rm_ofs;
|
||||
int size;
|
||||
int pass;
|
||||
int u;
|
||||
|
@ -5215,7 +5215,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
size = (insn >> 20) & 3;
|
||||
vec_size = q ? 16 : 8;
|
||||
rd_ofs = neon_reg_offset(rd, 0);
|
||||
rn_ofs = neon_reg_offset(rn, 0);
|
||||
rm_ofs = neon_reg_offset(rm, 0);
|
||||
|
||||
if ((insn & (1 << 23)) == 0) {
|
||||
|
@ -5228,61 +5227,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
if (size != 3) {
|
||||
op = (insn >> 8) & 0xf;
|
||||
if ((insn & (1 << 6)) == 0) {
|
||||
/* Three registers of different lengths. */
|
||||
/* undefreq: bit 0 : UNDEF if size == 0
|
||||
* bit 1 : UNDEF if size == 1
|
||||
* bit 2 : UNDEF if size == 2
|
||||
* bit 3 : UNDEF if U == 1
|
||||
* Note that [2:0] set implies 'always UNDEF'
|
||||
*/
|
||||
int undefreq;
|
||||
/* prewiden, src1_wide, src2_wide, undefreq */
|
||||
static const int neon_3reg_wide[16][4] = {
|
||||
{0, 0, 0, 7}, /* VADDL: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VADDW: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VSUBL: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VSUBW: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VADDHN: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VABAL */
|
||||
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
|
||||
{0, 0, 0, 7}, /* VABDL */
|
||||
{0, 0, 0, 7}, /* VMLAL */
|
||||
{0, 0, 0, 7}, /* VQDMLAL */
|
||||
{0, 0, 0, 7}, /* VMLSL */
|
||||
{0, 0, 0, 7}, /* VQDMLSL */
|
||||
{0, 0, 0, 7}, /* Integer VMULL */
|
||||
{0, 0, 0, 7}, /* VQDMULL */
|
||||
{0, 0, 0, 0xa}, /* Polynomial VMULL */
|
||||
{0, 0, 0, 7}, /* Reserved: always UNDEF */
|
||||
};
|
||||
|
||||
undefreq = neon_3reg_wide[op][3];
|
||||
|
||||
if ((undefreq & (1 << size)) ||
|
||||
((undefreq & 8) && u)) {
|
||||
return 1;
|
||||
}
|
||||
if (rd & 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle polynomial VMULL in a single pass. */
|
||||
if (op == 14) {
|
||||
if (size == 0) {
|
||||
/* VMULL.P8 */
|
||||
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
|
||||
0, gen_helper_neon_pmull_h);
|
||||
} else {
|
||||
/* VMULL.P64 */
|
||||
if (!dc_isar_feature(aa32_pmull, s)) {
|
||||
return 1;
|
||||
}
|
||||
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
|
||||
0, gen_helper_gvec_pmull_q);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
abort(); /* all others handled by decodetree */
|
||||
/* Three registers of different lengths: handled by decodetree */
|
||||
return 1;
|
||||
} else {
|
||||
/* Two registers and a scalar. NB that for ops of this form
|
||||
* the ARM ARM labels bit 24 as Q, but it is in our variable
|
||||
|
|
Loading…
Reference in New Issue