rx.c (rx_conditional_register_usage): Do not warn if no fixed registers are available...
authorNick Clifton <nickc@redhat.com>
Wed, 2 Dec 2009 10:59:04 +0000 (10:59 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Wed, 2 Dec 2009 10:59:04 +0000 (10:59 +0000)
        * config/rx/rx.c (rx_conditional_register_usage): Do not warn if
        no fixed registers are available for interrupt handlers.  Do not
        fix normal registers.
        (MUST_SAVE_ACC_REGISTER): New macro.
        (rx_get_stack_layout): Create a stack frame for fast interrupt
        handlers, if necessary.  Push extra registers if needed in order
        to save the accumulator.
        (rx_expand_prologue): Create a stack frame for fast interrupt
        handlers, if necessary.
        (rx_expand_builtin_mvfc): Handle the case where there is no
        target.

From-SVN: r154903

gcc/ChangeLog
gcc/config/rx/rx.c

index a28fc61..2459495 100644 (file)
@@ -1,3 +1,17 @@
+2009-12-02  Nick Clifton  <nickc@redhat.com>
+
+       * config/rx/rx.c (rx_conditional_register_usage): Do not warn if
+       no fixed registers are available for interrupt handlers.  Do not
+       fix normal registers.
+       (MUST_SAVE_ACC_REGISTER): New macro.
+       (rx_get_stack_layout): Create a stack frame for fast interrupt
+       handlers, if necessary.  Push extra registers if needed in order
+       to save the accumulator.
+       (rx_expand_prologue): Create a stack frame for fast interrupt
+       handlers, if necessary.
+       (rx_expand_builtin_mvfc): Handle the case where there is no
+       target.
+
 2009-12-01  Sebastian Pop  <sebastian.pop@amd.com>
 
        * config/i386/abmintrin.h (__lzcnt16): New.
index 14cf09b..3fb8b32 100644 (file)
@@ -887,46 +887,25 @@ rx_conditional_register_usage (void)
 
       if (use_fixed_regs)
        {
-         unsigned int switched = 0;
          unsigned int r;
 
-         /* This is for fast interrupt handlers.  Any register in
-            the range r10 to r13 (inclusive) that is currently
-            marked as fixed is now a viable, call-saved register.
-            All other registers are fixed.  */
          memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
          memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
-         
-         for (r = 1; r < 10; r++)
-           fixed_regs[r] = call_used_regs[r] = 1;
-         
+
+         /* This is for fast interrupt handlers.  Any register in
+            the range r10 to r13 (inclusive) that is currently
+            marked as fixed is now a viable, call-used register.  */     
          for (r = 10; r <= 13; r++)
            if (fixed_regs[r])
              {
                fixed_regs[r] = 0;
                call_used_regs[r] = 1;
-               ++ switched;
-             }
-           else
-             {
-               fixed_regs[r] = 1;
-               call_used_regs[r] = 1;
              }
 
-         fixed_regs[14] = call_used_regs[14] = 1;
-         fixed_regs[15] = call_used_regs[15] = 1;
-
-         if (switched == 0)
-           {
-             static bool warned = false;
-
-             if (! warned)
-               {
-                 warning (0, "no fixed registers available "
-                          "for use by fast interrupt handler");
-                 warned = true;
-               }
-           }
+         /* Mark r7 as fixed.  This is just a hack to avoid
+            altering the reg_alloc_order array so that the newly
+            freed r10-r13 registers are the preferred registers.  */
+         fixed_regs[7] = call_used_regs[7] = 1;
        }
       else
        {
@@ -1017,6 +996,11 @@ bit_count (unsigned int x)
   return (x + (x >> 16)) & 0x3f;
 }
 
+#define MUST_SAVE_ACC_REGISTER                 \
+  (TARGET_SAVE_ACC_REGISTER                    \
+   && (is_interrupt_func (NULL_TREE)           \
+       || is_fast_interrupt_func (NULL_TREE)))
+
 /* Returns either the lowest numbered and highest numbered registers that
    occupy the call-saved area of the stack frame, if the registers are
    stored as a contiguous block, or else a bitmask of the individual
@@ -1040,15 +1024,10 @@ rx_get_stack_layout (unsigned int * lowest,
   unsigned int pushed_mask;
   unsigned int unneeded_pushes;
 
-  if (is_naked_func (NULL_TREE)
-      || is_fast_interrupt_func (NULL_TREE))
+  if (is_naked_func (NULL_TREE))
     {
       /* Naked functions do not create their own stack frame.
-        Instead the programmer must do that for us.
-
-        Fast interrupt handlers use fixed registers that have
-        been epsecially released to the function, so they do
-        not need or want a stack frame.  */
+        Instead the programmer must do that for us.  */
       * lowest = 0;
       * highest = 0;
       * register_mask = 0;
@@ -1063,7 +1042,14 @@ rx_get_stack_layout (unsigned int * lowest,
          && (! call_used_regs[reg]
              /* Even call clobbered registered must
                 be pushed inside interrupt handlers.  */
-             || is_interrupt_func (NULL_TREE)))
+             || is_interrupt_func (NULL_TREE)
+             /* Likewise for fast interrupt handlers, except registers r10 -
+                r13.  These are normally call-saved, but may have been set
+                to call-used by rx_conditional_register_usage.  If so then
+                they can be used in the fast interrupt handler without
+                saving them on the stack.  */
+             || (is_fast_interrupt_func (NULL_TREE)
+                 && ! IN_RANGE (reg, 10, 13))))
        {
          if (low == 0)
            low = reg;
@@ -1078,6 +1064,18 @@ rx_get_stack_layout (unsigned int * lowest,
        fixed_reg = reg;
     }
 
+  /* If we have to save the accumulator register, make sure
+     that at least two registers are pushed into the frame.  */
+  if (MUST_SAVE_ACC_REGISTER
+      && bit_count (save_mask) < 2)
+    {
+      save_mask |= (1 << 13) | (1 << 14);
+      if (low == 0)
+       low = 13;
+      if (high == 0)
+       high = 14;
+    }
+
   /* Decide if it would be faster fill in the call-saved area of the stack
      frame using multiple PUSH instructions instead of a single PUSHM
      instruction.
@@ -1207,9 +1205,7 @@ rx_expand_prologue (void)
   rtx insn;
 
   /* Naked functions use their own, programmer provided prologues.  */
-  if (is_naked_func (NULL_TREE)
-      /* Fast interrupt functions never use the stack.  */
-      || is_fast_interrupt_func (NULL_TREE))
+  if (is_naked_func (NULL_TREE))
     return;
 
   rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
@@ -1236,13 +1232,13 @@ rx_expand_prologue (void)
       mark_frame_related (insn);
     }
 
