]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* tm.texi.in (OVERLAPPING_REGISTER_NAMES): Document new macro.
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 13 Nov 2010 23:04:26 +0000 (23:04 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 13 Nov 2010 23:04:26 +0000 (23:04 +0000)
* tm.texi: Regenerated.
* output.h (decode_reg_name_and_count): Declare.
* varasm.c (decode_reg_name_and_count): New function.
(decode_reg_name): Reimplement using decode_reg_name_and_count.
* reginfo.c (fix_register): Use decode_reg_name_and_count and
iterate over all regs used.
* stmt.c (expand_asm_operands): Likewise.
* arm/aout.h (OVERLAPPING_REGISTER_NAMES): Define.
(ADDITIONAL_REGISTER_NAMES): Remove aliases that overlap
multiple machine registers.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166722 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/aout.h
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/output.h
gcc/reginfo.c
gcc/stmt.c
gcc/varasm.c

index f84d1e13119f9c129ef5d55867e6b9b1c57a8e0a..7f3b465dc6991d899bcda6c50fdb78d919fedb5e 100644 (file)
@@ -1,3 +1,17 @@
+2010-11-13  Richard Earnshaw  <rearnsha@arm.com>
+
+       * tm.texi.in (OVERLAPPING_REGISTER_NAMES): Document new macro.
+       * tm.texi: Regenerated.
+       * output.h (decode_reg_name_and_count): Declare.
+       * varasm.c (decode_reg_name_and_count): New function.
+       (decode_reg_name): Reimplement using decode_reg_name_and_count.
+       * reginfo.c (fix_register): Use decode_reg_name_and_count and 
+       iterate over all regs used.
+       * stmt.c (expand_asm_operands): Likewise.
+       * arm/aout.h (OVERLAPPING_REGISTER_NAMES): Define.
+       (ADDITIONAL_REGISTER_NAMES): Remove aliases that overlap
+       multiple machine registers.
+
 2010-11-13  Eric Botcazou  <ebotcazou@adacore.com>
 
        * stor-layout.c (place_union_field): Do not put location information
index 5abad67dd69046875639c49f2398bcbe7cab82ff..b5f7109d86833fcc0a154762734d147530fa6947 100644 (file)
   {"mvdx12", 39},                              \
   {"mvdx13", 40},                              \
   {"mvdx14", 41},                              \
-  {"mvdx15", 42},                              \
-  {"d0", 63}, {"q0", 63},                      \
-  {"d1", 65},                                  \
-  {"d2", 67}, {"q1", 67},                      \
-  {"d3", 69},                                  \
-  {"d4", 71}, {"q2", 71},                      \
-  {"d5", 73},                                  \
-  {"d6", 75}, {"q3", 75},                      \
-  {"d7", 77},                                  \
-  {"d8", 79}, {"q4", 79},                      \
-  {"d9", 81},                                  \
-  {"d10", 83}, {"q5", 83},                     \
-  {"d11", 85},                                 \
-  {"d12", 87}, {"q6", 87},                     \
-  {"d13", 89},                                 \
-  {"d14", 91}, {"q7", 91},                     \
-  {"d15", 93},                                 \
-  {"q8", 95},                                  \
-  {"q9", 99},                                  \
-  {"q10", 103},                                        \
-  {"q11", 107},                                        \
-  {"q12", 111},                                        \
-  {"q13", 115},                                        \
-  {"q14", 119},                                        \
-  {"q15", 123}                                 \
+  {"mvdx15", 42}                               \
+}
+#endif
+
+#ifndef OVERLAPPING_REGISTER_NAMES
+#define OVERLAPPING_REGISTER_NAMES             \
+{                                              \
+  {"d0", 63, 2},                               \
+  {"d1", 65, 2},                               \
+  {"d2", 67, 2},                               \
+  {"d3", 69, 2},                               \
+  {"d4", 71, 2},                               \
+  {"d5", 73, 2},                               \
+  {"d6", 75, 2},                               \
+  {"d7", 77, 2},                               \
+  {"d8", 79, 2},                               \
+  {"d9", 81, 2},                               \
+  {"d10", 83, 2},                              \
+  {"d11", 85, 2},                              \
+  {"d12", 87, 2},                              \
+  {"d13", 89, 2},                              \
+  {"d14", 91, 2},                              \
+  {"d15", 93, 2},                              \
+  {"q0", 63, 4},                               \
+  {"q1", 67, 4},                               \
+  {"q2", 71, 4},                               \
+  {"q3", 75, 4},                               \
+  {"q4", 79, 4},                               \
+  {"q5", 83, 4},                               \
+  {"q6", 87, 4},                               \
+  {"q7", 91, 4},                               \
+  {"q8", 95, 4},                               \
+  {"q9", 99, 4},                               \
+  {"q10", 103, 4},                             \
+  {"q11", 107, 4},                             \
+  {"q12", 111, 4},                             \
+  {"q13", 115, 4},                             \
+  {"q14", 119, 4},                             \
+  {"q15", 123, 4}                              \
 }
 #endif
 
