OSDN Git Service

* config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Sep 2010 21:20:51 +0000 (21:20 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Sep 2010 21:20:51 +0000 (21:20 +0000)
        (TARGET_DWARF_HANDLE_FRAME_UNSPEC): New.
        (do_spill): Use REG_CFA_OFFSET.
        (ia64_expand_prologue): Use REG_CFA_ADJUST_CFA and REG_CFA_REGISTER
        as appropriate.
        (ia64_expand_epilogue): Likewise.
        (process_set): Split into ...
        (process_cfa_adjust_cfa): this,
        (process_cfa_register): this,
        (process_cfa_offset): and this new function.
        (ia64_asm_unwind_emit): Use them.  Expect REG_CFA_* notes
        instead of REG_FRAME_RELATED_EXPR.

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

gcc/ChangeLog
gcc/config/ia64/ia64.c

index ee1404f..012757e 100644 (file)
@@ -1,3 +1,18 @@
+2010-09-24  Richard Henderson  <rth@redhat.com>
+
+       * config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): New.
+       (TARGET_DWARF_HANDLE_FRAME_UNSPEC): New.
+       (do_spill): Use REG_CFA_OFFSET.
+       (ia64_expand_prologue): Use REG_CFA_ADJUST_CFA and REG_CFA_REGISTER
+       as appropriate.
+       (ia64_expand_epilogue): Likewise.
+       (process_set): Split into ...
+       (process_cfa_adjust_cfa): this,
+       (process_cfa_register): this,
+       (process_cfa_offset): and this new function.
+       (ia64_asm_unwind_emit): Use them.  Expect REG_CFA_* notes
+       instead of REG_FRAME_RELATED_EXPR.
+
 2010-09-24  Olivier Hainque  <hainque@adacore.com>
 
        * config/i386/vx-common.h (DBX_REGISTER_NUMBER): Reinstate.
index d02d2b8..61be5a4 100644 (file)
@@ -230,7 +230,6 @@ static void emit_predicate_relation_info (void);
 static void ia64_reorg (void);
 static bool ia64_in_small_data_p (const_tree);
 static void process_epilogue (FILE *, rtx, bool, bool);
-static int process_set (FILE *, rtx, rtx, bool, bool);
 
 static bool ia64_assemble_integer (rtx, unsigned int, int);
 static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
@@ -318,6 +317,8 @@ static enum machine_mode ia64_promote_function_mode (const_tree,
                                                     int);
 static void ia64_trampoline_init (rtx, tree, rtx);
 static void ia64_override_options_after_change (void);
+
+static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int);
 \f
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ia64_attribute_table[] =
@@ -527,6 +528,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
 
+#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
+#define TARGET_DWARF_HANDLE_FRAME_UNSPEC  ia64_dwarf_handle_frame_unspec
 #undef TARGET_ASM_UNWIND_EMIT
 #define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit
 #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
@@ -3035,7 +3038,7 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off,
          off = current_frame_info.total_size - cfa_off;
        }
 
-      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+      add_reg_note (insn, REG_CFA_OFFSET,
                    gen_rtx_SET (VOIDmode,
                                 gen_rtx_MEM (GET_MODE (reg),
                                              plus_constant (base, off)),
@@ -3219,6 +3222,10 @@ ia64_expand_prologue (void)
     {
       insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
+
+      /* Force the unwind info to recognize this as defining a new CFA,
+        rather than some temp register setup.  */
+      add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX);
     }
 
   if (current_frame_info.total_size != 0)
@@ -3241,13 +3248,12 @@ ia64_expand_prologue (void)
       if (! frame_pointer_needed)
        {
          RTX_FRAME_RELATED_P (insn) = 1;
-         if (GET_CODE (offset) != CONST_INT)
-           add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-                         gen_rtx_SET (VOIDmode,
-                                      stack_pointer_rtx,
-                                      gen_rtx_PLUS (DImode,
-                                                    stack_pointer_rtx,
-                                                    frame_size_rtx)));
+         add_reg_note (insn, REG_CFA_ADJUST_CFA,
+                       gen_rtx_SET (VOIDmode,
+                                    stack_pointer_rtx,
+                                    gen_rtx_PLUS (DImode,
+                                                  stack_pointer_rtx,
+                                                  frame_size_rtx)));
        }
 
       /* ??? At this point we must generate a magic insn that appears to
@@ -3275,7 +3281,11 @@ ia64_expand_prologue (void)
 
       reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
       insn = emit_move_insn (ar_unat_save_reg, reg);
-      RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0);
+      if (current_frame_info.r[reg_save_ar_unat])
+       {
+         RTX_FRAME_RELATED_P (insn) = 1;
+         add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
+       }
 
       /* Even if we're not going to generate an epilogue, we still
         need to save the register so that EH works.  */