-  if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER)
+  if (MUST_SAVE_ACC_REGISTER)
     {
       unsigned int acc_high, acc_low;
 
       /* Interrupt handlers have to preserve the accumulator
         register if so requested by the user.  Use the first
-         two pushed register as intermediaries.  */
+         two pushed registers as intermediaries.  */
       if (mask)
        {
          acc_low = acc_high = 0;
@@ -1510,7 +1506,7 @@ rx_expand_epilogue (bool is_sibcall)
        emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
                               GEN_INT (total_size)));
 
-      if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER)
+      if (MUST_SAVE_ACC_REGISTER)
        {
          unsigned int acc_low, acc_high;
 
@@ -1901,6 +1897,9 @@ rx_expand_builtin_mvfc (tree t_arg, rtx target)
   if (! CONST_INT_P (arg))
     return NULL_RTX;
 
+  if (target == NULL_RTX)
+    return NULL_RTX;
+
   if (! REG_P (target))
     target = force_reg (SImode, target);
 
@@ -2135,7 +2134,7 @@ rx_func_attr_inlinable (const_tree decl)
    a function_decl or NULL if this is an indirect call, using EXP  */
 
 static bool
-rx_function_ok_for_sibcall (tree decl, tree exp)
+rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
   /* Do not allow indirect tailcalls.  The
      sibcall patterns do not support them.  */