diff -raurEbB -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/ChangeLog devo/ecos/packages/services/objloader/current/ChangeLog
--- clean/ecos/packages/services/objloader/current/ChangeLog	2005-07-08 21:14:13.000000000 +0100
+++ devo/ecos/packages/services/objloader/current/ChangeLog	2005-08-30 13:11:09.614088000 +0100
@@ -1,5 +1,10 @@
+2005-08-30  Mark Retallack  <mark.retallack@siemens.com>
+
+	* src/relocate_ppc.c: Added branch Island to allow 26bit function calls
+	* cdl/objloader.cdl: Added option to enable branch island support
+
 2005-07-08  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* include/objelf.h: Include hal_tables.h otherwise we get strange
 	linker errors.
 	* cdl/objloader.cdl: Rearranged the building of the test case.
diff -raurEbB -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/cdl/objloader.cdl devo/ecos/packages/services/objloader/current/cdl/objloader.cdl
--- clean/ecos/packages/services/objloader/current/cdl/objloader.cdl	2005-07-08 21:14:13.000000000 +0100
+++ devo/ecos/packages/services/objloader/current/cdl/objloader.cdl	2005-08-30 14:56:08.010737600 +0100
@@ -102,10 +102,20 @@
 #               puts $::cdl_header "#include <cyg/objloader/relocate_arm.h>"
 #            }
 #            compile relocate_arm.c
 #        }
         