@@ -3314,8 +3324,7 @@ ia64_expand_prologue (void)
          /* ??? Denote pr spill/fill by a DImode move that modifies all
             64 hard registers.  */
          RTX_FRAME_RELATED_P (insn) = 1;
-         add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-                       gen_rtx_SET (VOIDmode, alt_reg, reg));
+         add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
 
          /* Even if we're not going to generate an epilogue, we still
             need to save the register so that EH works.  */
@@ -3361,6 +3370,7 @@ ia64_expand_prologue (void)
          reg_emitted (reg_save_ar_lc);
          insn = emit_move_insn (alt_reg, reg);
          RTX_FRAME_RELATED_P (insn) = 1;
+         add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
 
          /* Even if we're not going to generate an epilogue, we still
             need to save the register so that EH works.  */
@@ -3387,6 +3397,7 @@ ia64_expand_prologue (void)
           reg_emitted (reg_save_b0);
          insn = emit_move_insn (alt_reg, reg);
          RTX_FRAME_RELATED_P (insn) = 1;
+         add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
 
          /* Even if we're not going to generate an epilogue, we still
             need to save the register so that EH works.  */
@@ -3677,6 +3688,7 @@ ia64_expand_epilogue (int sibcall_p)
     {
       insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL);
     }
   else if (current_frame_info.total_size)
     {
@@ -3696,13 +3708,12 @@ ia64_expand_epilogue (int sibcall_p)
                                    offset));
 
       RTX_FRAME_RELATED_P (insn) = 1;
-      if (GET_CODE (offset) != CONST_INT)
-       add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-                     gen_rtx_SET (VOIDmode,
-                                  stack_pointer_rtx,
-                                  gen_rtx_PLUS (DImode,
-                                                stack_pointer_rtx,
-                                                frame_size_rtx)));
+      add_reg_note (insn, REG_CFA_ADJUST_CFA,
+                   gen_rtx_SET (VOIDmode,
+                                stack_pointer_rtx,
+                                gen_rtx_PLUS (DImode,
+                                              stack_pointer_rtx,
+                                              frame_size_rtx)));
     }
 
   if (cfun->machine->ia64_eh_epilogue_bsp)
@@ -3713,11 +3724,12 @@ ia64_expand_epilogue (int sibcall_p)
   else
     {
       int fp = GR_REG (2);
-      /* We need a throw away register here, r0 and r1 are reserved, so r2 is the
-        first available call clobbered register.  If there was a frame_pointer
-        register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM,
-        so we have to make sure we're using the string "r2" when emitting
-        the register name for the assembler.  */
+      /* We need a throw away register here, r0 and r1 are reserved,
+        so r2 is the first available call clobbered register.  If
+        there was a frame_pointer register, we may have swapped the
+        names of r2 and HARD_FRAME_POINTER_REGNUM, so we have to make
+        sure we're using the string "r2" when emitting the register
+        name for the assembler.  */
       if (current_frame_info.r[reg_fp] 
           && current_frame_info.r[reg_fp] == GR_REG (2))
        fp = HARD_FRAME_POINTER_REGNUM;
@@ -9590,6 +9602,17 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame)
      + ARG_POINTER_CFA_OFFSET (current_function_decl));
 }
 
+/* All we need to do here is avoid a crash in the generic dwarf2
+   processing.  The real CFA definition is set up above.  */
+
+static void
+ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label),
+                               rtx ARG_UNUSED (pattern),
+                               int index)
+{
+  gcc_assert (index == UNSPECV_ALLOC);
+}
+
 /* The generic dwarf2 frame debug info generator does not define a
    separate region for the very end of the epilogue, so refrain from
    doing so in the IA64-specific code as well.  */
