Index: c/src/lib/libcpu/powerpc/ChangeLog
===================================================================
--- c/src/lib/libcpu/powerpc/ChangeLog	(revision 58dac487fd94d18205bc17db3daa0f9b6f421cb6)
+++ c/src/lib/libcpu/powerpc/ChangeLog	(revision 10df690794041d4d9d98aa2011b26a86a71ed0c4)
@@ -1,2 +1,11 @@
+2011-01-31	Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+	* new-exceptions/bspsupport/ppc_exc.S,
+	new-exceptions/bspsupport/ppc_exc_asm_macros.h,
+	new-exceptions/bspsupport/ppc_exc_naked.S,
+	new-exceptions/bspsupport/ppc_exc_prologue.c: Branch targets are now
+	global for all minimal prologues.  Generate branch instruction in
+	minimal prologues.
+
 2011-01-31	Sebastian Huber <sebastian.huber@embedded-brains.de>
 
Index: c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc.S
===================================================================
--- c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc.S	(revision 58dac487fd94d18205bc17db3daa0f9b6f421cb6)
+++ c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc.S	(revision 10df690794041d4d9d98aa2011b26a86a71ed0c4)
@@ -67,5 +67,12 @@
 	stw	VECTOR_REGISTER, VECTOR_OFFSET(r1)
 	mflr	VECTOR_REGISTER
-	bla	wrap_auto
+
+	/*
+	 * We store the absolute branch target address here.  It will be used
+	 * to generate the branch operation in ppc_exc_make_prologue().
+	 *
+	 * We add one to request the link in the generated branch instruction.
+	 */
+	.int	ppc_exc_wrap_auto + 1
 
 	.global ppc_exc_tgpr_clr_prolog_size
@@ -88,5 +95,12 @@
 	stw	VECTOR_REGISTER, ppc_exc_vector_register_std@sdarel(r13)
 	mflr	VECTOR_REGISTER
-	bla	wrap_auto_async
+
+	/*
+	 * We store the absolute branch target address here.  It will be used
+	 * to generate the branch operation in ppc_exc_make_prologue().
+	 *
+	 * We add one to request the link in the generated branch instruction.
+	 */
+	.int	ppc_exc_wrap_auto_async + 1
 
 /******************************************************/
@@ -120,5 +134,6 @@
 
 	/* LR holds vector, VECTOR_REGISTER holds orig. LR */
-wrap_auto:
+        .global ppc_exc_wrap_auto
+ppc_exc_wrap_auto:
 	stw	FRAME_REGISTER, FRAME_OFFSET(r1)
 
@@ -139,5 +154,6 @@
 	b	wrap_no_save_frame_register_std
 
-wrap_auto_async:
+        .global ppc_exc_wrap_auto_async
+ppc_exc_wrap_auto_async:
 	stwu	r1, -EXCEPTION_FRAME_END(r1)
 	stw	FRAME_REGISTER, FRAME_OFFSET(r1)
Index: c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h
===================================================================
--- c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h	(revision 58dac487fd94d18205bc17db3daa0f9b6f421cb6)
+++ c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h	(revision 10df690794041d4d9d98aa2011b26a86a71ed0c4)
@@ -107,7 +107,10 @@
 	 */
 	li	VECTOR_REGISTER, ( \_VEC | 0xffff8000 )
-	/*	Branch (must be within 32MB)
-	 */
-	ba	wrap_\_FLVR
+
+	/*
+	 * We store the absolute branch target address here.  It will be used
+	 * to generate the branch operation in ppc_exc_make_prologue().
+	 */
+	.int	ppc_exc_wrap_\_FLVR
 
 	.endm
@@ -130,5 +133,10 @@
 	stw	VECTOR_REGISTER, VECTOR_OFFSET(r1)
 	li	VECTOR_REGISTER, \_VEC
-	ba	wrap_nopush_\_FLVR
+
+	/*
+	 * We store the absolute branch target address here.  It will be used
+	 * to generate the branch operation in ppc_exc_make_prologue().
+	 */
+	.int	ppc_exc_wrap_nopush_\_FLVR
 
 	.endm
