vec_full_reg_size(s), gvec_op);
}
+/* Expand a 3-operand operation using an out-of-line helper. */
+static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
+ int rn, int rm, int data, gen_helper_gvec_3 *fn)
+{
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm),
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
+}
+
/* Expand a 3-operand + env pointer operation using
* an out-of-line helper.
*/
}
feature = ARM_FEATURE_V8_RDM;
break;
+ case 0x02: /* SDOT (vector) */
+ case 0x12: /* UDOT (vector) */
+ if (size != MO_32) {
+ unallocated_encoding(s);
+ return;
+ }
+ feature = ARM_FEATURE_V8_DOTPROD;
+ break;
case 0x8: /* FCMLA, #0 */
case 0x9: /* FCMLA, #90 */
case 0xa: /* FCMLA, #180 */
}
return;
+ case 0x2: /* SDOT / UDOT */
+ gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0,
+ u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b);
+ return;
+
case 0x8: /* FCMLA, #0 */
case 0x9: /* FCMLA, #90 */
case 0xa: /* FCMLA, #180 */
return;
}
break;
+ case 0x0e: /* SDOT */
+ case 0x1e: /* UDOT */
+ if (size != MO_32 || !arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
+ unallocated_encoding(s);
+ return;
+ }
+ break;
case 0x11: /* FCMLA #0 */
case 0x13: /* FCMLA #90 */
case 0x15: /* FCMLA #180 */
}
switch (16 * u + opcode) {
+ case 0x0e: /* SDOT */
+ case 0x1e: /* UDOT */
+ gen_gvec_op3_ool(s, is_q, rd, rn, rm, index,
+ u ? gen_helper_gvec_udot_idx_b
+ : gen_helper_gvec_sdot_idx_b);
+ return;
case 0x11: /* FCMLA #0 */
case 0x13: /* FCMLA #90 */
case 0x15: /* FCMLA #180 */
*/
static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
{
- gen_helper_gvec_3_ptr *fn_gvec_ptr;
- int rd, rn, rm, rot, size, opr_sz;
- TCGv_ptr fpst;
+ gen_helper_gvec_3 *fn_gvec = NULL;
+ gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
+ int rd, rn, rm, opr_sz;
+ int data = 0;
bool q;
q = extract32(insn, 6, 1);
if ((insn & 0xfe200f10) == 0xfc200800) {
/* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
- size = extract32(insn, 20, 1);
- rot = extract32(insn, 23, 2);
+ int size = extract32(insn, 20, 1);
+ data = extract32(insn, 23, 2); /* rot */
if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
return 1;
fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
} else if ((insn & 0xfea00f10) == 0xfc800800) {
/* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
- size = extract32(insn, 20, 1);
- rot = extract32(insn, 24, 1);
+ int size = extract32(insn, 20, 1);
+ data = extract32(insn, 24, 1); /* rot */
if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
return 1;
}
fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
+ } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
+ /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
+ bool u = extract32(insn, 4, 1);
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
+ return 1;
+ }
+ fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
} else {
return 1;
}
}
opr_sz = (1 + q) * 8;
- fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
- opr_sz, opr_sz, rot, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (fn_gvec_ptr) {
+ TCGv_ptr fpst = get_fpstatus_ptr(1);
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
+ vfp_reg_offset(1, rn),
+ vfp_reg_offset(1, rm), fpst,
+ opr_sz, opr_sz, data, fn_gvec_ptr);
+ tcg_temp_free_ptr(fpst);
+ } else {
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
+ vfp_reg_offset(1, rn),
+ vfp_reg_offset(1, rm),
+ opr_sz, opr_sz, data, fn_gvec);
+ }
return 0;
}
static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
{
- gen_helper_gvec_3_ptr *fn_gvec_ptr;
+ gen_helper_gvec_3 *fn_gvec = NULL;
+ gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
int rd, rn, rm, opr_sz, data;
- TCGv_ptr fpst;
bool q;
q = extract32(insn, 6, 1);
data = (index << 2) | rot;
fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
: gen_helper_gvec_fcmlah_idx);
+ } else if ((insn & 0xffb00f00) == 0xfe200d00) {
+ /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
+ int u = extract32(insn, 4, 1);
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
+ return 1;
+ }
+ fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
+ /* rm is just Vm, and index is M. */
+ data = extract32(insn, 5, 1); /* index */
+ rm = extract32(insn, 0, 4);
} else {
return 1;
}
}
opr_sz = (1 + q) * 8;
- fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
- opr_sz, opr_sz, data, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (fn_gvec_ptr) {
+ TCGv_ptr fpst = get_fpstatus_ptr(1);
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
+ vfp_reg_offset(1, rn),
+ vfp_reg_offset(1, rm), fpst,
+ opr_sz, opr_sz, data, fn_gvec_ptr);
+ tcg_temp_free_ptr(fpst);
+ } else {
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
+ vfp_reg_offset(1, rn),
+ vfp_reg_offset(1, rm),
+ opr_sz, opr_sz, data, fn_gvec);
+ }
return 0;
}