@@ -9619,53 +9642,19 @@ process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
                       STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
 }
 
-/* This function processes a SET pattern looking for specific patterns
-   which result in emitting an assembly directive required for unwinding.  */
+/* This function processes a SET pattern for REG_CFA_ADJUST_CFA.  */
 
-static int
-process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
+static void
+process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn,
+                       bool unwind, bool frame)
 {
-  rtx src = SET_SRC (pat);
   rtx dest = SET_DEST (pat);
-  int src_regno, dest_regno;
-
-  /* Look for the ALLOC insn.  */
-  if (GET_CODE (src) == UNSPEC_VOLATILE
-      && XINT (src, 1) == UNSPECV_ALLOC
-      && GET_CODE (dest) == REG)
-    {
-      dest_regno = REGNO (dest);
-
-      /* If this is the final destination for ar.pfs, then this must
-        be the alloc in the prologue.  */
-      if (dest_regno == current_frame_info.r[reg_save_ar_pfs])
-       {
-         if (unwind)
-           fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-       }
-      else
-       {
-         /* This must be an alloc before a sibcall.  We must drop the
-            old frame info.  The easiest way to drop the old frame
-            info is to ensure we had a ".restore sp" directive
-            followed by a new prologue.  If the procedure doesn't
-            have a memory-stack frame, we'll issue a dummy ".restore
-            sp" now.  */
-         if (current_frame_info.total_size == 0 && !frame_pointer_needed)
-           /* if haven't done process_epilogue() yet, do it now */
-           process_epilogue (asm_out_file, insn, unwind, frame);
-         if (unwind)
-           fprintf (asm_out_file, "\t.prologue\n");
-       }
-      return 1;
-    }
+  rtx src = SET_SRC (pat);
 
-  /* Look for SP = ....  */
-  if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM)
+  if (dest == stack_pointer_rtx)
     {
       if (GET_CODE (src) == PLUS)
-        {
+       {
          rtx op0 = XEXP (src, 0);
          rtx op1 = XEXP (src, 1);
          
@@ -9675,7 +9664,8 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
            {
              gcc_assert (!frame_pointer_needed);
              if (unwind)
-               fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
+               fprintf (asm_out_file,
+                        "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
                         -INTVAL (op1));
              ia64_dwarf2out_def_steady_cfa (insn, frame);
            }
@@ -9684,240 +9674,303 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
        }
       else
        {
-         gcc_assert (GET_CODE (src) == REG
-                     && REGNO (src) == HARD_FRAME_POINTER_REGNUM);
+         gcc_assert (src == hard_frame_pointer_rtx);
          process_epilogue (asm_out_file, insn, unwind, frame);
        }
+    }
+  else if (dest == hard_frame_pointer_rtx)
+    {
+      gcc_assert (src == stack_pointer_rtx);
+      gcc_assert (frame_pointer_needed);
 
-      return 1;
+      if (unwind)
+       fprintf (asm_out_file, "\t.vframe r%d\n",
+                ia64_dbx_register_number (REGNO (dest)));
+      ia64_dwarf2out_def_steady_cfa (insn, frame);
     }
+  else
+    gcc_unreachable ();
+}
 
-  /* Register move we need to look at.  */
-  if (GET_CODE (dest) == REG && GET_CODE (src) == REG)
-    {
-      src_regno = REGNO (src);
-      dest_regno = REGNO (dest);
+/* This function processes a SET pattern for REG_CFA_REGISTER.  */
 
-      switch (src_regno)
-       {
-       case BR_REG (0):
-         /* Saving return address pointer.  */
-         gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]);
-         if (unwind)
-           fprintf (asm_out_file, "\t.save rp, r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-         return 1;
+static void
+process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind)
+{
+  rtx dest = SET_DEST (pat);
+  rtx src = SET_SRC (pat);
 
-       case PR_REG (0):
-         gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]);
-         if (unwind)
-           fprintf (asm_out_file, "\t.save pr, r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-         return 1;
+  int dest_regno = REGNO (dest);
+  int src_regno = REGNO (src);
 
-       case AR_UNAT_REGNUM:
-         gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]);
-         if (unwind)
-           fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-         return 1;
+  switch (src_regno)
+    {
+    case BR_REG (0):
+      /* Saving return address pointer.  */
+      gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]);
+      if (unwind)
+       fprintf (asm_out_file, "\t.save rp, r%d\n",
+                ia64_dbx_register_number (dest_regno));
+      break;
 
