diff options
author | Stam Markianos-Wright <stam.markianos-wright@arm.com> | 2023-01-17 12:57:47 +0000 |
---|---|---|
committer | Tamar Christina <tamar.christina@arm.com> | 2023-01-17 13:38:47 +0000 |
commit | 656412a7a4da0aef43ead1ea976ba0235a7ec30a (patch) | |
tree | 2e2263e55499e324660b0c4cd5e8d63d28a861f7 /gas/config/tc-arm.c | |
parent | 13023445a33e246aa3e221ed746935f5bcb0372d (diff) | |
download | gdb-656412a7a4da0aef43ead1ea976ba0235a7ec30a.zip gdb-656412a7a4da0aef43ead1ea976ba0235a7ec30a.tar.gz gdb-656412a7a4da0aef43ead1ea976ba0235a7ec30a.tar.bz2 |
gas: arm: Fix a further IT-predicated vcvt issue in the presense of MVE vcvtn
Previously we had experienced issues with assembling a "VCVTNE" instruction
in the presence of the MVE architecture extension, because it could be
interpreted both as:
* The base instruction VCVT + NE for IT predication when inside an IT block.
* The MVE instruction VCVTN + E in the Else of a VPT block.
Given a C reproducer of:
```
int test_function(float value)
{
int ret_val = 10;
if (value != 0.0)
{
ret_val = (int) value;
}
return ret_val;
}
```
GCC generates a VCVTNE instruction based on the `truncsisf2_vfp`
pattern, which will look like:
`vcvtne.s32.f32 s-reg, s-reg`
This still triggers an error due to being misidentified as "vcvtn+e"
Similar errors were found with other type combinations and instruction
patterns (these have all been added to the testing of this patch).
This class of errors was previously worked around by:
https://sourceware.org/pipermail/binutils/2020-August/112728.html
which addressed this by looking at the operand types, however,
that isn't adequate to cover all the extra cases that have been
found. Instead, we add some special-casing logic earlier when
the instructions are parsed that is conditional on whether we are
in a VPT block or not, when the instruction is parsed.
gas/ChangeLog:
* config/tc-arm.c (opcode_lookup): Add special vcvtn handling.
* testsuite/gas/arm/mve-vcvtne-it-bad.l: Add further testing.
* testsuite/gas/arm/mve-vcvtne-it-bad.s: Likewise.
* testsuite/gas/arm/mve-vcvtne-it.d: Likewise.
* testsuite/gas/arm/mve-vcvtne-it.s: Likewise.
Diffstat (limited to 'gas/config/tc-arm.c')
-rw-r--r-- | gas/config/tc-arm.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index a5687ba..d86a375 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -19187,16 +19187,6 @@ do_neon_cvt_1 (enum neon_cvt_mode mode) return; } - if ((rs == NS_FD || rs == NS_QQI) && mode == neon_cvt_mode_n - && ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) - { - /* We are dealing with vcvt with the 'ne' condition. */ - inst.cond = 0x1; - inst.instruction = N_MNEM_vcvt; - do_neon_cvt_1 (neon_cvt_mode_z); - return; - } - /* VFP rather than Neon conversions. */ if (flavour >= neon_cvt_flavour_first_fp) { @@ -22792,6 +22782,23 @@ opcode_lookup (char **str) cond = (const struct asm_cond *) str_hash_find_n (arm_vcond_hsh, affix, 1); opcode = (const struct asm_opcode *) str_hash_find_n (arm_ops_hsh, base, affix - base); + + /* A known edge case is a conflict between an 'e' as a suffix for an + Else of a VPT predication block and an 'ne' suffix for an IT block. + If we detect that edge case here and we are not in a VPT VECTOR_PRED + block, reset opcode and cond, so that the 'ne' case can be detected + in the next section for 2-character conditional suffixes. + An example where this is a problem is between the MVE 'vcvtn' and the + non-MVE 'vcvt' instructions. */ + if (cond && opcode + && cond->template_name[0] == 'e' + && opcode->template_name[affix - base - 1] == 'n' + && now_pred.type != VECTOR_PRED) + { + opcode = NULL; + cond = NULL; + } + /* If this opcode can not be vector predicated then don't accept it with a vector predication code. */ if (opcode && !opcode->mayBeVecPred) |