[PATCH 18/57][Arm][GAS] Add support for MVE instructions: vhcadd, vhadd, vhsub and vrhadd

gas/ChangeLog:
2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	* config/tc-arm.c (enum operand_parse_code): New operand.
	(parse_operands): Handle new operand.
	(mve_encode_qqr): Change to support new instructions.
	(enum vfp_or_neon_is_neon_bits): Moved.
	(vfp_or_neon_is_neon): Moved.
	(check_simd_pred_availability): Moved.
	(do_neon_dyadic_i_su): Changed to support MVE variants.
	(neon_dyadic_misc): Changed mve_encode_qqr call.
	(do_mve_vbrsr): Likewise.
	(do_mve_vhcadd): New encoding function.
	(insns): Change existing to accept MVE variants and add new.
	* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.d: New test.
	* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.l: New test.
	* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.s: New test.
	* testsuite/gas/arm/mve-vhcadd-bad.d: New test.
	* testsuite/gas/arm/mve-vhcadd-bad.l: New test.
	* testsuite/gas/arm/mve-vhcadd-bad.s: New test.
This commit is contained in:
Andre Vieira 2019-05-16 11:40:26 +01:00
parent d58196e061
commit 7df5412033
8 changed files with 358 additions and 95 deletions

View File

@ -1,3 +1,23 @@
2019-05-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
* config/tc-arm.c (enum operand_parse_code): New operand.
(parse_operands): Handle new operand.
(mve_encode_qqr): Change to support new instructions.
(enum vfp_or_neon_is_neon_bits): Moved.
(vfp_or_neon_is_neon): Moved.
(check_simd_pred_availability): Moved.
(do_neon_dyadic_i_su): Changed to support MVE variants.
(neon_dyadic_misc): Changed mve_encode_qqr call.
(do_mve_vbrsr): Likewise.
(do_mve_vhcadd): New encoding function.
(insns): Change existing to accept MVE variants and add new.
* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.d: New test.
* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.l: New test.
* testsuite/gas/arm/mve-vhadd-vhsub-vrhadd-bad.s: New test.
* testsuite/gas/arm/mve-vhcadd-bad.d: New test.
* testsuite/gas/arm/mve-vhcadd-bad.l: New test.
* testsuite/gas/arm/mve-vhcadd-bad.s: New test.
2019-05-16 Andre Vieira <andre.simoesdiasvieira@arm.com>
* config/tc-arm.c (do_neon_fmac): Change to support MVE variants.

View File

