Hi all,

Following the transition to UAL I noticed that the %N output modifier doesn't really work. It calls fp_const_from_val to get the VFP encoding from a real value, but fp_const_from_val only supports the floating point zero constant and ICEs for all other values, making it useless for pretty much all purposes.
For example, the testcase in this patch ICEs.

With the conversion to UAL we no longer output the VFP encoded form of floating point constants but rather their natural representation. This patch makes sure that %N negates its operand properly and outputs it as a normal floating point number. It also handles operand lossage (if, for example, the user passed in a register instead of a constant).


Ok for upstream?

2014-09-02  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    * config/arm/arm.c (fp_const_from_val): Delete prototype and
    definition.
    (arm_print_operand): Don't use fp_const_from_val in the 'N' case.
    Report unsupported operand.

2014-09-02  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    * gcc.target/arm/n_output_modifier_1.c: New test.
commit 592aa40e87285c53229ccf544691611e9c78b578
Author: Kyrylo Tkachov <kyrylo.tkac...@arm.com>
Date:   Wed Aug 13 14:08:02 2014 +0100

    [ARM] Fix %N output modifier

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5f7cbb1..a48ca4e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -100,7 +100,6 @@ static void arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update
 static void arm_print_operand (FILE *, rtx, int);
 static void arm_print_operand_address (FILE *, rtx);
 static bool arm_print_operand_punct_valid_p (unsigned char code);
-static const char *fp_const_from_val (REAL_VALUE_TYPE *);
 static arm_cc get_arm_condition_code (rtx);
 static HOST_WIDE_INT int_log2 (HOST_WIDE_INT);
 static const char *output_multi_immediate (rtx *, const char *, const char *,
@@ -17534,17 +17533,6 @@ arm_reorg (void)
 
 /* Routines to output assembly language.  */
 
-/* Return string representation of passed in real value.  */
-static const char *
-fp_const_from_val (REAL_VALUE_TYPE *r)
-{
-  if (!fp_consts_inited)
-    init_fp_table ();
-
-  gcc_assert (REAL_VALUES_EQUAL (*r, value_fp0));
-  return "0";
-}
-
 /* OPERANDS[0] is the entire list of insns that constitute pop,
    OPERANDS[1] is the base register, RETURN_PC is true iff return insn
    is in the list, UPDATE is true iff the list contains explicit
@@ -21533,13 +21521,21 @@ arm_print_operand (FILE *stream, rtx x, int code)
 
     case 'N':
       {
-	REAL_VALUE_TYPE r;
-	REAL_VALUE_FROM_CONST_DOUBLE (r, x);
-	r = real_value_negate (&r);
-	fprintf (stream, "%s", fp_const_from_val (&r));
-      }
-      return;
+        if (CONST_DOUBLE_P (x))
+          {
+            char fpstr[20];
+            REAL_VALUE_TYPE r;
+
+            REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+            r = real_value_negate (&r);
+            real_to_decimal (fpstr, &r, sizeof (fpstr), 0, 1);
+            fprintf (stream, "%s", fpstr);
+          }
+        else
+          output_operand_lossage ("Unsupported operand for code '%c'", code);
 
+        return;
+      }
     /* An integer or symbol address without a preceding # sign.  */
     case 'c':
       switch (GET_CODE (x))
diff --git a/gcc/testsuite/gcc.target/arm/n_output_modifier_1.c b/gcc/testsuite/gcc.target/arm/n_output_modifier_1.c
new file mode 100644
index 0000000..e94914b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/n_output_modifier_1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_vfp_ok } */
+/* { dg-final { scan-assembler-times "-5.0e-1" 1 } } */
+
+
+int
+foo (int a)
+{
+  int result = 0;
+   __asm__ ("%0, %N1"
+            : "=r"(result)
+            : "Dt"(0.5)
+            : );
+  return result;
+}
+

Reply via email to