Fetched from Xilinx gcc git at https://github.com/Xilinx/gcc

From 23c35173490ac2d6348a668dfc9c1a6eb62171f2 Mon Sep 17 00:00:00 2001
From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
Date: Mon, 18 Jun 2012 20:18:13 +0200
Subject: [PATCH] [Patch, microblaze]: Enable DWARF exception handling support.

Changelog

2013-03-18  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
            David Holsgrove <david.holsgrove@xilinx.com>

 * common/config/microblaze/microblaze-common.c: Remove
   TARGET_EXCEPT_UNWIND_INFO definition.
 * config/microblaze/microblaze-protos.h: Add
   microblaze_eh_return prototype.
 * gcc/config/microblaze/microblaze.c: (microblaze_must_save_register,
   microblaze_expand_epilogue, microblaze_return_addr): Handle
   calls_eh_return
   (microblaze_eh_return): New function.
 * gcc/config/microblaze/microblaze.h: Define RETURN_ADDR_OFFSET,
   EH_RETURN_DATA_REGNO, MB_EH_STACKADJ_REGNUM, EH_RETURN_STACKADJ_RTX,
   ASM_PREFERRED_EH_DATA_FORMAT
 * gcc/config/microblaze/microblaze.md: Define eh_return pattern.

Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
 gcc/common/config/microblaze/microblaze-common.c |  3 ---
 gcc/config/microblaze/microblaze-protos.h        |  1 +
 gcc/config/microblaze/microblaze.c               | 29 ++++++++++++++++++++----
 gcc/config/microblaze/microblaze.h               | 15 ++++++++++++
 gcc/config/microblaze/microblaze.md              | 11 +++++++++
 5 files changed, 52 insertions(+), 7 deletions(-)

Index: b/gcc/common/config/microblaze/microblaze-common.c
===================================================================
--- a/gcc/common/config/microblaze/microblaze-common.c
+++ b/gcc/common/config/microblaze/microblaze-common.c
@@ -37,7 +37,4 @@
 #undef  TARGET_OPTION_OPTIMIZATION_TABLE
 #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table
 
-#undef TARGET_EXCEPT_UNWIND_INFO
-#define TARGET_EXCEPT_UNWIND_INFO  sjlj_except_unwind_info
-
 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
Index: b/gcc/config/microblaze/microblaze-protos.h
===================================================================
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -54,6 +54,7 @@
 extern int symbol_mentioned_p (rtx);
 extern int label_mentioned_p (rtx);
 extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx);
+extern void microblaze_eh_return (rtx op0);
 #endif  /* RTX_CODE */
 
 /* Declare functions in microblaze-c.c.  */
Index: b/gcc/config/microblaze/microblaze.c
===================================================================
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -1906,6 +1906,11 @@
   if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
     return 1;
 
+  if (crtl->calls_eh_return
+      && regno == MB_ABI_SUB_RETURN_ADDR_REGNUM) {
+    return 1;
+  }
+
   if (!crtl->is_leaf)
     {
       if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
@@ -1933,6 +1938,13 @@
 	return 1;
     }
 
+  if (crtl->calls_eh_return
+      && (regno == EH_RETURN_DATA_REGNO (0)
+          || regno == EH_RETURN_DATA_REGNO (1)))
+    {
+      return 1;
+    }
+
   return 0;
 }
 
@@ -2962,6 +2974,12 @@
       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
     }
 
+  if (crtl->calls_eh_return)
+    emit_insn (gen_addsi3 (stack_pointer_rtx,
+                           stack_pointer_rtx,
+                           gen_rtx_raw_REG (SImode,
+                                            MB_EH_STACKADJ_REGNUM)));
+
   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
 						    MB_ABI_SUB_RETURN_ADDR_REGNUM)));
 }
@@ -3256,10 +3274,13 @@
   if (count != 0)
     return NULL_RTX;
 
-  return gen_rtx_PLUS (Pmode,
-		       get_hard_reg_initial_val (Pmode,
-						 MB_ABI_SUB_RETURN_ADDR_REGNUM),
-		       GEN_INT (8));
+  return get_hard_reg_initial_val (Pmode,
+                                   MB_ABI_SUB_RETURN_ADDR_REGNUM);
+}
+
+void microblaze_eh_return (rtx op0)
+{
+  emit_insn (gen_movsi(gen_rtx_MEM(Pmode, stack_pointer_rtx), op0));
 }
 
 /* Queue an .ident string in the queue of top-level asm statements.
Index: b/gcc/config/microblaze/microblaze.h
===================================================================
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -184,6 +184,21 @@
 #define INCOMING_RETURN_ADDR_RTX  			\
   gen_rtx_REG (VOIDmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)
 
+/* Specifies the offset from INCOMING_RETURN_ADDR_RTX and the actual return PC.  */
+#define RETURN_ADDR_OFFSET (8)
+
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? MB_ABI_FIRST_ARG_REGNUM + (N) : INVALID_REGNUM)
+
+#define MB_EH_STACKADJ_REGNUM  MB_ABI_INT_RETURN_VAL2_REGNUM
+#define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, MB_EH_STACKADJ_REGNUM)
+
+/* Select a format to encode pointers in exception handling data.  CODE
+   is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
+   true if the symbol may be affected by dynamic relocations.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+  ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
+
 /* Use DWARF 2 debugging information by default.  */
 #define DWARF2_DEBUGGING_INFO
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
Index: b/gcc/config/microblaze/microblaze.md
===================================================================
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -2261,4 +2261,15 @@
   (set_attr "mode"      "SI")
   (set_attr "length"    "4")])
 
+; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+  [(use (match_operand 0 "general_operand" ""))]
+  ""
+  "
+{
+  microblaze_eh_return(operands[0]);
+  DONE;
+}")
+
 (include "sync.md")
+