@@ -375,10 +383,12 @@
 	.macro	WRAP _FLVR _PRI _SRR0 _SRR1 _RFI
 
-wrap_\_FLVR:
+	.global ppc_exc_wrap_\_FLVR
+ppc_exc_wrap_\_FLVR:
 
 	/* Push exception frame */
 	stwu	r1, -EXCEPTION_FRAME_END(r1)
 
-wrap_nopush_\_FLVR:
+	.global ppc_exc_wrap_nopush_\_FLVR
+ppc_exc_wrap_nopush_\_FLVR:
 
 	/* Save frame register */
Index: c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S
===================================================================
--- c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S	(revision 58dac487fd94d18205bc17db3daa0f9b6f421cb6)
+++ c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S	(revision 10df690794041d4d9d98aa2011b26a86a71ed0c4)
@@ -29,7 +29,13 @@
 	stw	VECTOR_REGISTER, VECTOR_OFFSET(r1)
 	li	VECTOR_REGISTER, 0
-	ba	wrap_naked
 
-wrap_naked:
+	/*
+	 * We store the absolute branch target address here.  It will be used
+	 * to generate the branch operation in ppc_exc_make_prologue().
+	 */
+	.int	ppc_exc_wrap_naked
+
+        .global ppc_exc_wrap_naked
+ppc_exc_wrap_naked:
 
 	/* Save scratch registers */
Index: c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c
===================================================================
--- c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c	(revision 58dac487fd94d18205bc17db3daa0f9b6f421cb6)
+++ c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c	(revision 10df690794041d4d9d98aa2011b26a86a71ed0c4)
@@ -63,4 +63,42 @@
 };
 
+static bool ppc_exc_create_branch_op(
+  unsigned vector,
+  uint32_t *prologue,
+  size_t prologue_size
+)
+{
+  static const uintptr_t BRANCH_OP_CODE = 18 << 26;
+  static const uintptr_t BRANCH_OP_LINK = 0x1;
+  static const uintptr_t BRANCH_OP_ABS = 0x2;
+  static const uintptr_t BRANCH_OP_MSK = 0x3ffffff;
+  size_t branch_op_index = prologue_size / 4 - 1;
+  uintptr_t vector_address = (uintptr_t) ppc_exc_vector_address(vector);
+  uintptr_t branch_op_address = vector_address + 4 * branch_op_index;
+
+  /* This value may have BRANCH_OP_LINK set */
+  uintptr_t target_address = prologue [branch_op_index];
+
+  uintptr_t branch_target_address = target_address - branch_op_address;
+
+  /*
+   * We prefer to use a relative branch.  This has the benefit that custom
+   * minimal prologues in a read-only area are relocatable.
+   */
+  if ((branch_target_address & ~BRANCH_OP_MSK) != 0) {
+    /* Target to far for relative branch (PC Â± 32M) */
+    if (target_address >= 0xfe000001 || target_address < 0x01fffffd) {
+      /* Can use an absolute branch */
+      branch_target_address = (target_address | BRANCH_OP_ABS) & BRANCH_OP_MSK;
+    } else {
+      return false;
+    }
+  }
+
+  prologue [branch_op_index] = BRANCH_OP_CODE | branch_target_address;
+
+  return true;
+}
+
 rtems_status_code ppc_exc_make_prologue(
   unsigned vector,
@@ -72,5 +110,4 @@
   const uint32_t *prologue_template = NULL;
   size_t prologue_template_size = 0;
-  uintptr_t vector_address = (uintptr_t) ppc_exc_vector_address(vector);
   bool fixup_vector = false;
 
@@ -105,4 +142,8 @@
     memcpy(prologue, prologue_template, prologue_template_size);
 
+    if (!ppc_exc_create_branch_op(vector, prologue, prologue_template_size)) {
+      return RTEMS_INVALID_ADDRESS;
+    }
+
     if (fixup_vector) {
       if (vector <= 0x7fffU) {
