From aacf0b33aa8a55f935be02a6f6a3b3b62f60d14b Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Wed, 20 Aug 2014 16:49:53 +0100 Subject: [PATCH] [ARM] Fix vcmp with #0.0 * config/tc-arm.c (parse_ifimm_zero): New function. (enum operand_parse_code): Add OP_RSVD_FI0 value. (parse_operands): Handle OP_RSVD_FI0. (asm_opcode_insns): Use RSVD_FI0 for second operand of vcmp, vcmpe. * gas/arm/ual-vcmp.s: New file. * gas/arm/ual-vcmp.d: Likewise. * gas/arm/vcmp-zero-bad.s: Likewise. * gas/arm/vcmp-zero-bad.d: Likewise. * gas/arm/vcmp-zero-bad.l: Likewise. --- gas/ChangeLog | 7 ++++ gas/config/tc-arm.c | 48 +++++++++++++++++++++++++-- gas/testsuite/ChangeLog | 8 +++++ gas/testsuite/gas/arm/ual-vcmp.d | 24 ++++++++++++++ gas/testsuite/gas/arm/ual-vcmp.s | 21 ++++++++++++ gas/testsuite/gas/arm/vcmp-zero-bad.d | 4 +++ gas/testsuite/gas/arm/vcmp-zero-bad.l | 8 +++++ gas/testsuite/gas/arm/vcmp-zero-bad.s | 12 +++++++ 8 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 gas/testsuite/gas/arm/ual-vcmp.d create mode 100644 gas/testsuite/gas/arm/ual-vcmp.s create mode 100644 gas/testsuite/gas/arm/vcmp-zero-bad.d create mode 100644 gas/testsuite/gas/arm/vcmp-zero-bad.l create mode 100644 gas/testsuite/gas/arm/vcmp-zero-bad.s diff --git a/gas/ChangeLog b/gas/ChangeLog index b756e31567d..138a407f906 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2014-08-20 Kyrylo Tkachov + + * config/tc-arm.c (parse_ifimm_zero): New function. + (enum operand_parse_code): Add OP_RSVD_FI0 value. + (parse_operands): Handle OP_RSVD_FI0. + (asm_opcode_insns): Use RSVD_FI0 for second operand of vcmp, vcmpe. + 2014-08-20 Alan Modra * Makefile.am: Typo fix. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 7dc0e7e24cf..ae908b17616 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -249,6 +249,8 @@ static arm_feature_set selected_cpu = ARM_ARCH_NONE; /* Must be long enough to hold any of the names in arm_cpus. */ static char selected_cpu_name[16]; +extern FLONUM_TYPE generic_floating_point_number; + /* Return if no cpu was selected on command-line. */ static bfd_boolean no_cpu_selected (void) @@ -4944,6 +4946,31 @@ is_quarter_float (unsigned imm) return (imm & 0x7ffff) == 0 && ((imm & 0x7e000000) ^ bs) == 0; } + +/* Detect the presence of a floating point or integer zero constant, + i.e. #0.0 or #0. */ + +static bfd_boolean +parse_ifimm_zero (char **in) +{ + int error_code; + + if (!is_immediate_prefix (**in)) + return FALSE; + + ++*in; + error_code = atof_generic (in, ".", EXP_CHARS, + &generic_floating_point_number); + + if (!error_code + && generic_floating_point_number.sign == '+' + && (generic_floating_point_number.low + > generic_floating_point_number.leader)) + return TRUE; + + return FALSE; +} + /* Parse an 8-bit "quarter-precision" floating point number of the form: 0baBbbbbbc defgh000 00000000 00000000. The zero and minus-zero cases need special handling, since they can't be @@ -6417,6 +6444,7 @@ enum operand_parse_code OP_RNDQ_I0, /* Neon D or Q reg, or immediate zero. */ OP_RVSD_I0, /* VFP S or D reg, or immediate zero. */ + OP_RSVD_FI0, /* VFP S or D reg, or floating point immediate zero. */ OP_RR_RNSC, /* ARM reg or Neon scalar. */ OP_RNSDQ_RNSC, /* Vector S, D or Q reg, or Neon scalar. */ OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */ @@ -6700,6 +6728,22 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) po_reg_or_goto (REG_TYPE_VFSD, try_imm0); break; + case OP_RSVD_FI0: + { + po_reg_or_goto (REG_TYPE_VFSD, try_ifimm0); + break; + try_ifimm0: + if (parse_ifimm_zero (&str)) + inst.operands[i].imm = 0; + else + { + inst.error + = _("only floating point zero is allowed as immediate value"); + goto failure; + } + } + break; + case OP_RR_RNSC: { po_scalar_or_goto (8, try_rr); @@ -19543,8 +19587,8 @@ static const struct asm_opcode insns[] = nCE(vnmul, _vnmul, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), nCE(vnmla, _vnmla, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), nCE(vnmls, _vnmls, 3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul), - nCE(vcmp, _vcmp, 2, (RVSD, RVSD_I0), vfp_nsyn_cmp), - nCE(vcmpe, _vcmpe, 2, (RVSD, RVSD_I0), vfp_nsyn_cmp), + nCE(vcmp, _vcmp, 2, (RVSD, RSVD_FI0), vfp_nsyn_cmp), + nCE(vcmpe, _vcmpe, 2, (RVSD, RSVD_FI0), vfp_nsyn_cmp), NCE(vpush, 0, 1, (VRSDLST), vfp_nsyn_push), NCE(vpop, 0, 1, (VRSDLST), vfp_nsyn_pop), NCE(vcvtz, 0, 2, (RVSD, RVSD), vfp_nsyn_cvtz), diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 79aad549764..ad41e0ffd04 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2014-08-20 Kyrylo Tkachov + + * gas/arm/ual-vcmp.s: New file. + * gas/arm/ual-vcmp.d: Likewise. + * gas/arm/vcmp-zero-bad.s: Likewise. + * gas/arm/vcmp-zero-bad.d: Likewise. + * gas/arm/vcmp-zero-bad.l: Likewise. + 2014-08-13 Mike Frysinger * gas/bfin/parallel_illegal.d: Add missing semicolons. diff --git a/gas/testsuite/gas/arm/ual-vcmp.d b/gas/testsuite/gas/arm/ual-vcmp.d new file mode 100644 index 00000000000..2e9fb3d5076 --- /dev/null +++ b/gas/testsuite/gas/arm/ual-vcmp.d @@ -0,0 +1,24 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: UAL vcmp with 0 +#as: -mfpu=vfpv3 + +.*: +file format .*arm.* + + +Disassembly of section .text: +0+000 <[^>]*> eeb50a40 vcmp.f32 s0, #0.0 +0+004 <[^>]*> eef50a40 vcmp.f32 s1, #0.0 +0+008 <[^>]*> eef51ac0 vcmpe.f32 s3, #0.0 +0+00c <[^>]*> eeb52ac0 vcmpe.f32 s4, #0.0 +0+010 <[^>]*> eef52a40 vcmp.f32 s5, #0.0 +0+014 <[^>]*> eeb53a40 vcmp.f32 s6, #0.0 +0+018 <[^>]*> eef53ac0 vcmpe.f32 s7, #0.0 +0+01c <[^>]*> eeb54ac0 vcmpe.f32 s8, #0.0 +0+020 <[^>]*> eeb50b40 vcmp.f64 d0, #0.0 +0+024 <[^>]*> eeb51b40 vcmp.f64 d1, #0.0 +0+028 <[^>]*> eeb52bc0 vcmpe.f64 d2, #0.0 +0+02c <[^>]*> eeb53bc0 vcmpe.f64 d3, #0.0 +0+030 <[^>]*> eeb54b40 vcmp.f64 d4, #0.0 +0+034 <[^>]*> eeb55b40 vcmp.f64 d5, #0.0 +0+038 <[^>]*> eeb56bc0 vcmpe.f64 d6, #0.0 +0+03c <[^>]*> eeb57bc0 vcmpe.f64 d7, #0.0 \ No newline at end of file diff --git a/gas/testsuite/gas/arm/ual-vcmp.s b/gas/testsuite/gas/arm/ual-vcmp.s new file mode 100644 index 00000000000..79efa4e79a5 --- /dev/null +++ b/gas/testsuite/gas/arm/ual-vcmp.s @@ -0,0 +1,21 @@ +.text +.arm +.syntax unified + +vcmp.f32 s0, #0.0 +vcmp.f32 s1, #0 +vcmpe.f32 s3, #0.0 +vcmpe.f32 s4, #0 +vcmp.f32 s5, #0.0e2 +vcmp.f32 s6, #0e-3 +vcmpe.f32 s7, #0.0000 +vcmpe.f32 s8, #.0 + +vcmp.f64 d0, #0.0 +vcmp.f64 d1, #0 +vcmpe.f64 d2, #0.0 +vcmpe.f64 d3, #0 +vcmp.f64 d4, #0.0e5 +vcmp.f64 d5, #0e-2 +vcmpe.f64 d6, #0.00 +vcmpe.f64 d7, #.0 diff --git a/gas/testsuite/gas/arm/vcmp-zero-bad.d b/gas/testsuite/gas/arm/vcmp-zero-bad.d new file mode 100644 index 00000000000..806cf00f656 --- /dev/null +++ b/gas/testsuite/gas/arm/vcmp-zero-bad.d @@ -0,0 +1,4 @@ +# name: UAL vcmp with #0.0 bad instructions. +# as: -mfpu=vfpv3 +# source: vcmp-zero-bad.s +# error-output: vcmp-zero-bad.l diff --git a/gas/testsuite/gas/arm/vcmp-zero-bad.l b/gas/testsuite/gas/arm/vcmp-zero-bad.l new file mode 100644 index 00000000000..975d02b8c07 --- /dev/null +++ b/gas/testsuite/gas/arm/vcmp-zero-bad.l @@ -0,0 +1,8 @@ +[^:]*: Assembler messages: +[^:]*:5: Error: only floating point zero is allowed as immediate value -- `vcmp.f32 s0,#0.01' +[^:]*:6: Error: only floating point zero is allowed as immediate value -- `vcmp.f32 s1,#2' +[^:]*:7: Error: only floating point zero is allowed as immediate value -- `vcmpe.f32 s3,5' +[^:]*:8: Error: only floating point zero is allowed as immediate value -- `vcmpe.f32 s4,#-0.0' +[^:]*:10: Error: only floating point zero is allowed as immediate value -- `vcmp.f64 d0,#-1' +[^:]*:11: Error: garbage following instruction -- `vcmpe.f64 d3,#0x35' +[^:]*:12: Error: only floating point zero is allowed as immediate value -- `vcmpe.f64 d4,0xf' diff --git a/gas/testsuite/gas/arm/vcmp-zero-bad.s b/gas/testsuite/gas/arm/vcmp-zero-bad.s new file mode 100644 index 00000000000..3be79cba839 --- /dev/null +++ b/gas/testsuite/gas/arm/vcmp-zero-bad.s @@ -0,0 +1,12 @@ +.text +.arm +.syntax unified + +vcmp.f32 s0, #0.01 +vcmp.f32 s1, #2 +vcmpe.f32 s3, 5 +vcmpe.f32 s4, #-0.0 + +vcmp.f64 d0, #-1 +vcmpe.f64 d3, #0x35 +vcmpe.f64 d4, 0xf -- 2.30.2