index 229916da8c04a1af14b6e8ab824caed455bfc016..54465014613fce2870f3a128c17ee8ff85bbd20a 100644 (file)
@@ -8479,6 +8479,22 @@ registers, thus allowing the @code{asm} option in declarations to refer
 to registers using alternate names.
 @end defmac
 
+@defmac OVERLAPPING_REGISTER_NAMES
+If defined, a C initializer for an array of structures containing a
+name, a register number and a count of the number of consecutive
+machine registers the name overlaps.  This macro defines additional
+names for hard registers, thus allowing the @code{asm} option in
+declarations to refer to registers using alternate names.  Unlike
+@code{ADDITIONAL_REGISTER_NAMES}, this macro should be used when the
+register name implies multiple underlying registers.
+
+This macro should be used when it is important that a clobber in an
+@code{asm} statement clobbers all the underlying values implied by the
+register name.  For example, on ARM, clobbering the double-precision
+VFP register ``d0'' implies clobbering both single-precision registers
+``s0'' and ``s1''.
+@end defmac
+
 @defmac ASM_OUTPUT_OPCODE (@var{stream}, @var{ptr})
 Define this macro if you are using an unusual assembler that
 requires different names for the machine instructions.
index a9bc6044571e2370afab0c652db6f91b107a0f40..4b21c9295ff99e6d8dc83d9e74a97155f7dcde31 100644 (file)
@@ -8453,6 +8453,22 @@ registers, thus allowing the @code{asm} option in declarations to refer
 to registers using alternate names.
 @end defmac
 
+@defmac OVERLAPPING_REGISTER_NAMES
+If defined, a C initializer for an array of structures containing a
+name, a register number and a count of the number of consecutive
+machine registers the name overlaps.  This macro defines additional
+names for hard registers, thus allowing the @code{asm} option in
+declarations to refer to registers using alternate names.  Unlike
+@code{ADDITIONAL_REGISTER_NAMES}, this macro should be used when the
+register name implies multiple underlying registers.
+
+This macro should be used when it is important that a clobber in an
+@code{asm} statement clobbers all the underlying values implied by the
+register name.  For example, on ARM, clobbering the double-precision
+VFP register ``d0'' implies clobbering both single-precision registers
+``s0'' and ``s1''.
+@end defmac
+
 @defmac ASM_OUTPUT_OPCODE (@var{stream}, @var{ptr})
 Define this macro if you are using an unusual assembler that
 requires different names for the machine instructions.
index fa223d5cf7e64b8ebf20cf2741273c16769823ab..07372a388a13477e5b39f1d3899d33542366d32c 100644 (file)
@@ -177,6 +177,11 @@ extern enum tls_model decl_default_tls_model (const_tree);
    Prefixes such as % are optional.  */
 extern int decode_reg_name (const char *);
 
+/* Similar to decode_reg_name, but takes an extra parameter that is a
+   pointer to the number of (internal) registers described by the
+   external name.  */
+extern int decode_reg_name_and_count (const char *, int *);
+
 extern void assemble_alias (tree, tree);
 
 extern void default_assemble_visibility (tree, int);
