OSDN Git Service

* Makefile.in (ssa.o, regclass.o): Depend on $(EXPR_H).
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index 1d14a01..e31338a 100644 (file)
 #include "regs.h"
 #include "hard-reg-set.h"
 #include "flags.h"
-#include "insn-flags.h"
 #include "toplev.h"
 #include "recog.h"
 #include "output.h"
@@ -558,7 +557,11 @@ get_true_reg (pat)
          rtx subreg;
          if (FP_REG_P (subreg = SUBREG_REG (*pat)))
            {
-             *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
+             int regno_off = subreg_regno_offset (REGNO (subreg),
+                                                  GET_MODE (subreg),
+                                                  SUBREG_BYTE (*pat),
+                                                  GET_MODE (*pat));
+             *pat = FP_MODE_REG (REGNO (subreg) + regno_off,
                                  GET_MODE (subreg));
            default:
              return pat;
@@ -785,12 +788,8 @@ stack_result (decl)
   if (aggregate_value_p (DECL_RESULT (decl)))
     return 0;
 
-  result = DECL_RTL (DECL_RESULT (decl));
-  /* ?!?  What is this code supposed to do?  Can this code actually
-     trigger if we kick out aggregates above?  */
-  if (result != 0
-      && ! (GET_CODE (result) == REG
-           && REGNO (result) < FIRST_PSEUDO_REGISTER))
+  result = DECL_RTL_IF_SET (DECL_RESULT (decl));
+  if (result != 0)
     {
 #ifdef FUNCTION_OUTGOING_VALUE
       result
@@ -907,6 +906,23 @@ emit_pop_insn (insn, regstack, reg, where)
   rtx pop_insn, pop_rtx;
   int hard_regno;
 
+  /* For complex types take care to pop both halves.  These may survive in
+     CLOBBER and USE expressions.  */
+  if (COMPLEX_MODE_P (GET_MODE (reg)))
+    {
+      rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
+      rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
+
+      pop_insn = NULL_RTX;
+      if (get_hard_regnum (regstack, reg1) >= 0)
+         pop_insn = emit_pop_insn (insn, regstack, reg1, where);
+      if (get_hard_regnum (regstack, reg2) >= 0)
+         pop_insn = emit_pop_insn (insn, regstack, reg2, where);
+      if (!pop_insn)
+       abort ();
+      return pop_insn;
+    }
+
   hard_regno = get_hard_regnum (regstack, reg);
 
   if (hard_regno < FIRST_STACK_REG)
@@ -1130,9 +1146,12 @@ move_for_stack_reg (insn, regstack, pat)
             stack is not full, and then write the value to memory via
             a pop.  */
          rtx push_rtx, push_insn;
-         rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, XFmode);
+         rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src));
 
-         push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
+         if (GET_MODE (src) == TFmode)
+           push_rtx = gen_movtf (top_stack_reg, top_stack_reg);
+         else
+           push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
          push_insn = emit_insn_before (push_rtx, insn);
          REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
                                                REG_NOTES (insn));
@@ -1448,6 +1467,15 @@ subst_stack_regs_pat (insn, regstack, pat)
                    PATTERN (insn) = pat;
                    move_for_stack_reg (insn, regstack, pat);
                  }
+               if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
+                   && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1)
+                 {
+                   pat = gen_rtx_SET (VOIDmode,
+                                      FP_MODE_REG (REGNO (*dest) + 1, SFmode),
+                                      nan);
+                   PATTERN (insn) = pat;
+                   move_for_stack_reg (insn, regstack, pat);
+                 }
              }
          }
        break;
@@ -2558,10 +2586,15 @@ convert_regs_1 (file, block)
            }
        }
 
-      /* Care for EH edges specially.  The normal return path may return
-        a value in st(0), but the EH path will not, and there's no need
-        to add popping code to the edge.  */
-      if (e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
+      /* Care for non-call EH edges specially.  The normal return path have
+        values in registers.  These will be popped en masse by the unwind
+        library.  */
+      if ((e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) == EDGE_EH)
+       target_stack->top = -1;
+
+      /* Other calls may appear to have values live in st(0), but the
+        abnormal return path will not have actually loaded the values.  */
+      else if (e->flags & EDGE_ABNORMAL_CALL)
        {
          /* Assert that the lifetimes are as we expect -- one value
             live at st(0) on the end of the source block, and no