+/* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note. */
+
+static void
+dwarf2out_frame_debug_def_cfa (rtx pat, const char *label)
+{
+ memset (&cfa, 0, sizeof (cfa));
+
+ switch (GET_CODE (pat))
+ {
+ case PLUS:
+ cfa.reg = REGNO (XEXP (pat, 0));
+ cfa.offset = INTVAL (XEXP (pat, 1));
+ break;
+
+ case REG:
+ cfa.reg = REGNO (pat);
+ break;
+
+ default:
+ /* Recurse and define an expression. */
+ gcc_unreachable ();
+ }
+
+ def_cfa_1 (label, &cfa);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */
+
+static void
+dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label)
+{
+ rtx src, dest;
+
+ gcc_assert (GET_CODE (pat) == SET);
+ dest = XEXP (pat, 0);
+ src = XEXP (pat, 1);
+
+ switch (GET_CODE (src))
+ {
+ case PLUS:
+ gcc_assert (REGNO (XEXP (src, 0)) == cfa.reg);
+ cfa.offset -= INTVAL (XEXP (src, 1));
+ break;
+
+ case REG:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ cfa.reg = REGNO (dest);
+ gcc_assert (cfa.indirect == 0);
+
+ def_cfa_1 (label, &cfa);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note. */
+
+static void
+dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
+{
+ HOST_WIDE_INT offset;
+ rtx src, addr, span;
+
+ src = XEXP (set, 1);
+ addr = XEXP (set, 0);
+ gcc_assert (MEM_P (addr));
+ addr = XEXP (addr, 0);
+
+ /* As documented, only consider extremely simple addresses. */
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ gcc_assert (REGNO (addr) == cfa.reg);
+ offset = -cfa.offset;
+ break;
+ case PLUS:
+ gcc_assert (REGNO (XEXP (addr, 0)) == cfa.reg);
+ offset = INTVAL (XEXP (addr, 1)) - cfa.offset;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ span = targetm.dwarf_register_span (src);
+
+ /* ??? We'd like to use queue_reg_save, but we need to come up with
+ a different flushing heuristic for epilogues. */
+ if (!span)
+ reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
+ else
+ {
+ /* We have a PARALLEL describing where the contents of SRC live.
+ Queue register saves for each piece of the PARALLEL. */
+ int par_index;
+ int limit;
+ HOST_WIDE_INT span_offset = offset;
+
+ gcc_assert (GET_CODE (span) == PARALLEL);
+
+ limit = XVECLEN (span, 0);
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ rtx elem = XVECEXP (span, 0, par_index);
+
+ reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
+ INVALID_REGNUM, span_offset);
+ span_offset += GET_MODE_SIZE (GET_MODE (elem));
+ }
+ }
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note. */
+
+static void
+dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
+{
+ rtx src, dest;
+ unsigned sregno, dregno;
+
+ src = XEXP (set, 1);
+ dest = XEXP (set, 0);
+
+ if (src == pc_rtx)
+ sregno = DWARF_FRAME_RETURN_COLUMN;
+ else
+ sregno = DWARF_FRAME_REGNUM (REGNO (src));
+
+ dregno = DWARF_FRAME_REGNUM (REGNO (dest));
+
+ /* ??? We'd like to use queue_reg_save, but we need to come up with
+ a different flushing heuristic for epilogues. */
+ reg_save (label, sregno, dregno, 0);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
+
+static void
+dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
+{
+ dw_cfi_ref cfi = new_cfi ();
+ unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg));
+
+ cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
+
+ add_fde_cfi (label, cfi);
+}
+