index 65243cb2865b672c4fb2000238cffcea7fda5b07..86a20d31feb371b9cefb2ae7ec713222f227f5ca 100644 (file)
@@ -755,64 +755,69 @@ void
 fix_register (const char *name, int fixed, int call_used)
 {
   int i;
+  int reg, nregs;
 
   /* Decode the name and update the primary form of
      the register info.  */
 
-  if ((i = decode_reg_name (name)) >= 0)
+  if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0)
     {
-      if ((i == STACK_POINTER_REGNUM
+      gcc_assert (nregs >= 1);
+      for (i = reg; i < reg + nregs; i++)
+       {
+         if ((i == STACK_POINTER_REGNUM
 #ifdef HARD_FRAME_POINTER_REGNUM
-          || i == HARD_FRAME_POINTER_REGNUM
+              || i == HARD_FRAME_POINTER_REGNUM
 #else
-          || i == FRAME_POINTER_REGNUM
+              || i == FRAME_POINTER_REGNUM
 #endif
-          )
-         && (fixed == 0 || call_used == 0))
-       {
-         switch (fixed)
+              )
+             && (fixed == 0 || call_used == 0))
            {
-           case 0:
-             switch (call_used)
+             switch (fixed)
                {
                case 0:
-                 error ("can%'t use %qs as a call-saved register", name);
+                 switch (call_used)
+                   {
+                   case 0:
+                     error ("can%'t use %qs as a call-saved register", name);
+                     break;
+
+                   case 1:
+                     error ("can%'t use %qs as a call-used register", name);
+                     break;
+
+                   default:
+                     gcc_unreachable ();
+                   }
                  break;
 
                case 1:
-                 error ("can%'t use %qs as a call-used register", name);
+                 switch (call_used)
+                   {
+                   case 1:
+                     error ("can%'t use %qs as a fixed register", name);
+                     break;
+
+                   case 0:
+                   default:
+                     gcc_unreachable ();
+                   }
                  break;
 
                default:
                  gcc_unreachable ();
                }
-             break;
-
-           case 1:
-             switch (call_used)
-               {
-               case 1:
-                 error ("can%'t use %qs as a fixed register", name);
-                 break;
-
-               case 0:
-               default:
-                 gcc_unreachable ();
-               }
-             break;
-
-           default:
-             gcc_unreachable ();
            }
-       }
-      else
-       {
-         fixed_regs[i] = fixed;
-         call_used_regs[i] = call_used;
+         else
+           {
+             fixed_regs[i] = fixed;
+             call_used_regs[i] = call_used;
 #ifdef CALL_REALLY_USED_REGISTERS
-         if (fixed == 0)
-           call_really_used_regs[i] = call_used;
+             if (fixed == 0)
+               call_really_used_regs[i] = call_used;
 #endif
+           }
        }
     }
   else
index c8f56f5470b68dc30f5048a43f314905a44e4d5b..e24ed4ebb312b8ca4864ede10a2e464bb7fd91db 100644 (file)
@@ -687,13 +687,14 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
     {
       const char *regname;
+      int nregs;
 
       if (TREE_VALUE (tail) == error_mark_node)
        return;
       regname = TREE_STRING_POINTER (TREE_VALUE (tail));
 
-      i = decode_reg_name (regname);
-      if (i >= 0 || i == -4)
+      i = decode_reg_name_and_count (regname, &nregs);
+      if (i == -4)
        ++nclobbers;
       else if (i == -2)
        error ("unknown register name %qs in %<asm%>", regname);
@@ -701,14 +702,21 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       /* Mark clobbered registers.  */
       if (i >= 0)
         {
-         /* Clobbering the PIC register is an error.  */
-         if (i == (int) PIC_OFFSET_TABLE_REGNUM)
+         int reg;
+
+         for (reg = i; reg < i + nregs; reg++)
            {
-             error ("PIC register %qs clobbered in %<asm%>", regname);
-             return;
-           }
+             ++nclobbers;
+
+             /* Clobbering the PIC register is an error.  */
+             if (reg == (int) PIC_OFFSET_TABLE_REGNUM)
+               {
+                 error ("PIC register clobbered by %qs in %<asm%>", regname);
+                 return;
+               }
 
-         SET_HARD_REG_BIT (clobbered_regs, i);
+             SET_HARD_REG_BIT (clobbered_regs, reg);
+           }
        }
     }
 
