+ caller = find_function (isec, irela->r_offset, info);
+ if (caller->start == NULL)
+ off = irela->r_offset;
+ else
+ {
+ struct function_info *found = NULL;
+
+ /* Find the earliest piece of this function that
+ has frame adjusting instructions. We might
+ see dynamic frame adjustment (eg. for alloca)
+ in some later piece, but functions using
+ alloca always set up a frame earlier. Frame
+ setup instructions are always in one piece. */
+ if (caller->lr_store != (bfd_vma) -1
+ || caller->sp_adjust != (bfd_vma) -1)
+ found = caller;
+ while (caller->start != NULL)
+ {
+ caller = caller->start;
+ if (caller->lr_store != (bfd_vma) -1
+ || caller->sp_adjust != (bfd_vma) -1)
+ found = caller;
+ }
+ if (found != NULL)
+ caller = found;
+ off = (bfd_vma) -1;
+ }
+
+ if (off > caller->sp_adjust)
+ {
+ if (off > caller->lr_store)
+ /* Only *(*sp+16) is live. */
+ lrlive = 1;
+ else
+ /* If no lr save, then we must be in a
+ leaf function with a frame.
+ lr is still live. */
+ lrlive = 4;
+ }
+ else if (off > caller->lr_store)
+ {
+ /* Between lr save and stack adjust. */
+ lrlive = 3;
+ /* This should never happen since prologues won't
+ be split here. */
+ BFD_ASSERT (0);
+ }
+ else
+ /* On entry to function. */
+ lrlive = 5;
+
+ if (stub_type != br000_ovl_stub
+ && lrlive != stub_type - br000_ovl_stub)
+ /* xgettext:c-format */
+ info->callbacks->einfo (_("%pA:0x%v lrlive .brinfo (%u) differs "
+ "from analysis (%u)\n"),
+ isec, irela->r_offset, lrlive,
+ stub_type - br000_ovl_stub);
+ }
+
+ /* If given lrlive info via .brinfo, use it. */
+ if (stub_type > br000_ovl_stub)
+ lrlive = stub_type - br000_ovl_stub;
+
+ if (ovl == 0)
+ to = (htab->ovly_entry[1]->root.u.def.value
+ + htab->ovly_entry[1]->root.u.def.section->output_offset
+ + htab->ovly_entry[1]->root.u.def.section->output_section->vma);
+
+ /* The branch that uses this stub goes to stub_addr + 4. We'll
+ set up an xor pattern that can be used by the icache manager
+ to modify this branch to go directly to its destination. */
+ g->stub_addr += 4;
+ br_dest = g->stub_addr;
+ if (irela == NULL)
+ {
+ /* Except in the case of _SPUEAR_ stubs, the branch in
+ question is the one in the stub itself. */
+ BFD_ASSERT (stub_type == nonovl_stub);
+ g->br_addr = g->stub_addr;
+ br_dest = to;
+ }
+
+ set_id = ((dest_ovl - 1) >> htab->num_lines_log2) + 1;
+ bfd_put_32 (sec->owner, (set_id << 18) | (dest & 0x3ffff),
+ sec->contents + sec->size);
+ bfd_put_32 (sec->owner, BRASL + ((to << 5) & 0x007fff80) + 75,
+ sec->contents + sec->size + 4);
+ bfd_put_32 (sec->owner, (lrlive << 29) | (g->br_addr & 0x3ffff),
+ sec->contents + sec->size + 8);
+ patt = dest ^ br_dest;
+ if (irela != NULL && ELF32_R_TYPE (irela->r_info) == R_SPU_REL16)
+ patt = (dest - g->br_addr) ^ (br_dest - g->br_addr);
+ bfd_put_32 (sec->owner, (patt << 5) & 0x007fff80,
+ sec->contents + sec->size + 12);
+
+ if (ovl == 0)
+ /* Extra space for linked list entries. */
+ sec->size += 16;
+ }
+ else
+ abort ();
+
+ sec->size += ovl_stub_size (htab->params);
+
+ if (htab->params->emit_stub_syms)
+ {
+ size_t len;
+ char *name;
+ int add;
+
+ len = 8 + sizeof (".ovl_call.") - 1;
+ if (h != NULL)
+ len += strlen (h->root.root.string);
+ else
+ len += 8 + 1 + 8;
+ add = 0;
+ if (irela != NULL)
+ add = (int) irela->r_addend & 0xffffffff;
+ if (add != 0)
+ len += 1 + 8;
+ name = bfd_malloc (len + 1);
+ if (name == NULL)
+ return FALSE;
+
+ sprintf (name, "%08x.ovl_call.", g->ovl);
+ if (h != NULL)