/* qualifier_const_pointer | qualifier_map_mode */
qualifier_const_pointer_map_mode = 0x86,
/* Polynomial types. */
- qualifier_poly = 0x100
+ qualifier_poly = 0x100,
+ /* Lane indices - must be within range of previous argument = a vector. */
+ qualifier_lane_index = 0x200
};
/* The qualifier_internal allows generation of a unary builtin from
/* T (T, immediate). */
static enum arm_type_qualifiers
-arm_getlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+arm_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_immediate };
+#define BINOP_IMM_QUALIFIERS (arm_binop_imm_qualifiers)
+
+/* T (T, lane index). */
+static enum arm_type_qualifiers
+arm_getlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_none, qualifier_none, qualifier_lane_index };
#define GETLANE_QUALIFIERS (arm_getlane_qualifiers)
/* T (T, T, T, immediate). */
static enum arm_type_qualifiers
-arm_lanemac_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+arm_mac_n_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_none,
qualifier_none, qualifier_immediate };
-#define LANEMAC_QUALIFIERS (arm_lanemac_qualifiers)
+#define MAC_N_QUALIFIERS (arm_mac_n_qualifiers)
+
+/* T (T, T, T, lane index). */
+static enum arm_type_qualifiers
+arm_mac_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_none, qualifier_none, qualifier_none,
+ qualifier_none, qualifier_lane_index };
+#define MAC_LANE_QUALIFIERS (arm_mac_lane_qualifiers)
/* T (T, T, immediate). */
static enum arm_type_qualifiers
-arm_setlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+arm_ternop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
+#define TERNOP_IMM_QUALIFIERS (arm_ternop_imm_qualifiers)
+
+/* T (T, T, lane index). */
+static enum arm_type_qualifiers
+arm_setlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
#define SETLANE_QUALIFIERS (arm_setlane_qualifiers)
/* T (T, T). */
typedef enum {
NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT,
+ NEON_ARG_LANE_INDEX,
NEON_ARG_MEMORY,
NEON_ARG_STOP
} builtin_arg;
op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
break;
+ case NEON_ARG_LANE_INDEX:
+ /* Previous argument must be a vector, which this indexes. */
+ gcc_assert (argc > 0);
+ if (CONST_INT_P (op[argc]))
+ {
+ enum machine_mode vmode = mode[argc - 1];
+ neon_lane_bounds (op[argc], 0, GET_MODE_NUNITS (vmode), exp);
+ }
+ /* Fall through - if the lane index isn't a constant then
+ the next case will error. */
case NEON_ARG_CONSTANT:
if (!(*insn_data[icode].operand[opno].predicate)
(op[argc], mode[argc]))
int operands_k = k - is_void;
int expr_args_k = k - 1;
- if (d->qualifiers[qualifiers_k] & qualifier_immediate)
+ if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
+ args[k] = NEON_ARG_LANE_INDEX;
+ else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
args[k] = NEON_ARG_CONSTANT;
else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
{
VAR8 (BINOP, vqshlu, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
VAR8 (BINOP, vqrshls, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
VAR8 (BINOP, vqrshlu, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vshrs_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vshru_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vrshrs_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vrshru_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR3 (GETLANE, vshrn_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vrshrn_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqshrns_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqshrnu_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqrshrns_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqrshrnu_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqshrun_n, v8hi, v4si, v2di)
-VAR3 (GETLANE, vqrshrun_n, v8hi, v4si, v2di)
-VAR8 (GETLANE, vshl_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vqshl_s_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vqshl_u_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (GETLANE, vqshlu_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR3 (GETLANE, vshlls_n, v8qi, v4hi, v2si)
-VAR3 (GETLANE, vshllu_n, v8qi, v4hi, v2si)
-VAR8 (SETLANE, vsras_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (SETLANE, vsrau_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (SETLANE, vrsras_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (SETLANE, vrsrau_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vshrs_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vshru_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vrshrs_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vrshru_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vshrn_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vrshrn_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqshrns_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqshrnu_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqrshrns_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqrshrnu_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqshrun_n, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vqrshrun_n, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vshl_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vqshl_s_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vqshl_u_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (BINOP_IMM, vqshlu_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR3 (BINOP_IMM, vshlls_n, v8qi, v4hi, v2si)
+VAR3 (BINOP_IMM, vshllu_n, v8qi, v4hi, v2si)
+VAR8 (TERNOP_IMM, vsras_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (TERNOP_IMM, vsrau_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (TERNOP_IMM, vrsras_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (TERNOP_IMM, vrsrau_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
VAR2 (BINOP, vsub, v2sf, v4sf)
VAR3 (BINOP, vsubls, v8qi, v4hi, v2si)
VAR3 (BINOP, vsublu, v8qi, v4hi, v2si)
VAR6 (BINOP, vpadalu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vrecps, v2sf, v4sf)
VAR2 (BINOP, vrsqrts, v2sf, v4sf)
-VAR8 (SETLANE, vsri_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
-VAR8 (SETLANE, vsli_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (TERNOP_IMM, vsri_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
+VAR8 (TERNOP_IMM, vsli_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di)
VAR8 (UNOP, vabs, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR6 (UNOP, vqabs, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR8 (UNOP, vneg, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
VAR5 (UNOP, vcreate, v8qi, v4hi, v2si, v2sf, di)
VAR10 (UNOP, vdup_n,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
-VAR10 (BINOP, vdup_lane,
+VAR10 (GETLANE, vdup_lane,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
VAR5 (COMBINE, vcombine, v8qi, v4hi, v2si, v2sf, di)
VAR5 (UNOP, vget_high, v16qi, v8hi, v4si, v4sf, v2di)
VAR3 (UNOP, vmovls, v8qi, v4hi, v2si)
VAR3 (UNOP, vmovlu, v8qi, v4hi, v2si)
VAR6 (SETLANE, vmul_lane, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR6 (LANEMAC, vmla_lane, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR2 (LANEMAC, vmlals_lane, v4hi, v2si)
-VAR2 (LANEMAC, vmlalu_lane, v4hi, v2si)
-VAR2 (LANEMAC, vqdmlal_lane, v4hi, v2si)
-VAR6 (LANEMAC, vmls_lane, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR2 (LANEMAC, vmlsls_lane, v4hi, v2si)
-VAR2 (LANEMAC, vmlslu_lane, v4hi, v2si)
-VAR2 (LANEMAC, vqdmlsl_lane, v4hi, v2si)
+VAR6 (MAC_LANE, vmla_lane, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
+VAR2 (MAC_LANE, vmlals_lane, v4hi, v2si)
+VAR2 (MAC_LANE, vmlalu_lane, v4hi, v2si)
+VAR2 (MAC_LANE, vqdmlal_lane, v4hi, v2si)
+VAR6 (MAC_LANE, vmls_lane, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
+VAR2 (MAC_LANE, vmlsls_lane, v4hi, v2si)
+VAR2 (MAC_LANE, vmlslu_lane, v4hi, v2si)
+VAR2 (MAC_LANE, vqdmlsl_lane, v4hi, v2si)
VAR6 (BINOP, vmul_n, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR6 (LANEMAC, vmla_n, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR2 (LANEMAC, vmlals_n, v4hi, v2si)
-VAR2 (LANEMAC, vmlalu_n, v4hi, v2si)
-VAR2 (LANEMAC, vqdmlal_n, v4hi, v2si)
-VAR6 (LANEMAC, vmls_n, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
-VAR2 (LANEMAC, vmlsls_n, v4hi, v2si)
-VAR2 (LANEMAC, vmlslu_n, v4hi, v2si)
-VAR2 (LANEMAC, vqdmlsl_n, v4hi, v2si)
+VAR6 (MAC_N, vmla_n, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
+VAR2 (MAC_N, vmlals_n, v4hi, v2si)
+VAR2 (MAC_N, vmlalu_n, v4hi, v2si)
+VAR2 (MAC_N, vqdmlal_n, v4hi, v2si)
+VAR6 (MAC_N, vmls_n, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
+VAR2 (MAC_N, vmlsls_n, v4hi, v2si)
+VAR2 (MAC_N, vmlslu_n, v4hi, v2si)
+VAR2 (MAC_N, vqdmlsl_n, v4hi, v2si)
VAR10 (SETLANE, vext,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
VAR8 (UNOP, vrev64, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf)
(match_operand:SI 2 "immediate_operand" "")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
-
if (BYTES_BIG_ENDIAN)
{
/* The intrinsics are defined in terms of a model where the
(match_operand:SI 2 "immediate_operand" "")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
-
if (BYTES_BIG_ENDIAN)
{
/* The intrinsics are defined in terms of a model where the
(match_operand:SI 2 "immediate_operand" "")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, 1);
emit_move_insn (operands[0], operands[1]);
DONE;
})
(match_operand:SI 2 "immediate_operand" "")]
"TARGET_NEON"
{
- switch (INTVAL (operands[2]))
- {
- case 0:
- emit_move_insn (operands[0], gen_lowpart (DImode, operands[1]));
- break;
- case 1:
- emit_move_insn (operands[0], gen_highpart (DImode, operands[1]));
- break;
- default:
- neon_lane_bounds (operands[2], 0, 1);
- FAIL;
- }
+ int lane = INTVAL (operands[2]);
+ gcc_assert ((lane ==0) || (lane == 1));
+ emit_move_insn (operands[0], lane == 0
+ ? gen_lowpart (DImode, operands[1])
+ : gen_highpart (DImode, operands[1]));
DONE;
})
"TARGET_NEON"
{
unsigned int elt = INTVAL (operands[3]);
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
if (BYTES_BIG_ENDIAN)
{
(match_operand:SI 3 "immediate_operand" "i")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, 1);
emit_move_insn (operands[0], operands[1]);
DONE;
})
(match_operand:SI 2 "immediate_operand" "i")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_double_vector_mode>mode));
if (BYTES_BIG_ENDIAN)
{
unsigned int elt = INTVAL (operands[2]);
(match_operand:SI 2 "immediate_operand" "i")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, 1);
emit_move_insn (operands[0], operands[1]);
DONE;
})
(match_operand:SI 2 "immediate_operand" "i")]
"TARGET_NEON"
{
- neon_lane_bounds (operands[2], 0, 1);
emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
DONE;
})
UNSPEC_VMUL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]";
}
[(set (attr "type")
UNSPEC_VMUL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode));
return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]";
}
[(set (attr "type")
VMULL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmull.<sup>%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
}
[(set_attr "type" "neon_mul_<V_elem_ch>_scalar_long")]
UNSPEC_VQDMULL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
}
[(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_long")]
VQDMULH_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vq<r>dmulh.<V_s_elem>\t%q0, %q1, %P2[%c3]";
}
[(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_q")]
VQDMULH_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vq<r>dmulh.<V_s_elem>\t%P0, %P1, %P2[%c3]";
}
[(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_q")]
UNSPEC_VMLA_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]";
}
[(set (attr "type")
UNSPEC_VMLA_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]";
}
[(set (attr "type")
VMLAL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmlal.<sup>%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
}
[(set_attr "type" "neon_mla_<V_elem_ch>_scalar_long")]
UNSPEC_VQDMLAL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
}
[(set_attr "type" "neon_sat_mla_<V_elem_ch>_scalar_long")]
UNSPEC_VMLS_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]";
}
[(set (attr "type")
UNSPEC_VMLS_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]";
}
[(set (attr "type")
VMLSL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmlsl.<sup>%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
}
[(set_attr "type" "neon_mla_<V_elem_ch>_scalar_long")]
UNSPEC_VQDMLSL_LANE))]
"TARGET_NEON"
{
- neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
}
[(set_attr "type" "neon_sat_mla_<V_elem_ch>_scalar_long")]