sparclite 86x big endian instruction / little endian data support.
authorStan Cox <scox@redhat.com>
Wed, 27 May 1998 01:06:20 +0000 (01:06 +0000)
committerStan Cox <scox@redhat.com>
Wed, 27 May 1998 01:06:20 +0000 (01:06 +0000)
bfd/ChangeLog
gas/ChangeLog
gas/config/tc-sparc.c

index 25cfacb..a903be5 100644 (file)
@@ -1,3 +1,20 @@
+Tue May 26 19:37:47 1998  Stan Cox  <scox@equinox.cygnus.com>
+
+       * elf32-sparc.c (_bfd_sparc_elf_howto_table, sparc_reloc_map,
+       elf32_sparc_relocate_section): Added R_SPARC_32LE for little
+       endian data 32 bit relocations.
+       (elf32_sparc_merge_private_bfd_data): Check if linking little
+       endian objects with big endian objects.
+       (elf32_sparc_object_p): Set bfd_mach_sparc_sparclite_le.
+       (elf32_sparc_final_write_processing): Set EF_SPARC_LEDATA in e_flags.
+
+       * libbfd.h (bfd_reloc_code_real_names): Added BFD_RELOC_SPARC_32LE.
+       * reloc.c: Same.
+       
+       * cpu-sparc.c (arch_info_struct): Added sparc:sparclite_le
+
+       * archures.c (bfd_mach_sparc_sparclite_le): New.
+       
 Thu May 21 16:59:28 1998  Nick Clifton  <nickc@cygnus.com>
 
        * peicode.h (add_data_entry): Fix precedence of operators in if ()
index db961b1..9c8ea03 100644 (file)
@@ -1,3 +1,13 @@
+Tue May 26 19:27:52 1998  Stan Cox  <scox@equinox.cygnus.com>
+
+       * config/tc-sparc.c (OPTION_LITTLE_ENDIAN_DATA): New.
+       (md_parse_option): Add for same.
+       (sparc_md_end): Set bfd_mach_sparc_sparclite_le.
+       (md_apply_fix3, tc_gen_reloc): Allow BFD_RELOC_SPARC_32LE.
+       (cons_fix_new_sparc): Added to create BFD_RELOC_SPARC_32LE.
+
+       * config/tc-sparc.h (cons_fix_new_sparc): Added.
+       
 Thu May 21 15:02:41 1998  Nick Clifton  <nickc@cygnus.com>
 
        * config/tc-arm.c (find_real_start): Relax definition of local
index a7df86c..d8541fa 100644 (file)
@@ -92,6 +92,8 @@ static int enforce_aligned_data;
 
 extern int target_big_endian;
 
+static int target_little_endian_data;
+
 /* V9 and 86x have big and little endian data, but instructions are always big
    endian.  The sparclet has bi-endian support but both data and insns have
    the same endianness.  Global `target_big_endian' is used for data.
@@ -389,6 +391,8 @@ struct option md_longopts[] = {
 #endif
 #define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
   {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
+#define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
+  {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
@@ -454,10 +458,15 @@ md_parse_option (c, arg)
 #ifdef SPARC_BIENDIAN
     case OPTION_LITTLE_ENDIAN:
       target_big_endian = 0;
+      if (default_arch_type != sparclet)
+       as_fatal ("This target does not support -EL");
+      break;
+    case OPTION_LITTLE_ENDIAN_DATA:
+      target_little_endian_data = 1;
+      target_big_endian = 0;
       if (default_arch_type != sparc86x
-         && default_arch_type != sparclet
          && default_arch_type != v9)
-       as_fatal ("This target does not support -EL");
+       as_fatal ("This target does not support --little-endian-data");
       break;
     case OPTION_BIG_ENDIAN:
       target_big_endian = 1;
@@ -593,7 +602,9 @@ md_show_usage (stream)
 #ifdef SPARC_BIENDIAN
   fprintf (stream, _("\
 -EL                    generate code for a little endian machine\n\
--EB                    generate code for a big endian machine\n"));
+-EB                    generate code for a big endian machine\n\
+--little-endian-data   generate code for a machine having big endian
+                        instructions and little endian data."));
 #endif
 }
 \f
@@ -755,6 +766,8 @@ sparc_md_end ()
        bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
       else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
        bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
+      else if (default_arch_type == sparc86x && target_little_endian_data)
+       bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclite_le);
       else
        {
          /* The sparclite is treated like a normal sparc.  Perhaps it shouldn't
@@ -2540,7 +2553,8 @@ md_apply_fix3 (fixP, value, segment)
     {
       md_number_to_chars (buf, val, 2);
     }
-  else if (fixP->fx_r_type == BFD_RELOC_32)
+  else if (fixP->fx_r_type == BFD_RELOC_32
+          || fixP->fx_r_type == BFD_RELOC_SPARC_32LE)
     {
       md_number_to_chars (buf, val, 4);
     }
@@ -2778,6 +2792,7 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_SPARC_L44:
     case BFD_RELOC_SPARC_HIX22:
     case BFD_RELOC_SPARC_LOX10:
+    case BFD_RELOC_SPARC_32LE:
       code = fixp->fx_r_type;
       break;
     default:
@@ -3420,3 +3435,27 @@ sparc_elf_final_processing ()
     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
 }
 #endif
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+   reloc for a cons.  We could use the definition there, except that
+   we want to handle little endian relocs specially.  */
+
+void
+cons_fix_new_sparc (frag, where, nbytes, exp)
+     fragS *frag;
+     int where;
+     unsigned int nbytes;
+     expressionS *exp;
+{
+  bfd_reloc_code_real_type r;
+
+  r = (nbytes == 1 ? BFD_RELOC_8 :
+       (nbytes == 2 ? BFD_RELOC_16 :
+       (nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
+
+#ifdef OBJ_ELF
+  if (target_little_endian_data && nbytes == 4)
+    r = BFD_RELOC_SPARC_32LE;
+#endif  
+  fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+}