-       case AR_LC_REGNUM:
-         gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]);
-         if (unwind)
-           fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-         return 1;
+    case PR_REG (0):
+      gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]);
+      if (unwind)
+       fprintf (asm_out_file, "\t.save pr, r%d\n",
+                ia64_dbx_register_number (dest_regno));
+      break;
 
-       case STACK_POINTER_REGNUM:
-         gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM
-                     && frame_pointer_needed);
-         if (unwind)
-           fprintf (asm_out_file, "\t.vframe r%d\n",
-                    ia64_dbx_register_number (dest_regno));
-         ia64_dwarf2out_def_steady_cfa (insn, frame);
-         return 1;
+    case AR_UNAT_REGNUM:
+      gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]);
+      if (unwind)
+       fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
+                ia64_dbx_register_number (dest_regno));
+      break;
 
-       default:
-         /* Everything else should indicate being stored to memory.  */
-         gcc_unreachable ();
-       }
+    case AR_LC_REGNUM:
+      gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]);
+      if (unwind)
+       fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
+                ia64_dbx_register_number (dest_regno));
+      break;
+
+    default:
+      /* Everything else should indicate being stored to memory.  */
+      gcc_unreachable ();
     }
+}
 
-  /* Memory store we need to look at.  */
-  if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
-    {
-      long off;
-      rtx base;
-      const char *saveop;
+/* This function processes a SET pattern for REG_CFA_OFFSET.  */
 
-      if (GET_CODE (XEXP (dest, 0)) == REG)
-       {
-         base = XEXP (dest, 0);
-         off = 0;
-       }
-      else
-       {
-         gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
-                     && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
-         base = XEXP (XEXP (dest, 0), 0);
-         off = INTVAL (XEXP (XEXP (dest, 0), 1));
-       }
+static void
+process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind)
+{
+  rtx dest = SET_DEST (pat);
+  rtx src = SET_SRC (pat);
+  int src_regno = REGNO (src);
+  const char *saveop;
+  HOST_WIDE_INT off;
+  rtx base;
 
-      if (base == hard_frame_pointer_rtx)
-       {
-         saveop = ".savepsp";
-         off = - off;
-       }
-      else
-       {
-         gcc_assert (base == stack_pointer_rtx);
-         saveop = ".savesp";
-       }
+  gcc_assert (MEM_P (dest));
+  if (GET_CODE (XEXP (dest, 0)) == REG)
+    {
+      base = XEXP (dest, 0);
+      off = 0;
+    }
+  else
+    {
+      gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
+                 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
+      base = XEXP (XEXP (dest, 0), 0);
+      off = INTVAL (XEXP (XEXP (dest, 0), 1));
+    }
 
-      src_regno = REGNO (src);
-      switch (src_regno)
-       {
-       case BR_REG (0):
-         gcc_assert (!current_frame_info.r[reg_save_b0]);
-         if (unwind)
-           fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
-         return 1;
+  if (base == hard_frame_pointer_rtx)
+    {
+      saveop = ".savepsp";
+      off = - off;
+    }
+  else
+    {
+      gcc_assert (base == stack_pointer_rtx);
+      saveop = ".savesp";
+    }
 
-       case PR_REG (0):
-         gcc_assert (!current_frame_info.r[reg_save_pr]);
-         if (unwind)
-           fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
-         return 1;
+  src_regno = REGNO (src);
+  switch (src_regno)
+    {
+    case BR_REG (0):
+      gcc_assert (!current_frame_info.r[reg_save_b0]);
+      if (unwind)
+       fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n",
+                saveop, off);
+      break;
 
-       case AR_LC_REGNUM:
-         gcc_assert (!current_frame_info.r[reg_save_ar_lc]);
-         if (unwind)
-           fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
-         return 1;
+    case PR_REG (0):
+      gcc_assert (!current_frame_info.r[reg_save_pr]);
+      if (unwind)
+       fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n",
+                saveop, off);
+      break;
 
-       case AR_PFS_REGNUM:
-         gcc_assert (!current_frame_info.r[reg_save_ar_pfs]);
-         if (unwind)
-           fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
-         return 1;
+    case AR_LC_REGNUM:
+      gcc_assert (!current_frame_info.r[reg_save_ar_lc]);
+      if (unwind)
+       fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n",
+                saveop, off);
+      break;
 
