Still a lot of bogus code; just a checkpoint.
[deliverable/binutils-gdb.git] / bfd / coff-h8300.c
index 9e70b0e86e68a19c3fa9162a10f238ba59471606..6e7ba387f45a4304d1deb58ace910f449088fdf2 100644 (file)
@@ -138,7 +138,8 @@ funcvec_hash_newfunc (entry, gen_table, string)
      but it's not easily available here.  */
   if (bfd_get_mach (table->abfd) == bfd_mach_h8300)
     table->offset += 2;
-  else if (bfd_get_mach (table->abfd) == bfd_mach_h8300h)
+  else if (bfd_get_mach (table->abfd) == bfd_mach_h8300h
+          || bfd_get_mach (table->abfd) == bfd_mach_h8300s)
     table->offset += 4;
   else
     return NULL;
@@ -247,6 +248,9 @@ static reloc_howto_type howto_table[] =
 
   HOWTO (R_MOVL2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "32/24 relaxed move", false, 0x0000ffff, 0x0000ffff, false),
 
+  HOWTO (R_BCC_INV, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8 inverted", false, 0x000000ff, 0x000000ff, true),
+
+  HOWTO (R_JMP_DEL, 0, 0, 8, true, 0, complain_overflow_signed, special, "Deleted jump", false, 0x000000ff, 0x000000ff, true),
 };
 
 
@@ -255,7 +259,7 @@ static reloc_howto_type howto_table[] =
 #define SELECT_RELOC(x,howto) \
   { x.r_type = select_reloc(howto); }
 
-#define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
+#define BADMAG(x) (H8300BADMAG(x) && H8300HBADMAG(x) && H8300SBADMAG(x))
 #define H8300 1                        /* Customize coffcode.h */
 #define __A_MAGIC_SET__
 
@@ -340,6 +344,12 @@ rtype2howto (internal, dst)
     case R_MOVL2:
       internal->howto = howto_table + 17;
       break;
+    case R_BCC_INV:
+      internal->howto = howto_table + 18;
+      break;
+    case R_JMP_DEL:
+      internal->howto = howto_table + 19;
+      break;
     default:
       abort ();
       break;
@@ -387,6 +397,33 @@ reloc_processing (relent, reloc, symbols, abfd, section)
   /*  relent->section = 0;*/
 }
 
+static boolean
+h8300_symbol_address_p (abfd, input_section, address)
+     bfd *abfd;
+     asection *input_section;
+     bfd_vma address;
+{
+  asymbol **s;
+
+  s = _bfd_generic_link_get_symbols (abfd);
+  BFD_ASSERT (s != (asymbol **) NULL);
+
+  /* Search all the symbols for one in INPUT_SECTION with
+     address ADDRESS.  */
+  while (*s) 
+    {
+      asymbol *p = *s;
+      if (p->section == input_section
+         && (input_section->output_section->vma
+             + input_section->output_offset
+             + p->value) == address)
+       return true;
+      s++;
+    }    
+  return false;
+}
+
+
 /* If RELOC represents a relaxable instruction/reloc, change it into
    the relaxed reloc, notify the linker that symbol addresses
    have changed (bfd_perform_slip) and return how much the current
@@ -406,6 +443,8 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
   bfd_vma value;  
   bfd_vma dot;
   bfd_vma gap;
+  static asection *last_input_section = NULL;
+  static arelent *last_reloc = NULL;
 
   /* The address of the thing to be relocated will have moved back by 
      the size of the shrink - but we don't change reloc->address here,
@@ -413,6 +452,9 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
      uncooked section.  */
   bfd_vma address = reloc->address - shrink;
 
