if (debug_relocs)
printf ("writing relocation (%p) at 0x%lx type: %d\n", rel,
- input_section->output_section->vma + input_section->output_offset
- + rel->r_offset, howto->type);
+ (long) (input_section->output_section->vma + input_section->output_offset
+ + rel->r_offset), howto->type);
if (sym_diff_section != NULL)
{
BFD_ASSERT (sym_diff_section == input_section);
toaddr = sec->size;
if (debug_relocs)
printf (" deleting %d bytes between 0x%lx to 0x%lx\n",
- count, addr, toaddr);
+ count, (long) addr, (long) toaddr);
irel = elf_section_data (sec)->relocs;
irelend = irel + sec->reloc_count;
{
if (debug_relocs)
printf (" adjusting value of local symbol %s from 0x%lx ",
- name, isym->st_value);
+ name, (long) isym->st_value);
if (isym->st_value < addr + count)
isym->st_value = addr;
else
isym->st_value -= count;
if (debug_relocs)
- printf ("to 0x%lx\n", isym->st_value);
+ printf ("to 0x%lx\n", (long) isym->st_value);
}
/* Adjust the function symbol's size as well. */
else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC
asection *p;
if (debug_relocs)
printf (" adding %d words at 0x%lx\n", num_words,
- sec->output_section->vma + sec->output_offset + addr);
+ (long) (sec->output_section->vma + sec->output_offset + addr));
contents = elf_section_data (sec)->this_hdr.contents;
sec_end = sec->size;
printf (" adjusting value of local symbol %s from 0x%lx to "
"0x%lx\n", bfd_elf_string_from_elf_section
(abfd, symtab_hdr->sh_link, isym->st_name),
- isym->st_value, isym->st_value + num_bytes);
+ (long) isym->st_value, (long)(isym->st_value + num_bytes));
isym->st_value += num_bytes;
}
if (debug_relocs)
printf ("Relaxing %s (%p), output_offset: 0x%lx sec size: 0x%lx\n",
- sec->name, sec, sec->output_offset, sec->size);
+ sec->name, sec, (long) sec->output_offset, (long) sec->size);
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
if (debug_relocs)
printf (" processing reloc at 0x%lx for local sym: %s "
- "st_value: 0x%lx adj value: 0x%lx\n", sec->output_offset
- + sec->output_section->vma + irel->r_offset,
+ "st_value: 0x%lx adj value: 0x%lx\n",
+ (long) (sec->output_offset + sec->output_section->vma
+ + irel->r_offset),
bfd_elf_string_from_elf_section (abfd, symtab_hdr->sh_link,
isym->st_name),
- isym->st_value, symval);
+ (long) isym->st_value, (long) symval);
}
else
{
+ h->root.u.def.section->output_offset);
if (debug_relocs)
printf (" processing reloc at 0x%lx for global sym: %s "
- "st_value: 0x%lx adj value: 0x%lx\n", sec->output_offset
- + sec->output_section->vma + irel->r_offset,
- h->root.root.string, h->root.u.def.value, symval);
+ "st_value: 0x%lx adj value: 0x%lx\n",
+ (long) (sec->output_offset + sec->output_section->vma
+ + irel->r_offset),
+ h->root.root.string, (long) h->root.u.def.value,
+ (long) symval);
}
/* For simplicity of coding, we are going to modify the section
if (debug_relocs)
printf (" processing reloc at 0x%lx for local sym: %s "
- "st_value: 0x%lx adj value: 0x%lx\n", sec->output_offset
- + sec->output_section->vma + irel->r_offset,
+ "st_value: 0x%lx adj value: 0x%lx\n",
+ (long) (sec->output_offset + sec->output_section->vma
+ + irel->r_offset),
bfd_elf_string_from_elf_section
(abfd, symtab_hdr->sh_link, isym->st_name),
- isym->st_value, symval);
+ (long) isym->st_value, (long) symval);
}
else
{
+ h->root.u.def.section->output_offset);
if (debug_relocs)
printf (" processing reloc at 0x%lx for global sym: %s "
- "st_value: 0x%lx adj value: 0x%lx\n", sec->output_offset
- + sec->output_section->vma + irel->r_offset,
- h->root.root.string, h->root.u.def.value, symval);
+ "st_value: 0x%lx adj value: 0x%lx\n", (long)
+ (sec->output_offset + sec->output_section->vma
+ + irel->r_offset),
+ h->root.root.string, (long) h->root.u.def.value,
+ (long) symval);
}
/* For simplicity of coding, we are going to modify the section
able to relax. */
if ((long) value < 1016 && (long) value > -1016)
{
- int code2;
+ int code1, code2, opcode;
/* Get the opcode. */
code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);
- if (code2 != 0x4030)
+ if (code2 != 0x4030) /* BR -> JMP */
continue;
/* FIXME: check r4 and r3 ? */
/* FIXME: Handle 0x4010 as well ? */
if (debug_relocs)
printf (" R_MSP430_16 -> R_MSP430_10_PCREL ");
}
+ /* If we're trying to shrink a BR[A] after previously having
+ grown a JMP for this reloc, then we have a sequence like
+ this:
+ J<cond> 1f
+ BR[A]
+ 1:
+ The opcode for J<cond> has the target hard-coded as 2 words
+ ahead of the insn, instead of using a reloc.
+ This means we cannot rely on any of the helper functions to
+ update this hard-coded jump destination if we remove the
+ BR[A] insn, so we must explicitly update it here.
+ This does mean that we can remove the entire branch
+ instruction, and invert the conditional jump, saving us 4
+ bytes rather than only 2 if we detected this in the normal
+ way. */
+ code1 = bfd_get_16 (abfd, contents + irel->r_offset - 4);
+ switch (code1)
+ {
+ case 0x3802: opcode = 0x3401; break; /* Jl +2 -> Jge +1 */
+ case 0x3402: opcode = 0x3801; break; /* Jge +2 -> Jl +1 */
+ case 0x2c02: opcode = 0x2801; break; /* Jhs +2 -> Jlo +1 */
+ case 0x2802: opcode = 0x2c01; break; /* Jlo +2 -> Jhs +1 */
+ case 0x2402: opcode = 0x2001; break; /* Jeq +2 -> Jne +1 */
+ case 0x2002: opcode = 0x2401; break; /* jne +2 -> Jeq +1 */
+ case 0x3002: /* jn +2 */
+ /* FIXME: There is no direct inverse of the Jn insn. */
+ continue;
+ default:
+ /* The previous opcode does not have a hard-coded jump
+ that we added when previously relaxing, so relax the
+ current branch as normal. */
+ opcode = 0x3c00;
+ break;
+ }
if (debug_relocs)
- printf ("(shrinking with new opcode 0x3c00)\n");
-
- /* Fix the opcode right way. */
- bfd_put_16 (abfd, 0x3c00, contents + irel->r_offset - 2);
- irel->r_offset -= 2;
+ printf ("(shrinking with new opcode 0x%x)\n", opcode);
- /* Delete bytes. */
- if (!msp430_elf_relax_delete_bytes (abfd, sec,
- irel->r_offset + 2, 2))
- goto error_return;
+ if (opcode != 0x3c00)
+ {
+ /* Invert the opcode of the conditional jump. */
+ bfd_put_16 (abfd, opcode, contents + irel->r_offset - 4);
+ irel->r_offset -= 4;
+
+ /* Delete 4 bytes - the full BR insn. */
+ if (!msp430_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 2, 4))
+ goto error_return;
+ }
+ else
+ {
+ /* Fix the opcode right way. */
+ bfd_put_16 (abfd, opcode, contents + irel->r_offset - 2);
+ irel->r_offset -= 2;
+
+ /* Delete bytes. */
+ if (!msp430_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 2, 2))
+ goto error_return;
+ }
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
return TRUE;
-error_return:
+ error_return:
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
free (isymbuf);
if (contents != NULL