-       case AR_UNAT_REGNUM:
-         gcc_assert (!current_frame_info.r[reg_save_ar_unat]);
-         if (unwind)
-           fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
-         return 1;
+    case AR_PFS_REGNUM:
+      gcc_assert (!current_frame_info.r[reg_save_ar_pfs]);
+      if (unwind)
+       fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n",
+                saveop, off);
+      break;
 
-       case GR_REG (4):
-       case GR_REG (5):
-       case GR_REG (6):
-       case GR_REG (7):
-         if (unwind)
-           fprintf (asm_out_file, "\t.save.g 0x%x\n",
-                    1 << (src_regno - GR_REG (4)));
-         return 1;
+    case AR_UNAT_REGNUM:
+      gcc_assert (!current_frame_info.r[reg_save_ar_unat]);
+      if (unwind)
+       fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n",
+                saveop, off);
+      break;
 
-       case BR_REG (1):
-       case BR_REG (2):
-       case BR_REG (3):
-       case BR_REG (4):
-       case BR_REG (5):
-         if (unwind)
-           fprintf (asm_out_file, "\t.save.b 0x%x\n",
-                    1 << (src_regno - BR_REG (1)));
-         return 1;
+    case GR_REG (4):
+    case GR_REG (5):
+    case GR_REG (6):
+    case GR_REG (7):
+      if (unwind)
+       fprintf (asm_out_file, "\t.save.g 0x%x\n",
+                1 << (src_regno - GR_REG (4)));
+      break;
 
-       case FR_REG (2):
-       case FR_REG (3):
-       case FR_REG (4):
-       case FR_REG (5):
-         if (unwind)
-           fprintf (asm_out_file, "\t.save.f 0x%x\n",
-                    1 << (src_regno - FR_REG (2)));
-         return 1;
+    case BR_REG (1):
+    case BR_REG (2):
+    case BR_REG (3):
+    case BR_REG (4):
+    case BR_REG (5):
+      if (unwind)
+       fprintf (asm_out_file, "\t.save.b 0x%x\n",
+                1 << (src_regno - BR_REG (1)));
+      break;
 
-       case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
-       case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
-       case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
-       case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
-         if (unwind)
-           fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
-                    1 << (src_regno - FR_REG (12)));
-         return 1;
+    case FR_REG (2):
+    case FR_REG (3):
+    case FR_REG (4):
+    case FR_REG (5):
+      if (unwind)
+       fprintf (asm_out_file, "\t.save.f 0x%x\n",
+                1 << (src_regno - FR_REG (2)));
+      break;
 
-       default:
-         return 0;
-       }
-    }
+    case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
+    case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
+    case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
+    case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
+      if (unwind)
+       fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
+                1 << (src_regno - FR_REG (12)));
+      break;
 
-  return 0;
+    default:
+      /* ??? For some reason we mark other general registers, even those
+        we can't represent in the unwind info.  Ignore them.  */
+      break;
+    }
 }
 
-
 /* This function looks at a single insn and emits any directives
    required to unwind this insn.  */