+  if (input_section != last_input_section)
+    last_reloc = NULL;
+
   /* Only examine the relocs which might be relaxable.  */
   switch (reloc->howto->type)
     {     
@@ -436,9 +478,45 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
   
       /* If the distance is within -128..+128 inclusive, then we can relax
         this jump.  +128 is valid since the target will move two bytes
-        this jump.  */
+        closer if we do relax this branch.  */
       if ((int)gap >= -128 && (int)gap <= 128 )
        { 
+
+         /* It's possible we may be able to eliminate this branch entirely;
+            if the previous instruction is a branch around this instruction,
+            and there's no label at this instruction, then we can reverse
+            the condition on the previous branch and eliminate this jump.
+
+              original:                        new:
+                bCC lab1                       bCC' lab2
+                jmp lab2
+               lab1:                           lab1:
+       
+            This saves 4 bytes instead of two, and should be relatively
+            common.  */
+
+         if (gap <= 126
+             && last_reloc
+             && last_reloc->howto->type == R_PCRBYTE)
+           {
+             bfd_vma last_value;
+             last_value = bfd_coff_reloc16_get_value (last_reloc, link_info,
+                                                      input_section) + 1;
+
+             if (last_value == dot + 2
+                 && last_reloc->address + 1 == reloc->address
+                 && ! h8300_symbol_address_p (abfd, input_section, dot - 2))
+               {
+                 reloc->howto = howto_table + 19;
+                 last_reloc->howto = howto_table + 18;
+                 last_reloc->sym_ptr_ptr = reloc->sym_ptr_ptr;
+                 last_reloc->addend = reloc->addend;
+                 shrink += 4;
+                 bfd_perform_slip (abfd, 4, input_section, address);
+                 break;
+               }
+           }
+
          /* Change the reloc type.  */
          reloc->howto = reloc->howto + 1;        
 
@@ -488,7 +566,8 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
       if ((bfd_get_mach (abfd) == bfd_mach_h8300
           && value >= 0xff00
           && value <= 0xffff)
-         || (bfd_get_mach (abfd) == bfd_mach_h8300h
+         || ((bfd_get_mach (abfd) == bfd_mach_h8300h
+              || bfd_get_mach (abfd) == bfd_mach_h8300s)
              && value >= 0xffff00
              && value <= 0xffffff))
        {
@@ -510,7 +589,8 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
 
       /* The address is in 0xffff00..0xffffff inclusive on the h8300h,
         then we can relax this mov.b  */
-      if (bfd_get_mach (abfd) == bfd_mach_h8300h
+      if ((bfd_get_mach (abfd) == bfd_mach_h8300h
+          || bfd_get_mach (abfd) == bfd_mach_h8300s)
          && value >= 0xffff00
          && value <= 0xffffff)
        {
@@ -552,6 +632,8 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
        break;
     }
 
+  last_reloc = reloc;
+  last_input_section = input_section;
   return shrink;
 }
 
@@ -651,7 +733,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
       /* Sanity check.  */
-      if (value < 0xff 
+      if (value <= 0xff
          || (value >= 0x0000ff00 && value <= 0x0000ffff)
          || (value >= 0x00ffff00 && value <= 0x00ffffff)
          || (value >= 0xffffff00 && value <= 0xffffffff))
@@ -659,7 +741,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
          /* Everything looks OK.  Apply the relocation and update the
             src/dst address appropriately.  */
 
-         bfd_put_8 (abfd, gap, data + dst_address);
+         bfd_put_8 (abfd, value & 0xff, data + dst_address);
          dst_address += 1;
          src_address += 1;
        }
@@ -916,6 +998,42 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
       src_address += 4;
       break;
 
+    case R_BCC_INV:
+      /* Get the address of the target of this branch.  */
+      value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+      dot = (link_order->offset 
+            + dst_address 
+            + link_order->u.indirect.section->output_section->vma) + 1;
+
+      gap = value - dot;
+
+      /* Sanity check.  */
+      if (gap < -128 || gap > 126)
+       {
+         if (! ((*link_info->callbacks->reloc_overflow)
+                (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+                 reloc->howto->name, reloc->addend, input_section->owner,
+                 input_section, reloc->address)))
+           abort ();
+       }
+
+      /* Everything looks OK.  Fix the condition in the instruction, apply
+        the relocation, and update the src/dst address appropriately.  */
+
+      bfd_put_8 (abfd, bfd_get_8 (abfd, data + dst_address - 1) ^ 1,
+                data + dst_address - 1);
+      bfd_put_8 (abfd, gap, data + dst_address);
+      dst_address++;
+      src_address++;
+
+      /* All done.  */
+      break;
+
+    case R_JMP_DEL:
+      src_address += 4;
+      break;
+
     /* An 8bit memory indirect instruction (jmp/jsr).
 
        There's several things that need to be done to handle
@@ -934,7 +1052,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
           address in the function vector table.  */
        asymbol *symbol;
        bfd_vma value;
-       char *name;
+       const char *name;
        struct funcvec_hash_entry *h;
        asection *vectors_sec = h8300_coff_hash_table (link_info)->vectors_sec;
 
@@ -1010,7 +1128,8 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
                                                  link_info,
                                                  input_section),
                      vectors_sec->contents + h->offset);
-       else if (bfd_get_mach (input_section->owner) == bfd_mach_h8300h)
+       else if (bfd_get_mach (input_section->owner) == bfd_mach_h8300h
+                || bfd_get_mach (input_section->owner) == bfd_mach_h8300s)
          bfd_put_32 (abfd,
                      bfd_coff_reloc16_get_value (reloc,
                                                  link_info,
@@ -1131,7 +1250,7 @@ h8300_bfd_link_add_symbols(abfd, info)
        {
          arelent *reloc = relocs[i];
          asymbol *symbol = *(reloc->sym_ptr_ptr);
-         char *name;
+         const char *name;
 
          /* We've got an indirect reloc.  See if we need to add it
             to the function vector table.   At this point, we have
@@ -1179,7 +1298,8 @@ h8300_bfd_link_add_symbols(abfd, info)
                     takes 2 bytes on the h8300 and 4 bytes on the h8300h.  */
                  if (bfd_get_mach (abfd) == bfd_mach_h8300)
                    h8300_coff_hash_table (info)->vectors_sec->_raw_size += 2;
-                 else if (bfd_get_mach (abfd) == bfd_mach_h8300h)
+                 else if (bfd_get_mach (abfd) == bfd_mach_h8300h
+                          || bfd_get_mach (abfd) == bfd_mach_h8300s)
                    h8300_coff_hash_table (info)->vectors_sec->_raw_size += 4;
                }
            }
This page took 0.026561 seconds and 4 git commands to generate.