OSDN Git Service

update
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index ab3ded6..ab400c5 100644 (file)
@@ -166,6 +166,7 @@ Boston, MA 02111-1307, USA.  */
 #include "hard-reg-set.h"
 #include "flags.h"
 #include "insn-flags.h"
+#include "toplev.h"
 
 #ifdef STACK_REGS
 
@@ -237,6 +238,7 @@ extern rtx forced_labels;
 
 static void mark_regs_pat              PROTO((rtx, HARD_REG_SET *));
 static void straighten_stack           PROTO((rtx, stack));
+static void pop_stack                  PROTO((stack, int));
 static void record_label_references    PROTO((rtx, rtx));
 static rtx *get_true_reg               PROTO((rtx *));
 static int constrain_asm_operands      PROTO((int, rtx *, char **, int *,
@@ -637,9 +639,14 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
      already guaranteed that all operands have the same number of
      alternatives.  */
 
-  n_alternatives = 1;
-  for (q = constraints[0]; *q; q++)
-    n_alternatives += (*q == ',');
+  if (n_operands == 0)
+    n_alternatives = 0;
+  else
+    {
+      n_alternatives = 1;
+      for (q = constraints[0]; *q; q++)
+       n_alternatives += (*q == ',');
+    }
 
   this_alternative = 0;
   while (this_alternative < n_alternatives)
@@ -2337,6 +2344,15 @@ subst_stack_regs_pat (insn, regstack, pat)
       case IF_THEN_ELSE:
        /* This insn requires the top of stack to be the destination. */
 
+       /* If the comparison operator is an FP comparison operator,
+          it is handled correctly by compare_for_stack_reg () who
+          will move the destination to the top of stack. But if the
+          comparison operator is not an FP comparison operator, we
+          have to handle it here. */
+       if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
+           && REGNO (*dest) != regstack->reg[regstack->top])
+         emit_swap_insn (insn, regstack, *dest);       
+
        src1 = get_true_reg (&XEXP (SET_SRC (pat), 1));
        src2 = get_true_reg (&XEXP (SET_SRC (pat), 2));
 
@@ -3061,6 +3077,18 @@ convert_regs ()
            subst_stack_regs (insn, &regstack);
 
        } while (insn != block_end[block]);
+      
+      /* For all further actions, INSN needs to be the last insn in
+         this basic block.  If subst_stack_regs inserted additional
+         instructions after INSN, it is no longer the last one at
+         this point.  */
+      next = PREV_INSN (next);
+
+      /* If subst_stack_regs inserted something after a JUMP_INSN, that
+         is almost certainly a bug.  */
+      if (GET_CODE (insn) == JUMP_INSN && insn != next)
+       abort ();
+      insn = next;
 
       /* Something failed if the stack life doesn't match.  */