+
 static void
 ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn)
 {
   bool unwind = (flag_unwind_tables
                 || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
   bool frame = dwarf2out_do_frame ();
+  rtx note, pat;
+  bool handled_one;
+
+  if (!unwind && !frame)
+    return;
 
-  if (unwind || frame)
+  if (NOTE_INSN_BASIC_BLOCK_P (insn))
     {
-      rtx pat;
+      last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
 
-      if (NOTE_INSN_BASIC_BLOCK_P (insn))
+      /* Restore unwind state from immediately before the epilogue.  */
+      if (need_copy_state)
        {
-         last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
-
-         /* Restore unwind state from immediately before the epilogue.  */
-         if (need_copy_state)
+         if (unwind)
            {
-             if (unwind)
-               {
-                 fprintf (asm_out_file, "\t.body\n");
-                 fprintf (asm_out_file, "\t.copy_state %d\n",
-                          cfun->machine->state_num);
-               }
-             if (IA64_CHANGE_CFA_IN_EPILOGUE)
-               ia64_dwarf2out_def_steady_cfa (insn, frame);
-             need_copy_state = false;
+             fprintf (asm_out_file, "\t.body\n");
+             fprintf (asm_out_file, "\t.copy_state %d\n",
+                      cfun->machine->state_num);
            }
+         if (IA64_CHANGE_CFA_IN_EPILOGUE)
+           ia64_dwarf2out_def_steady_cfa (insn, frame);
+         need_copy_state = false;
        }
+    }
 
-      if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
-       return;
+  if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
+    return;
+
+  /* Look for the ALLOC insn.  */
+  if (INSN_CODE (insn) == CODE_FOR_alloc)
+    {
+      rtx dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
+      int dest_regno = REGNO (dest);
 
-      pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
-      if (pat)
-       pat = XEXP (pat, 0);
+      /* If this is the final destination for ar.pfs, then this must
+        be the alloc in the prologue.  */
+      if (dest_regno == current_frame_info.r[reg_save_ar_pfs])
+       {
+         if (unwind)
+           fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+                    ia64_dbx_register_number (dest_regno));
+       }
       else
-       pat = PATTERN (insn);
+       {
+         /* This must be an alloc before a sibcall.  We must drop the
+            old frame info.  The easiest way to drop the old frame
+            info is to ensure we had a ".restore sp" directive
+            followed by a new prologue.  If the procedure doesn't
+            have a memory-stack frame, we'll issue a dummy ".restore
+            sp" now.  */
+         if (current_frame_info.total_size == 0 && !frame_pointer_needed)
+           /* if haven't done process_epilogue() yet, do it now */
+           process_epilogue (asm_out_file, insn, unwind, frame);
+         if (unwind)
+           fprintf (asm_out_file, "\t.prologue\n");
+       }
+      return;
+    }
 
-      switch (GET_CODE (pat))
-        {
-       case SET:
-         process_set (asm_out_file, pat, insn, unwind, frame);
-         break;
+  handled_one = false;
+  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+    switch (REG_NOTE_KIND (note))
+      {
+      case REG_CFA_ADJUST_CFA:
+       pat = XEXP (note, 0);
+       if (pat == NULL)
+         pat = PATTERN (insn);
+       process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame);
+       handled_one = true;
+       break;
 
-       case PARALLEL:
-         {
-           int par_index;
-           int limit = XVECLEN (pat, 0);
-           for (par_index = 0; par_index < limit; par_index++)
-             {
-               rtx x = XVECEXP (pat, 0, par_index);
-               if (GET_CODE (x) == SET)
-                 process_set (asm_out_file, x, insn, unwind, frame);
-             }
-           break;
-         }
+      case REG_CFA_OFFSET:
+       pat = XEXP (note, 0);
+       if (pat == NULL)
+         pat = PATTERN (insn);
+       process_cfa_offset (asm_out_file, pat, unwind);
+       handled_one = true;
+       break;
 
-       default:
-         gcc_unreachable ();
-       }
-    }
+      case REG_CFA_REGISTER:
+       pat = XEXP (note, 0);
+       if (pat == NULL)
+         pat = PATTERN (insn);
+       process_cfa_register (asm_out_file, pat, unwind);
+       handled_one = true;
+       break;
+
+      case REG_FRAME_RELATED_EXPR:
+      case REG_CFA_DEF_CFA:
+      case REG_CFA_EXPRESSION:
+      case REG_CFA_RESTORE:
+      case REG_CFA_SET_VDRAP:
+       /* Not used in the ia64 port.  */
+       gcc_unreachable ();
+
+      default:
+       /* Not a frame-related note.  */
+       break;
+      }
+
+  /* All REG_FRAME_RELATED_P insns, besides ALLOC, are marked with the
+     explicit action to take.  No guessing required.  */
+  gcc_assert (handled_one);
 }
 
 /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY.  */