gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf32-msp430.c
index 67ad9584cebf329f3377303f2a42ebb54dfac5cc..59e54ecbc9ae8445063290afdbc649fddab40460 100644 (file)
@@ -746,8 +746,8 @@ msp430_final_link_relocate (reloc_howto_type *         howto,
 
   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);
@@ -1671,7 +1671,7 @@ msp430_elf_relax_delete_bytes (bfd * abfd, asection * sec, bfd_vma addr,
   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;
@@ -1721,13 +1721,13 @@ msp430_elf_relax_delete_bytes (bfd * abfd, asection * sec, bfd_vma addr,
        {
          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
@@ -1788,7 +1788,7 @@ msp430_elf_relax_add_words (bfd * abfd, asection * sec, bfd_vma addr,
   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;
@@ -1832,7 +1832,7 @@ msp430_elf_relax_add_words (bfd * abfd, asection * sec, bfd_vma addr,
          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;
       }
 
@@ -1881,7 +1881,7 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
 
   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;
 
@@ -1955,11 +1955,12 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
 
          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
        {
@@ -1983,9 +1984,11 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
                    + 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
@@ -2176,11 +2179,12 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
 
            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
          {
@@ -2204,9 +2208,11 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
                      + 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
@@ -2362,11 +2368,11 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
               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 ?  */
@@ -2391,17 +2397,65 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
                    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.  */
@@ -2433,20 +2487,17 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
        }
     }
 
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
   return TRUE;
 
-error_return:
-  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
+ error_return:
+  if (symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
   return FALSE;
This page took 0.028322 seconds and 4 git commands to generate.