+        cdl_option CYGPKG_SERVICES_OBJLOADER_BRANCH_ISLAND {
+            display        "Enable branch islands"
+            flavor         bool
+            active_if      { CYGBLD_OBJLOADER_ARCHITECTURE_POWERPC }
+            default_value  0
+            description    "
+               This option enables support for adding branch islands
+               when a branch is over the architectures maximum address range"
+        }        
+                
     }
  
     cdl_option CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL {
         display          "Verbosity of debug output"
         flavor           data
diff -raurEbB -u5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/services/objloader/current/src/relocate_ppc.c devo/ecos/packages/services/objloader/current/src/relocate_ppc.c
--- clean/ecos/packages/services/objloader/current/src/relocate_ppc.c	2005-07-07 11:55:13.000000000 +0100
+++ devo/ecos/packages/services/objloader/current/src/relocate_ppc.c	2005-08-30 15:15:27.968675200 +0100
@@ -63,11 +63,66 @@
 
 #include <pkgconf/objloader.h>
 #include <cyg/objloader/elf.h>
 #include <cyg/objloader/objelf.h>
 
+
+#include <cyg/infra/diag.h>
+
 #ifdef CYGPKG_HAL_POWERPC
+
+// The code block is make up of
+// the following instructions
+// NOTE: the bctrl opcode generates 0x4e, 0x80, 0x04, 0x21,
+// and we need 0x4e, 0x80, 0x04, 0x20, this will
+// leave the LR intact
+//
+//    asm volatile(
+//                "subi 1,1,8\n"
+//                "stw 3,0(1)\n"
+//                "lis 3,16386\n"
+//                "ori 3,3,8192\n"
+//                "mtctr 3\n"
+//                "lwz 3,0(1)\n"
+//                "addi 1,1,8\n"
+//                "bctrl\n"
+//                );
+//
+#ifdef CYGPKG_SERVICES_OBJLOADER_BRANCH_ISLAND
+
+static const char cyg_ldr_rel24_code[] =
+{
+    0x38, 0x21, 0xff, 0xf8,
+    0x90, 0x61, 0x00, 0x00,
+    0x3c, 0x60, 0x40, 0x02,
+    0x60, 0x63, 0x20, 0x00,
+    0x7c, 0x69, 0x03, 0xa6,
+    0x80, 0x61, 0x00, 0x00,
+    0x38, 0x21, 0x00, 0x08,
+    0x4e, 0x80, 0x04, 0x20
+};
+
+
+typedef struct
+{
+    char cayTrampoline[sizeof(cyg_ldr_rel24_code)];
+    cyg_int32 intOriginalLocation;
+    void *pNextTrampoline;
+} cyg_ldr_rel24_trampoline_type;
+
+
+// this assumes that the trampoline will be placed
+// in the same memory space as the loaded function
+// NOTE: this is a very simple linked list
+// we dont free it because we may need the entrys later
+// but we could free it!!
+static cyg_ldr_rel24_trampoline_type *cyg_ldr_rel24_trampoline_head = NULL;
+static cyg_ldr_rel24_trampoline_type *cyg_ldr_rel24_trampoline_tail = NULL;
+
+#endif // CYGPKG_SERVICES_OBJLOADER_BRANCH_ISLAND
+
+
 void
 cyg_ldr_flush_cache( void )
 {
     HAL_DCACHE_SYNC();
     HAL_ICACHE_SYNC();
@@ -77,11 +132,11 @@
 // 
 // sym_type  Type of relocation to apply,
 // mem       Address in memory to modify (relocate).
 // sym_value 
 cyg_int32 
-cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value )
+cyg_ldr_relocate( cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value)
 {
     cyg_int32  rel_offset, i;
 
     // PPC uses rela, so we have to add the addend.
     switch( sym_type )
@@ -94,12 +149,104 @@
         return 0;
     case R_PPC_ADDR16_LO:
         HAL_WRITE_UINT16( mem, _lo_( sym_value ) );
         return 0;
     case R_PPC_REL24:
+
+
+#ifdef CYGPKG_SERVICES_OBJLOADER_BRANCH_ISLAND
+        // ok, check if the user is calling more than
+        // the ppc can handle. This means that if the relative
+        // address has any of the top 6 bits set, then we need
+        // to use the trampoline
+        if ((( sym_value - mem )&0xfc000000) != 0)
+        {
+            if (cyg_ldr_rel24_trampoline_head == NULL )
+            {
+                // need to setup the list
+                cyg_ldr_rel24_trampoline_head = malloc(sizeof(cyg_ldr_rel24_trampoline_type));
+                // there may be an error here, but the rest of the code is
+                // make so that we can continue without the trampoline
+                cyg_ldr_rel24_trampoline_tail = cyg_ldr_rel24_trampoline_head;
+
+                if (cyg_ldr_rel24_trampoline_tail != NULL)
+                    memset(cyg_ldr_rel24_trampoline_tail, 0x0, sizeof(cyg_ldr_rel24_trampoline_type));
+
+            }
+
+            if (cyg_ldr_rel24_trampoline_head != NULL )
+            {
+
+                bool blnFound = false;
+
+                cyg_ldr_rel24_trampoline_type *pCurrentTrampoline;
+
+                pCurrentTrampoline = cyg_ldr_rel24_trampoline_head;
+
+                // ok, name is valid
+                // now scan the list for a matching entry
+                while((pCurrentTrampoline != NULL)&&(blnFound == false))
+                {
+                    if ((pCurrentTrampoline->intOriginalLocation != 0)&&
+                            (pCurrentTrampoline->intOriginalLocation == sym_value ))
+                    {
+                        // we have a match, so use it
+                        blnFound = true;
+                    }
+                    else
+                    {
+                        // select the next entry
+                        pCurrentTrampoline = pCurrentTrampoline->pNextTrampoline;
+                    }
+                }
+
+                // ok, did we find it?
+                if (blnFound == false)
+                {
+                    // no, so we need to alloc a new entry
+
+                    // Ok we need to construct the trampoline
+                    // this will be called instead of the function
+                    // directly and will inturn jump to the function.
+                    memcpy(&cyg_ldr_rel24_trampoline_tail->cayTrampoline[0], cyg_ldr_rel24_code, sizeof(cyg_ldr_rel24_code));
+
+                    // need to mod the address,
+                    // first to the top 16 bits
+                    cyg_ldr_rel24_trampoline_tail->cayTrampoline[10] = (char)((sym_value>>24)&0xff);
+                    cyg_ldr_rel24_trampoline_tail->cayTrampoline[11] = (char)((sym_value>>16)&0xff);
+                    // now the bottom 16 bits
+                    cyg_ldr_rel24_trampoline_tail->cayTrampoline[14] = (char)((sym_value>>8)&0xff);
+                    cyg_ldr_rel24_trampoline_tail->cayTrampoline[15] = (char)((sym_value>>0)&0xff);
+
+                    // ok, set the original location to jump to, to the
+                    // location that would of been used
+                    cyg_ldr_rel24_trampoline_tail->intOriginalLocation = sym_value;
+
+                    // ok, use this entry for the Trampoline
+                    pCurrentTrampoline = cyg_ldr_rel24_trampoline_tail;
+
+                    // now create the next entry
+                    cyg_ldr_rel24_trampoline_tail->pNextTrampoline = malloc(sizeof(cyg_ldr_rel24_trampoline_type));
+                    // set us to the next trampiline
+                    cyg_ldr_rel24_trampoline_tail = (cyg_ldr_rel24_trampoline_type*)cyg_ldr_rel24_trampoline_tail->pNextTrampoline;
+
+                    if (cyg_ldr_rel24_trampoline_tail != NULL)
+                        memset(cyg_ldr_rel24_trampoline_tail, 0x0, sizeof(cyg_ldr_rel24_trampoline_type));
+                }
+                else
+                {
+                    // we found an entry so use it
+                }
+
+                // set the location of the
+                // function to the trampoline instead
+                sym_value = (cyg_int32)&pCurrentTrampoline->cayTrampoline[0];
+            }
+        }
+#endif // CYGPKG_SERVICES_OBJLOADER_BRANCH_ISLAND
+
         // Now it is time to seek the destination address of the call.
-        // We need to do something in case the user jumps more than 16MB.
         rel_offset = ( sym_value - mem ) & 0x03FFFFFC; 
         HAL_READ_UINT32( mem, i );
         i &= 0xFC000003;
         HAL_WRITE_UINT32( mem, rel_offset | i );
         return 0;
