OSDN Git Service

* i386.c (incdec_operand): Accept only 1 and -1.
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index 0e85a5a..2bf0fe7 100644 (file)
 #include "output.h"
 #include "basic-block.h"
 #include "varray.h"
+#include "reload.h"
 
 #ifdef STACK_REGS
 
@@ -557,7 +558,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;
@@ -657,7 +662,20 @@ check_asm_stack_operands (insn)
            malformed_asm = 1;
          }
         else
-         reg_used_as_output[REGNO (recog_data.operand[i])] = 1;
+         {
+           int j;
+
+           for (j = 0; j < n_clobbers; j++)
+             if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
+               {
+                 error_for_asm (insn, "Output constraint %d cannot be specified together with \"%s\" clobber",
+                                i, reg_names [REGNO (clobber_reg[j])]);
+                 malformed_asm = 1;
+                 break;
+               }
+           if (j == n_clobbers)
+             reg_used_as_output[REGNO (recog_data.operand[i])] = 1;
+         }
       }
 
 
@@ -902,6 +920,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)
@@ -969,6 +1004,7 @@ emit_swap_insn (insn, regstack, reg)
       while (tmp != limit)
        {
          if (GET_CODE (tmp) == CODE_LABEL
+             || GET_CODE (tmp) == CALL_INSN
              || NOTE_INSN_BASIC_BLOCK_P (tmp)
              || (GET_CODE (tmp) == INSN
                  && stack_regs_mentioned (tmp)))
@@ -1125,9 +1161,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));
@@ -1443,6 +1482,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;
@@ -1450,7 +1498,7 @@ subst_stack_regs_pat (insn, regstack, pat)
 
     case SET:
       {
-       rtx *src1 = (rtx *) NULL_PTR, *src2;
+       rtx *src1 = (rtx *) 0, *src2;
        rtx src1_note, src2_note;
        rtx pat_src;
 
@@ -2553,10 +2601,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