@@ -1033,7 +1041,8 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
       for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
        {
          const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
-         int j = decode_reg_name (regname);
+         int reg, nregs;
+         int j = decode_reg_name_and_count (regname, &nregs);
          rtx clobbered_reg;
 
          if (j < 0)
@@ -1055,30 +1064,39 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
              continue;
            }
 
-         /* Use QImode since that's guaranteed to clobber just one reg.  */
-         clobbered_reg = gen_rtx_REG (QImode, j);
-
-         /* Do sanity check for overlap between clobbers and respectively
-            input and outputs that hasn't been handled.  Such overlap
-            should have been detected and reported above.  */
-         if (!clobber_conflict_found)
+         for (reg = j; reg < j + nregs; reg++)
            {
-             int opno;
-
-             /* We test the old body (obody) contents to avoid tripping
-                over the under-construction body.  */
-             for (opno = 0; opno < noutputs; opno++)
-               if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
-                 internal_error ("asm clobber conflict with output operand");
-
-             for (opno = 0; opno < ninputs - ninout; opno++)
-               if (reg_overlap_mentioned_p (clobbered_reg,
-                                            ASM_OPERANDS_INPUT (obody, opno)))
-                 internal_error ("asm clobber conflict with input operand");
-           }
+             /* Use QImode since that's guaranteed to clobber just
+              * one reg.  */
+             clobbered_reg = gen_rtx_REG (QImode, reg);
+
+             /* Do sanity check for overlap between clobbers and
+                respectively input and outputs that hasn't been
+                handled.  Such overlap should have been detected and
+                reported above.  */
+             if (!clobber_conflict_found)
+               {
+                 int opno;
+
+                 /* We test the old body (obody) contents to avoid
+                    tripping over the under-construction body.  */
+                 for (opno = 0; opno < noutputs; opno++)
+                   if (reg_overlap_mentioned_p (clobbered_reg,
+                                                output_rtx[opno]))
+                     internal_error
+                       ("asm clobber conflict with output operand");
+
+                 for (opno = 0; opno < ninputs - ninout; opno++)
+                   if (reg_overlap_mentioned_p (clobbered_reg,
+                                                ASM_OPERANDS_INPUT (obody,
+                                                                    opno)))
+                     internal_error
+                       ("asm clobber conflict with input operand");
+               }
 
-         XVECEXP (body, 0, i++)
-           = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
+             XVECEXP (body, 0, i++)
+               = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
+           }
        }
 
       if (nlabels > 0)
index 0c80c931fff5a67779205ce0d637b2d2cbc95fac..215e0edbd5927b37fa3121d988a66be9a0f1c66e 100644 (file)
@@ -764,8 +764,11 @@ set_user_assembler_name (tree decl, const char *name)
    Prefixes such as % are optional.  */
 
 int
-decode_reg_name (const char *asmspec)
+decode_reg_name_and_count (const char *asmspec, int *pnregs)
 {
+  /* Presume just one register is clobbered.  */
+  *pnregs = 1;
+
   if (asmspec != 0)
     {
       int i;
@@ -791,6 +794,25 @@ decode_reg_name (const char *asmspec)
            && ! strcmp (asmspec, strip_reg_name (reg_names[i])))
          return i;
 
+#ifdef OVERLAPPING_REGISTER_NAMES
+      {
+       static const struct
+       {
+         const char *const name;
+         const int number;
+         const int nregs;
+       } table[] = OVERLAPPING_REGISTER_NAMES;
+
+       for (i = 0; i < (int) ARRAY_SIZE (table); i++)
+         if (table[i].name[0]
+             && ! strcmp (asmspec, table[i].name))
+           {
+             *pnregs = table[i].nregs;
+             return table[i].number;
+           }
+      }
+#endif /* OVERLAPPING_REGISTER_NAMES */
+
 #ifdef ADDITIONAL_REGISTER_NAMES
       {
        static const struct { const char *const name; const int number; } table[]
@@ -814,6 +836,14 @@ decode_reg_name (const char *asmspec)
 
   return -1;
 }
+
+int
+decode_reg_name (const char *name)
+{
+  int count;
+  return decode_reg_name_and_count (name, &count);
+}
+
 \f
 /* Return true if DECL's initializer is suitable for a BSS section.  */