@ -6902,6 +6902,7 @@ enum operand_parse_code
OP_RNSD, /* Neon single or double precision register */
OP_RNDQ, /* Neon double or quad precision register */
OP_RNDQMQ, /* Neon double, quad or MVE vector register. */
OP_RNDQMQR, /* Neon double, quad, MVE vector or ARM register. */
OP_RNSDQ, /* Neon single, double or quad precision register */
OP_RNSC, /* Neon scalar D[X] */
OP_RVC, /* VFP control register */
@ -7242,6 +7243,10 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
try_nq:
case OP_RNQ: po_reg_or_fail (REG_TYPE_NQ); break;
case OP_RNSD: po_reg_or_fail (REG_TYPE_NSD); break;
case OP_RNDQMQR:
po_reg_or_goto (REG_TYPE_RN, try_rndqmq);
break;
try_rndqmq:
case OP_oRNDQMQ:
case OP_RNDQMQ:
po_reg_or_goto (REG_TYPE_MQ, try_rndq);
@ -15820,7 +15825,7 @@ neon_dp_fixup (struct arm_it* insn)
}
static void
mve_encode_qqr (int size, int fp)
mve_encode_qqr (int size, int U, int fp)
{
if (inst.operands[2].reg == REG_SP)
as_tsktsk (MVE_BAD_SP);
@ -15847,6 +15852,16 @@ mve_encode_qqr (int size, int fp)
/* vsub. */
else if (((unsigned)inst.instruction) == 0x1000800)
inst.instruction = 0xee011f40;
/* vhadd. */
else if (((unsigned)inst.instruction) == 0)
inst.instruction = 0xee000f40;
/* vhsub. */
else if (((unsigned)inst.instruction) == 0x200)
inst.instruction = 0xee001f40;
/* Set U-bit. */
inst.instruction |= U << 28;
/* Setting bits for size. */
inst.instruction |= neon_logbits (size) << 20;
}
@ -15945,15 +15960,112 @@ neon_two_same (int qbit, int ubit, int size)
neon_dp_fixup (&inst);
}
enum vfp_or_neon_is_neon_bits
{
NEON_CHECK_CC = 1,
NEON_CHECK_ARCH = 2,
NEON_CHECK_ARCH8 = 4
};
/* Call this function if an instruction which may have belonged to the VFP or
Neon instruction sets, but turned out to be a Neon instruction (due to the
operand types involved, etc.). We have to check and/or fix-up a couple of
things:
- Make sure the user hasn't attempted to make a Neon instruction
conditional.
- Alter the value in the condition code field if necessary.
- Make sure that the arch supports Neon instructions.
Which of these operations take place depends on bits from enum
vfp_or_neon_is_neon_bits.
WARNING: This function has side effects! If NEON_CHECK_CC is used and the
current instruction's condition is COND_ALWAYS, the condition field is
changed to inst.uncond_value. This is necessary because instructions shared
between VFP and Neon may be conditional for the VFP variants only, and the
unconditional Neon version must have, e.g., 0xF in the condition field. */
static int
vfp_or_neon_is_neon (unsigned check)
{
/* Conditions are always legal in Thumb mode (IT blocks). */
if (!thumb_mode && (check & NEON_CHECK_CC))
{
if (inst.cond != COND_ALWAYS)
{
first_error (_(BAD_COND));
return FAIL;
}
if (inst.uncond_value != -1)
inst.instruction |= inst.uncond_value << 28;
}
if (((check & NEON_CHECK_ARCH) && !mark_feature_used (&fpu_neon_ext_v1))
|| ((check & NEON_CHECK_ARCH8)
&& !mark_feature_used (&fpu_neon_ext_armv8)))
{
first_error (_(BAD_FPU));
return FAIL;
}
return SUCCESS;
}
static int
check_simd_pred_availability (int fp, unsigned check)
{
if (inst.cond > COND_ALWAYS)
{
if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
{
inst.error = BAD_FPU;
return 1;
}
inst.pred_insn_type = INSIDE_VPT_INSN;
}
else if (inst.cond < COND_ALWAYS)
{
if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
else if (vfp_or_neon_is_neon (check) == FAIL)
return 2;
}
else
{
if (!ARM_CPU_HAS_FEATURE (cpu_variant, fp ? mve_fp_ext : mve_ext)
&& vfp_or_neon_is_neon (check) == FAIL)
return 3;
if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
}
return 0;
}
/* Neon instruction encoders, in approximate order of appearance. */
static void
do_neon_dyadic_i_su (void)
{
enum neon_shape rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL);
struct neon_type_el et = neon_check_type (3, rs,
N_EQK, N_EQK, N_SU_32 | N_KEY);
neon_three_same (neon_quad (rs), et.type == NT_unsigned, et.size);
if (check_simd_pred_availability (0, NEON_CHECK_ARCH | NEON_CHECK_CC))
return;
enum neon_shape rs;
struct neon_type_el et;
if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
rs = neon_select_shape (NS_QQQ, NS_QQR, NS_NULL);
else
rs = neon_select_shape (NS_DDD, NS_QQQ, NS_NULL);
et = neon_check_type (3, rs, N_EQK, N_EQK, N_SU_32 | N_KEY);
if (rs != NS_QQR)
neon_three_same (neon_quad (rs), et.type == NT_unsigned, et.size);
else
mve_encode_qqr (et.size, et.type == NT_unsigned, 0);
}
static void
@ -16120,90 +16232,6 @@ neon_cmode_for_logic_imm (unsigned immediate, unsigned *immbits, int size)
return FAIL;
}
enum vfp_or_neon_is_neon_bits
{
NEON_CHECK_CC = 1,
NEON_CHECK_ARCH = 2,
NEON_CHECK_ARCH8 = 4
};
/* Call this function if an instruction which may have belonged to the VFP or
Neon instruction sets, but turned out to be a Neon instruction (due to the
operand types involved, etc.). We have to check and/or fix-up a couple of
things:
- Make sure the user hasn't attempted to make a Neon instruction
conditional.
- Alter the value in the condition code field if necessary.
- Make sure that the arch supports Neon instructions.
Which of these operations take place depends on bits from enum
vfp_or_neon_is_neon_bits.
WARNING: This function has side effects! If NEON_CHECK_CC is used and the
current instruction's condition is COND_ALWAYS, the condition field is
changed to inst.uncond_value. This is necessary because instructions shared
between VFP and Neon may be conditional for the VFP variants only, and the
unconditional Neon version must have, e.g., 0xF in the condition field. */
static int
vfp_or_neon_is_neon (unsigned check)
{
/* Conditions are always legal in Thumb mode (IT blocks). */
if (!thumb_mode && (check & NEON_CHECK_CC))
{
if (inst.cond != COND_ALWAYS)
{
first_error (_(BAD_COND));
return FAIL;
}
if (inst.uncond_value != -1)
inst.instruction |= inst.uncond_value << 28;
}
if (((check & NEON_CHECK_ARCH) && !mark_feature_used (&fpu_neon_ext_v1))
|| ((check & NEON_CHECK_ARCH8)
&& !mark_feature_used (&fpu_neon_ext_armv8)))
{
first_error (_(BAD_FPU));
return FAIL;
}
return SUCCESS;
}
static int
check_simd_pred_availability (int fp, unsigned check)
{
if (inst.cond > COND_ALWAYS)
{
if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
{
inst.error = BAD_FPU;
return 1;
}
inst.pred_insn_type = INSIDE_VPT_INSN;
}
else if (inst.cond < COND_ALWAYS)
{
if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
else if (vfp_or_neon_is_neon (check) == FAIL)
return 2;
}
else
{
if (!ARM_CPU_HAS_FEATURE (cpu_variant, fp ? mve_fp_ext : mve_ext)
&& vfp_or_neon_is_neon (check) == FAIL)
return 3;
if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
}
return 0;
}
static void
do_neon_logic (void)
{
@ -16332,7 +16360,7 @@ neon_dyadic_misc (enum neon_el_type ubit_meaning, unsigned types,
{
NEON_ENCODE (FLOAT, inst);
if (rs == NS_QQR)
mve_encode_qqr (et.size, 1);
mve_encode_qqr (et.size, 0, 1);
else
neon_three_same (neon_quad (rs), 0, et.size == 16 ? (int) et.size : -1);
}
@ -16340,7 +16368,7 @@ neon_dyadic_misc (enum neon_el_type ubit_meaning, unsigned types,
{
NEON_ENCODE (INTEGER, inst);
if (rs == NS_QQR)
mve_encode_qqr (et.size, 0);
mve_encode_qqr (et.size, 0, 0);
else
neon_three_same (neon_quad (rs), et.type == ubit_meaning, et.size);
}
@ -16991,6 +17019,30 @@ do_mve_vaddv (void)
mve_encode_rq (et.type == NT_unsigned, et.size);
}
static void
do_mve_vhcadd (void)
{
enum neon_shape rs = neon_select_shape (NS_QQQI, NS_NULL);
struct neon_type_el et
= neon_check_type (3, rs, N_EQK, N_EQK, N_S8 | N_S16 | N_S32 | N_KEY);
if (inst.cond > COND_ALWAYS)
inst.pred_insn_type = INSIDE_VPT_INSN;
else
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
unsigned rot = inst.relocs[0].exp.X_add_number;
constraint (rot != 90 && rot != 270, _("immediate out of range"));
if (et.size == 32 && inst.operands[0].reg == inst.operands[2].reg)
as_tsktsk (_("Warning: 32-bit element size and same first and third "
"operand makes instruction UNPREDICTABLE"));
mve_encode_qqq (0, et.size);
inst.instruction |= (rot == 270) << 12;
inst.is_neon = 1;
}
static void
do_mve_vadc (void)
{
@ -17021,7 +17073,7 @@ do_mve_vbrsr (void)
else
inst.pred_insn_type = MVE_OUTSIDE_PRED_INSN;
mve_encode_qqr (et.size, 0);
mve_encode_qqr (et.size, 0, 0);
}
static void
@ -23585,11 +23637,8 @@ static const struct asm_opcode insns[] =
/* integer ops, valid types S8 S16 S32 U8 U16 U32. */
NUF(vaba, 0000710, 3, (RNDQ, RNDQ, RNDQ), neon_dyadic_i_su),
NUF(vabaq, 0000710, 3, (RNQ, RNQ, RNQ), neon_dyadic_i_su),
NUF(vhadd, 0000000, 3, (RNDQ, oRNDQ, RNDQ), neon_dyadic_i_su),
NUF(vhaddq, 0000000, 3, (RNQ, oRNQ, RNQ), neon_dyadic_i_su),
NUF(vrhadd, 0000100, 3, (RNDQ, oRNDQ, RNDQ), neon_dyadic_i_su),
NUF(vrhaddq, 0000100, 3, (RNQ, oRNQ, RNQ), neon_dyadic_i_su),
NUF(vhsub, 0000200, 3, (RNDQ, oRNDQ, RNDQ), neon_dyadic_i_su),
NUF(vhsubq, 0000200, 3, (RNQ, oRNQ, RNQ), neon_dyadic_i_su),
/* integer ops, valid types S8 S16 S32 S64 U8 U16 U32 U64. */
NUF(vqadd, 0000010, 3, (RNDQ, oRNDQ, RNDQ), neon_dyadic_i64_su),
@ -24271,6 +24320,7 @@ static const struct asm_opcode insns[] =
ToC("vpsteee", fe712f4d, 0, (), mve_vpt),
/* MVE and MVE FP only. */
mToC("vhcadd", ee000f00, 4, (RMQ, RMQ, RMQ, EXPi), mve_vhcadd),
mCEF(vadc, _vadc, 3, (RMQ, RMQ, RMQ), mve_vadc),
mCEF(vadci, _vadci, 3, (RMQ, RMQ, RMQ), mve_vadc),
mToC("vsbc", fe300f00, 3, (RMQ, RMQ, RMQ), mve_vsbc),
@ -24383,6 +24433,9 @@ static const struct asm_opcode insns[] =
MNUF(vcls, 1b00400, 2, (RNDQMQ, RNDQMQ), neon_cls),
MNUF(vclz, 1b00480, 2, (RNDQMQ, RNDQMQ), neon_clz),
mnCE(vdup, _vdup, 2, (RNDQMQ, RR_RNSC), neon_dup),
MNUF(vhadd, 00000000, 3, (RNDQMQ, oRNDQMQ, RNDQMQR), neon_dyadic_i_su),
MNUF(vrhadd, 00000100, 3, (RNDQMQ, oRNDQMQ, RNDQMQ), neon_dyadic_i_su),
MNUF(vhsub, 00000200, 3, (RNDQMQ, oRNDQMQ, RNDQMQR), neon_dyadic_i_su),
#undef ARM_VARIANT
#define ARM_VARIANT & arm_ext_v8_3

View File

@ -0,0 +1,5 @@
#name: bad MVE VHADD, VHSUB and VRHADD instructions
#as: -march=armv8.1-m.main+mve
#error_output: mve-vhadd-vhsub-vrhadd-bad.l
.*: +file format .*arm.*

View File

@ -0,0 +1,71 @@
[^:]*: Assembler messages:
[^:]*:10: Error: bad type in SIMD instruction -- `vhadd.i8 q0,q1,q2'
[^:]*:11: Error: bad type in SIMD instruction -- `vhadd.s64 q0,q1,q2'
[^:]*:12: Error: bad type in SIMD instruction -- `vhadd.i8 q0,q1,r2'
[^:]*:13: Error: bad type in SIMD instruction -- `vhadd.s64 q0,q1,r2'
[^:]*:14: Error: bad type in SIMD instruction -- `vhsub.i16 q0,q1,q2'
[^:]*:15: Error: bad type in SIMD instruction -- `vhsub.u64 q0,q1,q2'
[^:]*:16: Error: bad type in SIMD instruction -- `vhsub.i16 q0,q1,r2'
[^:]*:17: Error: bad type in SIMD instruction -- `vhsub.u64 q0,q1,r2'
[^:]*:18: Error: bad type in SIMD instruction -- `vrhadd.i32 q0,q1,q2'
[^:]*:19: Error: bad type in SIMD instruction -- `vrhadd.s64 q0,q1,q2'
[^:]*:20: Warning: instruction is UNPREDICTABLE with SP operand
[^:]*:21: Warning: instruction is UNPREDICTABLE with PC operand
[^:]*:22: Warning: instruction is UNPREDICTABLE with SP operand
[^:]*:23: Warning: instruction is UNPREDICTABLE with PC operand
[^:]*:24: Error: garbage following instruction -- `vrhadd.s8 q0,q1,r2'
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:28: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:29: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:31: Error: syntax error -- `vhaddeq.s8 q0,q1,r2'
[^:]*:32: Error: syntax error -- `vhaddeq.s8 q0,q1,r2'
[^:]*:34: Error: syntax error -- `vhaddeq.s8 q0,q1,r2'
[^:]*:35: Error: vector predicated instruction should be in VPT/VPST block -- `vhaddt.s8 q0,q1,r2'
[^:]*:37: Error: instruction missing MVE vector predication code -- `vhadd.s8 q0,q1,r2'
[^:]*:39: Error: syntax error -- `vhaddeq.s8 q0,q1,q2'
[^:]*:40: Error: syntax error -- `vhaddeq.s8 q0,q1,q2'
[^:]*:42: Error: syntax error -- `vhaddeq.s8 q0,q1,q2'
[^:]*:43: Error: vector predicated instruction should be in VPT/VPST block -- `vhaddt.s8 q0,q1,q2'
[^:]*:45: Error: instruction missing MVE vector predication code -- `vhadd.s8 q0,q1,q2'
[^:]*:47: Error: syntax error -- `vhsubeq.s8 q0,q1,r2'
[^:]*:48: Error: syntax error -- `vhsubeq.s8 q0,q1,r2'
[^:]*:50: Error: syntax error -- `vhsubeq.s8 q0,q1,r2'
[^:]*:51: Error: vector predicated instruction should be in VPT/VPST block -- `vhsubt.s8 q0,q1,r2'
[^:]*:53: Error: instruction missing MVE vector predication code -- `vhsub.s8 q0,q1,r2'
[^:]*:55: Error: syntax error -- `vhsubeq.s8 q0,q1,q2'
[^:]*:56: Error: syntax error -- `vhsubeq.s8 q0,q1,q2'
[^:]*:58: Error: syntax error -- `vhsubeq.s8 q0,q1,q2'
[^:]*:59: Error: vector predicated instruction should be in VPT/VPST block -- `vhsubt.s8 q0,q1,q2'
[^:]*:61: Error: instruction missing MVE vector predication code -- `vhsub.s8 q0,q1,q2'
[^:]*:63: Error: syntax error -- `vrhaddeq.s8 q0,q1,q2'
[^:]*:64: Error: syntax error -- `vrhaddeq.s8 q0,q1,q2'
[^:]*:66: Error: syntax error -- `vrhaddeq.s8 q0,q1,q2'
[^:]*:67: Error: vector predicated instruction should be in VPT/VPST block -- `vrhaddt.s8 q0,q1,q2'
[^:]*:69: Error: instruction missing MVE vector predication code -- `vrhadd.s8 q0,q1,q2'

View File

@ -0,0 +1,69 @@
.macro cond, op, lastreg
.irp cond, eq, ne, gt, ge, lt, le
it \cond
\op\().s8 q0, q1, \lastreg
.endr
.endm
.syntax unified
.thumb
vhadd.i8 q0, q1, q2
vhadd.s64 q0, q1, q2
vhadd.i8 q0, q1, r2
vhadd.s64 q0, q1, r2
vhsub.i16 q0, q1, q2
vhsub.u64 q0, q1, q2
vhsub.i16 q0, q1, r2
vhsub.u64 q0, q1, r2
vrhadd.i32 q0, q1, q2
vrhadd.s64 q0, q1, q2
vhadd.s8 q0, q1, sp
vhadd.s8 q0, q1, pc
vhsub.s8 q0, q1, sp
vhsub.s8 q0, q1, pc
vrhadd.s8 q0, q1, r2
cond vhadd, r2
cond vhadd, q2
cond vhsub, r2
cond vhsub, q2
cond vrhadd, q2
it eq
vhaddeq.s8 q0, q1, r2
vhaddeq.s8 q0, q1, r2
vpst
vhaddeq.s8 q0, q1, r2
vhaddt.s8 q0, q1, r2
vpst
vhadd.s8 q0, q1, r2
it eq
vhaddeq.s8 q0, q1, q2
vhaddeq.s8 q0, q1, q2
vpst
vhaddeq.s8 q0, q1, q2
vhaddt.s8 q0, q1, q2
vpst
vhadd.s8 q0, q1, q2
it eq
vhsubeq.s8 q0, q1, r2
vhsubeq.s8 q0, q1, r2
vpst
vhsubeq.s8 q0, q1, r2
vhsubt.s8 q0, q1, r2
vpst
vhsub.s8 q0, q1, r2
it eq
vhsubeq.s8 q0, q1, q2
vhsubeq.s8 q0, q1, q2
vpst
vhsubeq.s8 q0, q1, q2
vhsubt.s8 q0, q1, q2
vpst
vhsub.s8 q0, q1, q2
it eq
vrhaddeq.s8 q0, q1, q2
vrhaddeq.s8 q0, q1, q2
vpst
vrhaddeq.s8 q0, q1, q2
vrhaddt.s8 q0, q1, q2
vpst
vrhadd.s8 q0, q1, q2

View File

@ -0,0 +1,5 @@
#name: bad MVE VHCADD instructions
#as: -march=armv8.1-m.main+mve
#error_output: mve-vhcadd-bad.l
.*: +file format .*arm.*

View File

@ -0,0 +1,17 @@
[^:]*: Assembler messages:
[^:]*:10: Error: bad type in SIMD instruction -- `vhcadd.u8 q0,q1,q2,#90'
[^:]*:11: Error: bad type in SIMD instruction -- `vhcadd.i8 q0,q1,q2,#90'
[^:]*:12: Error: bad type in SIMD instruction -- `vhcadd.s64 q0,q1,q2,#90'
[^:]*:13: Error: immediate out of range -- `vhcadd.s8 q0,q1,q2,#0'
[^:]*:14: Error: immediate out of range -- `vhcadd.s8 q0,q1,q2,#180'
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:15: Warning: instruction is UNPREDICTABLE in an IT block
[^:]*:17: Error: syntax error -- `vhcaddeq.s8 q0,q1,q2,#90'
[^:]*:18: Error: syntax error -- `vhcaddeq.s8 q0,q1,q2,#90'
[^:]*:20: Error: syntax error -- `vhcaddeq.s8 q0,q1,q2,#90'
[^:]*:21: Error: vector predicated instruction should be in VPT/VPST block -- `vhcaddt.s8 q0,q1,q2,#90'
[^:]*:23: Error: instruction missing MVE vector predication code -- `vhcadd.s8 q0,q1,q2,#90'

View File

@ -0,0 +1,23 @@
.macro cond
.irp cond, eq, ne, gt, ge, lt, le
it \cond
vhcadd.s8 q0, q1, q2, #90
.endr
.endm
.syntax unified
.thumb
vhcadd.u8 q0, q1, q2, #90
vhcadd.i8 q0, q1, q2, #90
vhcadd.s64 q0, q1, q2, #90
vhcadd.s8 q0, q1, q2, #0
vhcadd.s8 q0, q1, q2, #180
cond
it eq
vhcaddeq.s8 q0, q1, q2, #90
vhcaddeq.s8 q0, q1, q2, #90
vpst
vhcaddeq.s8 q0, q1, q2, #90
vhcaddt.s8 q0, q1, q2, #90
vpst
vhcadd.s8 q0, q1, q2, #90