* config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to
authorIan Lance Taylor <ian@airs.com>
Fri, 8 Oct 1993 20:01:10 +0000 (20:01 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 8 Oct 1993 20:01:10 +0000 (20:01 +0000)
hold register masks.
(md_begin): Initialize them to zero.
(append_insn): Update mips_gprmask and mips_cprmask.  Also add
register variables pinfo and prev_pinfo.
* config/tc-mips.h (mips_gprmask, mips_cprmask): Declare.
* config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask
and cprmask from mips_gprmask and mips_cprmask.

gas/ChangeLog
gas/config/obj-ecoff.c
gas/config/tc-mips.c
gas/config/tc-mips.h

index cdca726db0ba4f8a607f7f440dc86e5b0c617188..dcd4506ee26251467468ebf624d857d34aee9439 100644 (file)
@@ -1,5 +1,14 @@
 Fri Oct  8 14:09:35 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
+       * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to
+       hold register masks.
+       (md_begin): Initialize them to zero.
+       (append_insn): Update mips_gprmask and mips_cprmask.  Also add
+       register variables pinfo and prev_pinfo.
+       * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare.
+       * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask
+       and cprmask from mips_gprmask and mips_cprmask.
+
        * config/tc-mips.h: Define TARGET_FORMAT if OBJ_ELF.
        * config/tc-mips.c (GPOPT): Define if OBJ_ECOFF or OBJ_ELF.
        (various): Change all references to GP references to apply if
index 0006c2d1c9c6d5484fe0361e2131e1af4d1a2174..5e66e3a7d4fe3384c387024bc1e6756e7e42bbaf 100644 (file)
@@ -1449,7 +1449,6 @@ static void obj_ecoff_size PARAMS ((int));
 static void obj_ecoff_tag PARAMS ((int));
 static void obj_ecoff_type PARAMS ((int));
 static void obj_ecoff_val PARAMS ((int));
-static void obj_ecoff_stab PARAMS ((int));
 static void obj_ecoff_ent PARAMS ((int));
 static void obj_ecoff_begin PARAMS ((int));
 static void obj_ecoff_bend PARAMS ((int));
@@ -1460,28 +1459,32 @@ static void obj_ecoff_loc PARAMS ((int));
 static void obj_ecoff_mask PARAMS ((int));
 static void mark_stabs PARAMS ((int));
 static char *ecoff_add_bytes PARAMS ((char **buf, char **bufend,
-                                     char *bufptr, long need));
-static long ecoff_padding_adjust PARAMS ((char **buf, char **bufend,
-                                          long offset, char **bufptrptr));
-static long ecoff_build_lineno PARAMS ((char **buf, char **bufend,
-                                       long offset, long *linecntptr));
-static long ecoff_build_symbols PARAMS ((char **buf, char **bufend,
-                                        long offset,
-                                        char **extbuf, char **extbufend,
-                                        long *extoffset,
-                                        varray_t *ext_strings,
-                                        struct hash_control *ext_str_hash));
-static long ecoff_build_procs PARAMS ((char **buf, char **bufend,
-                                      long offset));
-static long ecoff_build_aux PARAMS ((char **buf, char **bufend,
-                                    long offset));
-static long ecoff_build_strings PARAMS ((char **buf, char **bufend,
-                                        long offset,
-                                        varray_t *vp));
-static long ecoff_build_ss PARAMS ((char **buf, char **bufend,
-                                    long offset));
-static long ecoff_build_fdr PARAMS ((char **buf, char **bufend,
-                                    long offset));
+                                     char *bufptr, unsigned long need));
+static unsigned long ecoff_padding_adjust PARAMS ((char **buf,
+                                                  char **bufend,
+                                                  unsigned long offset,
+                                                  char **bufptrptr));
+static unsigned long ecoff_build_lineno PARAMS ((char **buf, char **bufend,
+                                                unsigned long offset,
+                                                long *linecntptr));
+static unsigned long ecoff_build_symbols PARAMS ((char **buf, char **bufend,
+                                                 unsigned long offset,
+                                                 char **extbuf,
+                                                 char **extbufend,
+                                                 unsigned long *extoffset,
+                                                 varray_t *ext_strings,
+                                                 struct hash_control *));
+static unsigned long ecoff_build_procs PARAMS ((char **buf, char **bufend,
+                                               unsigned long offset));
+static unsigned long ecoff_build_aux PARAMS ((char **buf, char **bufend,
+                                             unsigned long offset));
+static unsigned long ecoff_build_strings PARAMS ((char **buf, char **bufend,
+                                                 unsigned long offset,
+                                                 varray_t *vp));
+static unsigned long ecoff_build_ss PARAMS ((char **buf, char **bufend,
+                                            unsigned long offset));
+static unsigned long ecoff_build_fdr PARAMS ((char **buf, char **bufend,
+                                             unsigned long offset));
 static page_t *allocate_cluster PARAMS ((unsigned long npages));
 static page_t *allocate_page PARAMS ((void));
 static scope_t *allocate_scope PARAMS ((void));
@@ -1540,11 +1543,6 @@ const pseudo_typeS obj_pseudo_table[] =
   { "type",    obj_ecoff_type,         0 },
   { "val",     obj_ecoff_val,          0 },
 
-  /* stabs debugging information.  */
-  { "stabd",   obj_ecoff_stab,         'd' },
-  { "stabn",   obj_ecoff_stab,         'n' },
-  { "stabs",   obj_ecoff_stab,         's' },
-
   /* ECOFF specific debugging information.  */
   { "begin",   obj_ecoff_begin,        0 },
   { "bend",    obj_ecoff_bend,         0 },
@@ -1634,7 +1632,7 @@ add_string (vp, hash_tbl, str, ret_hash)
   hash_ptr = (shash_t *) hash_find (hash_tbl, str);
   if (hash_ptr == (shash_t *) NULL)
     {
-      register char *err;
+      register const char *err;
 
       if (vp->objects_last_page + len >= PAGE_USIZE)
         {
@@ -1654,7 +1652,7 @@ add_string (vp, hash_tbl, str, ret_hash)
       strcpy (hash_ptr->string, str);
 
       err = hash_insert (hash_tbl, str, (char *) hash_ptr);
-      if (*err != '\0')
+      if (err)
        as_fatal ("Inserting \"%s\" into string hash table: %s",
                  str, err);
     }
@@ -2085,7 +2083,7 @@ get_tag (tag, sym, basic_type)
      bt_t basic_type;                  /* bt_Struct, bt_Union, or bt_Enum */
 {
   shash_t *hash_ptr;
-  char *err;
+  const char *err;
   tag_t *tag_ptr;
 
   if (cur_file_ptr == (efdr_t *) NULL)
@@ -2110,11 +2108,11 @@ get_tag (tag, sym, basic_type)
     {
       char *perm;
 
-      perm = xmalloc (strlen (tag) + 1);
+      perm = xmalloc ((unsigned long) (strlen (tag) + 1));
       strcpy (perm, tag);
       hash_ptr = allocate_shash ();
       err = hash_insert (tag_hash, perm, (char *) hash_ptr);
-      if (*err != '\0')
+      if (err)
        as_fatal ("Inserting \"%s\" into tag hash table: %s",
                  tag, err);
       hash_ptr->string = perm;
@@ -2127,7 +2125,7 @@ get_tag (tag, sym, basic_type)
   tag_ptr->basic_type  = basic_type;
   tag_ptr->sym         = sym;
   tag_ptr->ifd         = ((sym == (localsym_t *) NULL)
-                          ? -1
+                          ? (symint_t) -1
                           : cur_file_ptr->file_index);
   tag_ptr->same_block  = cur_tag_head->first_tag;
 
@@ -2284,7 +2282,8 @@ add_file (file_name, indx)
     {
       (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
                               symbol_new ("L0\001", now_seg,
-                                          frag_now_fix (), frag_now),
+                                          (valueT) frag_now_fix (),
+                                          frag_now),
                               0, ECOFF_MARK_STAB (N_SOL));
       return;
     }
@@ -2525,7 +2524,7 @@ static sc_t coff_storage_class;
 static st_t coff_symbol_typ;
 static int coff_is_function;
 static char *coff_tag;
-static long coff_value;        /* FIXME: Might be 64 bits.  */
+static valueT coff_value;
 symbolS *coff_sym_value;
 static int coff_inside_enumeration;
 
@@ -2553,7 +2552,7 @@ obj_ecoff_def (ignore)
        free (coff_sym_name);
       if (coff_tag != (char *) NULL)
        free (coff_tag);
-      coff_sym_name = (char *) xmalloc (strlen (name) + 1);
+      coff_sym_name = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
       strcpy (coff_sym_name, name);
       coff_type = type_info_init;
       coff_storage_class = sc_Nil;
@@ -2781,7 +2780,7 @@ obj_ecoff_tag (ignore)
   name = input_line_pointer;
   name_end = get_symbol_end ();
 
-  coff_tag = (char *) xmalloc (strlen (name) + 1);
+  coff_tag = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
   strcpy (coff_tag, name);
 
   *input_line_pointer = name_end;
@@ -2984,7 +2983,7 @@ obj_ecoff_endef (ignore)
                          coff_symbol_typ,
                          coff_storage_class,
                          coff_sym_value,
-                         coff_value,
+                         (symint_t) coff_value,
                          indx);
 
   /* deal with struct, union, and enum tags.  */
@@ -3053,7 +3052,8 @@ obj_ecoff_end (ignore)
   else
     (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
                             symbol_new ("L0\001", now_seg,
-                                        frag_now_fix (), frag_now),
+                                        (valueT) frag_now_fix (),
+                                        frag_now),
                             (symint_t) 0, (symint_t) 0);
 
   cur_proc_ptr = (proc_t *) NULL;
@@ -3226,7 +3226,7 @@ obj_ecoff_loc (ignore)
      int ignore;
 {
   lineno_list_t *list;
-  int lineno;
+  symint_t lineno;
 
   if (cur_file_ptr == (efdr_t *) NULL)
     {
@@ -3260,7 +3260,8 @@ obj_ecoff_loc (ignore)
     {
       (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
                               symbol_new ("L0\001", now_seg,
-                                          frag_now_fix (), frag_now),
+                                          (valueT) frag_now_fix (),
+                                          frag_now),
                               0, lineno);
       return;
     }
@@ -3309,13 +3310,16 @@ mark_stabs (ignore)
     }
 }
 \f
-/* Parse .stabs directives.
+/* Handle .stabs directives.  The actual parsing routine is done by a
+   generic routine.  This routine is called via OBJ_PROCESS_STAB.
+   When this is called, input_line_pointer will be pointing at the
+   value field of the stab.
 
    .stabs directives have five fields:
        "string"        a string, encoding the type information.
        code            a numeric code, defined in <stab.h>
        0               a zero
-       0               a zero or line number
+       desc            a zero or line number
        value           a numeric value or an address.
 
     If the value is relocatable, we transform this into:
@@ -3335,111 +3339,76 @@ mark_stabs (ignore)
     .stabn directives have four fields (string is null):
        code            a numeric code, defined in <stab.h>
        0               a zero
-       0               a zero or a line number
+       desc            a zero or a line number
        value           a numeric value or an address.  */
 
-static void
-obj_ecoff_stab (type)
+void
+ecoff_stab (what, string, type, other, desc)
+     int what;
+     const char *string;
      int type;
+     int other;
+     int desc;
 {
-  char *string;
   efdr_t *save_file_ptr = cur_file_ptr;
-  symint_t code;
-  symint_t value;
   symbolS *sym;
+  symint_t value;
   st_t st;
   sc_t sc;
+  symint_t indx;
 
-  if (cur_file_ptr == (efdr_t *) NULL)
+  /* We don't handle .stabd.  */
+  if (what != 's' && what != 'n')
     {
-      add_file ((const char *) NULL, 0);
-      save_file_ptr = cur_file_ptr;
+      as_bad (".stab%c is not supported", what);
+      return;
     }
 
-  if (stabs_seen == 0)
-    mark_stabs (0);
+  /* A .stabn uses a null name, not an empty string.  */
+  if (what == 'n')
+    string = NULL;
 
-  if (type != 's')
-    string = (char *) NULL;
-  else
-    {
-      int len;
+  /* We ignore the other field.  */
+  if (other != 0)
+    as_warn (".stab%c: ignoring non-zero other field", what);
 
-      string = demand_copy_C_string (&len);
-      SKIP_WHITESPACE ();
-      if (*input_line_pointer == ',')
-       input_line_pointer++;
-      else
-       {
-         as_warn ("Bad .stab%c directive", type);
-         demand_empty_rest_of_line ();
-         return;
-       }
-    }
-
-  code = (symint_t) get_absolute_expression ();
-
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer++ != ',')
+  /* Make sure we have a current file.  */
+  if (cur_file_ptr == (efdr_t *) NULL)
     {
-      as_warn ("Bad .stab%c directive", type);
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
+      add_file ((const char *) NULL, 0);
+      save_file_ptr = cur_file_ptr;
     }
 
-  if (get_absolute_expression () != 0)
-    {
-      as_warn ("Bad .stab%c directive (expected 0)", type);
-      demand_empty_rest_of_line ();
-      return;
-    }
-      
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer++ != ',')
-    {
-      as_warn ("Bad .stab%c directive", type);
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
-    }
+  /* For stabs in ECOFF, the first symbol must be @stabs.  This is a
+     signal to gdb.  */
+  if (stabs_seen == 0)
+    mark_stabs (0);
 
-  /* Line number stabs are handled differently, since they have two values,
-     the line number and the address of the label.  We use the index field
-     (aka code) to hold the line number, and the value field to hold the
-     address.  The symbol type is st_Label, which should be different from
-     the other stabs, so that gdb can recognize it.  */
-  if (code == N_SLINE)
+  /* Line number stabs are handled differently, since they have two
+     values, the line number and the address of the label.  We use the
+     index field (aka desc) to hold the line number, and the value
+     field to hold the address.  The symbol type is st_Label, which
+     should be different from the other stabs, so that gdb can
+     recognize it.  */
+  if (type == N_SLINE)
     {
       SYMR dummy_symr;
       char *name;
       char name_end;
 
-      code = (symint_t) get_absolute_expression ();
-
 #ifndef NO_LISTING
       if (listing)
-       listing_source_line (code);
+       listing_source_line ((unsigned int) desc);
 #endif
 
-      if (*input_line_pointer++ != ',')
-       {
-         as_warn ("Bad .stab%c directive", type);
-         --input_line_pointer;
-         demand_empty_rest_of_line ();
-         return;
-       }
-
-      dummy_symr.index = code;
-      if (dummy_symr.index != code)
+      dummy_symr.index = desc;
+      if (dummy_symr.index != desc)
        {
-         as_warn ("Line number (%lu) for .stab%c directive cannot fit in index field (20 bits)",
-                  code, type);
-         demand_empty_rest_of_line ();
+         as_warn ("Line number (%d) for .stab%c directive cannot fit in index field (20 bits)",
+                  desc, what);
          return;
        }
 
-      SKIP_WHITESPACE ();
       name = input_line_pointer;
       name_end = get_symbol_end ();
 
@@ -3449,29 +3418,15 @@ obj_ecoff_stab (type)
       value = 0;
       st = st_Label;
       sc = sc_Text;
+      indx = desc;
     }
   else
     {
 #ifndef NO_LISTING
-      if (listing && (code == N_SO || code == N_SOL))
+      if (listing && (type == N_SO || type == N_SOL))
        listing_source_file (string);
 #endif
       
-      /* The next number is sometimes the line number of the
-        declaration.  We have nowhere to put it, so we just ignore
-        it.  */
-      (void) get_absolute_expression ();
-      
-      SKIP_WHITESPACE ();
-      if (*input_line_pointer++ != ',')
-       {
-         as_warn ("Bad .stab%c directive", type);
-         --input_line_pointer;
-         demand_empty_rest_of_line ();
-         return;
-       }
-
-      SKIP_WHITESPACE ();
       if (isdigit (*input_line_pointer)
          || *input_line_pointer == '-'
          || *input_line_pointer == '+')
@@ -3483,8 +3438,7 @@ obj_ecoff_stab (type)
        }
       else if (! is_name_beginner ((unsigned char) *input_line_pointer))
        {
-         as_warn ("Illegal .stab%c directive, bad character", type);
-         demand_empty_rest_of_line ();
+         as_warn ("Illegal .stab%c directive, bad character", what);
          return;
        }
       else
@@ -3511,10 +3465,10 @@ obj_ecoff_stab (type)
            }
        }
 
-      code = ECOFF_MARK_STAB (code);
+      indx = ECOFF_MARK_STAB (type);
     }
 
-  (void) add_ecoff_symbol (string, st, sc, sym, value, code);
+  (void) add_ecoff_symbol (string, st, sc, sym, value, indx);
 
   /* Restore normal file type.  */
   cur_file_ptr = save_file_ptr;
@@ -3527,7 +3481,7 @@ ecoff_add_bytes (buf, bufend, bufptr, need)
      char **buf;
      char **bufend;
      char *bufptr;
-     long need;
+     unsigned long need;
 {
   unsigned long at;
   unsigned long want;
@@ -3545,11 +3499,11 @@ ecoff_add_bytes (buf, bufend, bufptr, need)
 /* Adjust the symbolic information buffer to the alignment required
    for the ECOFF target debugging information.  */
 
-static long
+static unsigned long
 ecoff_padding_adjust (buf, bufend, offset, bufptrptr)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
      char **bufptrptr;
 {
   bfd_size_type align;
@@ -3557,7 +3511,7 @@ ecoff_padding_adjust (buf, bufend, offset, bufptrptr)
   align = ecoff_backend (stdoutput)->debug_align;
   if ((offset & (align - 1)) != 0)
     {
-      long add;
+      unsigned long add;
 
       add = align - (offset & (align - 1));
       if (*bufend - (*buf + offset) < add)
@@ -3573,11 +3527,11 @@ ecoff_padding_adjust (buf, bufend, offset, bufptrptr)
 
 /* Build the line number information.  */
 
-static long
+static unsigned long
 ecoff_build_lineno (buf, bufend, offset, linecntptr)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
      long *linecntptr;
 {
   char *bufptr;
@@ -3585,7 +3539,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
   lineno_list_t *last;
   efdr_t *file;
   proc_t *proc;
-  long c;
+  unsigned long c;
   long iline;
   long totcount;
 
@@ -3764,7 +3718,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
 
 /* Build and swap out the symbols.  */
 
-static long
+static unsigned long
 ecoff_build_symbols (buf,
                     bufend,
                     offset,
@@ -3775,10 +3729,10 @@ ecoff_build_symbols (buf,
                     ext_str_hash)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
      char **extbuf;
      char **extbufend;
-     long *extoffset;
+     unsigned long *extoffset;
      varray_t *ext_strings;
      struct hash_control *ext_str_hash;
 {
@@ -4120,11 +4074,11 @@ ecoff_build_symbols (buf,
 
 /* Swap out the procedure information.  */
 
-static long
+static unsigned long
 ecoff_build_procs (buf, bufend, offset)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
 {
   const bfd_size_type external_pdr_size
     = ecoff_backend (stdoutput)->external_pdr_size;
@@ -4212,11 +4166,11 @@ ecoff_build_procs (buf, bufend, offset)
 
 /* Swap out the aux information.  */
 
-static long
+static unsigned long
 ecoff_build_aux (buf, bufend, offset)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
 {
   int bigendian;
   union aux_ext *aux_out;
@@ -4321,14 +4275,14 @@ ecoff_build_aux (buf, bufend, offset)
 /* Copy out the strings from a varray_t.  This returns the number of
    bytes copied, rather than the new offset.  */
 
-static long
+static unsigned long
 ecoff_build_strings (buf, bufend, offset, vp)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
      varray_t *vp;
 {
-  long istr;
+  unsigned long istr;
   char *str_out;
   vlinks_t *str_link;
 
@@ -4340,7 +4294,7 @@ ecoff_build_strings (buf, bufend, offset, vp)
        str_link != (vlinks_t *) NULL;
        str_link = str_link->next)
     {
-      long str_cnt;
+      unsigned long str_cnt;
 
       if (str_link->next == (vlinks_t *) NULL)
        str_cnt = vp->objects_last_page;
@@ -4360,11 +4314,11 @@ ecoff_build_strings (buf, bufend, offset, vp)
 
 /* Dump out the local strings.  */
 
-static long
+static unsigned long
 ecoff_build_ss (buf, bufend, offset)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
 {
   long iss;
   vlinks_t *file_link;
@@ -4402,11 +4356,11 @@ ecoff_build_ss (buf, bufend, offset)
 
 /* Swap out the file descriptors.  */
 
-static long
+static unsigned long
 ecoff_build_fdr (buf, bufend, offset)
      char **buf;
      char **bufend;
-     long offset;
+     unsigned long offset;
 {
   const bfd_size_type external_fdr_size
     = ecoff_backend (stdoutput)->external_fdr_size;
@@ -4467,10 +4421,10 @@ ecoff_frob_file ()
   HDRR *hdr;
   char *buf;
   char *bufend;
-  long offset;
+  unsigned long offset;
   char *extbuf;
   char *extbufend;
-  long extoffset;
+  unsigned long extoffset;
   varray_t ext_strings;
   static varray_t init_ext_strings = INIT_VARRAY (char);
   struct hash_control *ext_str_hash;
@@ -4651,7 +4605,15 @@ ecoff_frob_file ()
 
 #undef SET
 
-  /* FIXME: set the register masks.  */
+#ifdef TC_MIPS
+  /* Get the MIPS register masks.  It's probably not worth setting up
+     a generic interface for this.  */
+  ecoff_data (stdoutput)->gprmask = mips_gprmask;
+  ecoff_data (stdoutput)->cprmask[0] = mips_cprmask[0];
+  ecoff_data (stdoutput)->cprmask[1] = mips_cprmask[1];
+  ecoff_data (stdoutput)->cprmask[2] = mips_cprmask[2];
+  ecoff_data (stdoutput)->cprmask[3] = mips_cprmask[3];
+#endif
 
   ecoff_data (stdoutput)->raw_size = offset;
   ecoff_data (stdoutput)->raw_syments = buf;
@@ -4660,7 +4622,7 @@ ecoff_frob_file ()
   /* FIXME: what should hdr->vstamp be?  */
 
   bfd_set_symtab (stdoutput, bfd_get_outsymbols (stdoutput),
-                 hdr->isymMax + hdr->iextMax);
+                 (unsigned int) (hdr->isymMax + hdr->iextMax));
 }
 \f
 /* Allocate a cluster of pages.  */
index f7b1947e9fb890f4103c5b3a95d50344c49a0748..e03a4bc30ca946e2ac06c96d2f80931113217cda 100644 (file)
 #define GPOPT
 #endif
 
+/* These variables are filled in with the masks of registers used.
+   The object format code reads them and puts them in the appropriate
+   place.  */
+unsigned long mips_gprmask;
+unsigned long mips_cprmask[4];
+
 /* MIPS ISA (Instruction Set Architecture) level.  */
 static int mips_isa = -1;
 
@@ -367,6 +373,12 @@ md_begin ()
 
   mips_no_prev_insn ();
 
+  mips_gprmask = 0;
+  mips_cprmask[0] = 0;
+  mips_cprmask[1] = 0;
+  mips_cprmask[2] = 0;
+  mips_cprmask[3] = 0;
+
   /* set the default alignment for the text section (2**2) */
   record_alignment (text_section, 2);
 
@@ -477,10 +489,14 @@ append_insn (ip, address_expr, reloc_type)
      expressionS *address_expr;
      bfd_reloc_code_real_type reloc_type;
 {
+  register unsigned long prev_pinfo, pinfo;
   char *f;
   fixS *fixp;
   int nops = 0;
 
+  prev_pinfo = prev_insn.insn_mo->pinfo;
+  pinfo = ip->insn_mo->pinfo;
+
   if (! mips_noreorder)
     {
       /* If the previous insn required any delay slots, see if we need
@@ -508,15 +524,15 @@ append_insn (ip, address_expr, reloc_type)
 
       /* The previous insn might require a delay slot, depending upon
         the contents of the current insn.  */
-      if ((prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
+      if ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
          || (mips_isa < 2
-             && (prev_insn.insn_mo->pinfo & INSN_LOAD_MEMORY_DELAY)))
+             && (prev_pinfo & INSN_LOAD_MEMORY_DELAY)))
        {
          /* A load from a coprocessor or from memory.  All load
             delays delay the use of general register rt for one
             instruction on the r3000.  The r6000 and r4000 use
             interlocks.  */
-         know (prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T);
+         know (prev_pinfo & INSN_WRITE_GPR_T);
          if (mips_optimize == 0
              || insn_uses_reg (ip,
                                ((prev_insn.insn_opcode >> OP_SH_RT)
@@ -524,9 +540,9 @@ append_insn (ip, address_expr, reloc_type)
                                0))
            ++nops;
        }
-      else if ((prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
+      else if ((prev_pinfo & INSN_COPROC_MOVE_DELAY)
               || (mips_isa < 2
-                  && (prev_insn.insn_mo->pinfo & INSN_COPROC_MEMORY_DELAY)))
+                  && (prev_pinfo & INSN_COPROC_MEMORY_DELAY)))
        {
          /* A generic coprocessor delay.  The previous instruction
             modified a coprocessor general or control register.  If
@@ -542,7 +558,7 @@ append_insn (ip, address_expr, reloc_type)
             knowledge of CP0 handling, and the coprocessors other
             than the floating point unit are not distinguished at
             all.  */
-         if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_T)
+         if (prev_pinfo & INSN_WRITE_FPR_T)
            {
              if (mips_optimize == 0
                  || insn_uses_reg (ip,
@@ -551,7 +567,7 @@ append_insn (ip, address_expr, reloc_type)
                                    1))
                ++nops;
            }
-         else if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_S)
+         else if (prev_pinfo & INSN_WRITE_FPR_S)
            {
              if (mips_optimize == 0
                  || insn_uses_reg (ip,
@@ -569,14 +585,14 @@ append_insn (ip, address_expr, reloc_type)
                 current instruction uses them, we must insert two
                 NOPS.  */
              if (mips_optimize == 0
-                 || ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
-                     && (ip->insn_mo->pinfo & INSN_READ_COND_CODE)))
+                 || ((prev_pinfo & INSN_WRITE_COND_CODE)
+                     && (pinfo & INSN_READ_COND_CODE)))
                nops += 2;
-             else if (ip->insn_mo->pinfo & INSN_COP)
+             else if (pinfo & INSN_COP)
                ++nops;
            }
        }
-      else if (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
+      else if (prev_pinfo & INSN_WRITE_COND_CODE)
        {
          /* The previous instruction sets the coprocessor condition
             codes, but does not require a general coprocessor delay
@@ -584,16 +600,16 @@ append_insn (ip, address_expr, reloc_type)
             instruction).  If this instruction uses the condition
             codes, we need to insert a single NOP.  */
          if (mips_optimize == 0
-             || ip->insn_mo->pinfo & INSN_READ_COND_CODE)
+             || (pinfo & INSN_READ_COND_CODE))
            ++nops;
        }
-      else if (prev_insn.insn_mo->pinfo & INSN_READ_LO)
+      else if (prev_pinfo & INSN_READ_LO)
        {
          /* The previous instruction reads the LO register; if the
             current instruction writes to the LO register, we must
             insert two NOPS.  */
          if (mips_optimize == 0
-             || ip->insn_mo->pinfo & INSN_WRITE_LO)
+             || (pinfo & INSN_WRITE_LO))
            nops += 2;
        }
       else if (prev_insn.insn_mo->pinfo & INSN_READ_HI)
@@ -602,7 +618,7 @@ append_insn (ip, address_expr, reloc_type)
             current instruction writes to the HI register, we must
             insert a NOP.  */
          if (mips_optimize == 0
-             || ip->insn_mo->pinfo & INSN_WRITE_HI)
+             || (pinfo & INSN_WRITE_HI))
            nops += 2;
        }
 
@@ -617,11 +633,11 @@ append_insn (ip, address_expr, reloc_type)
       if (nops == 0
          && (((prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
               && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
-              && (ip->insn_mo->pinfo & INSN_READ_COND_CODE))
+              && (pinfo & INSN_READ_COND_CODE))
              || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)
-                 && (ip->insn_mo->pinfo & INSN_WRITE_LO))
+                 && (pinfo & INSN_WRITE_LO))
              || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
-                 && (ip->insn_mo->pinfo & INSN_WRITE_HI))))
+                 && (pinfo & INSN_WRITE_HI))))
        ++nops;
 
       /* Now emit the right number of NOP instructions.  */
@@ -685,6 +701,28 @@ append_insn (ip, address_expr, reloc_type)
 
   md_number_to_chars (f, ip->insn_opcode, 4);
 
+  /* Update the register mask information.  */
+  if (pinfo & INSN_WRITE_GPR_D)
+    mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD);
+  if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0)
+    mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT);
+  if (pinfo & INSN_READ_GPR_S)
+    mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS);
+  if (pinfo & INSN_WRITE_GPR_31)
+    mips_gprmask |= 1 << 31;
+  if (pinfo & INSN_WRITE_FPR_D)
+    mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FD) & OP_MASK_FD);
+  if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0)
+    mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS);
+  if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0)
+    mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT);
+  if (pinfo & INSN_COP)
+    {
+      /* We don't keep enough information to sort these cases out.  */
+    }
+  /* Never set the bit for $0, which is always zero.  */
+  mips_gprmask &=~ 1 << 0;
+
   if (! mips_noreorder)
     {
       /* Filling the branch delay slot is more complex.  We try to
@@ -692,8 +730,8 @@ append_insn (ip, address_expr, reloc_type)
         do if the previous instruction does not set up a condition
         that the branch tests and if the branch is not itself the
         target of any branch.  */
-      if ((ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
-         || (ip->insn_mo->pinfo & INSN_COND_BRANCH_DELAY))
+      if ((pinfo & INSN_UNCOND_BRANCH_DELAY)
+         || (pinfo & INSN_COND_BRANCH_DELAY))
        {
          if (mips_optimize < 2
              /* If we have seen .set nobopt, don't optimize.  */
@@ -741,37 +779,37 @@ append_insn (ip, address_expr, reloc_type)
                   bc1t LABEL
                 we can not swap, and I don't feel like handling that
                 case.  */
-             || (ip->insn_mo->pinfo & INSN_READ_COND_CODE)
+             || (pinfo & INSN_READ_COND_CODE)
              /* We can not swap with an instruction that requires a
                 delay slot, becase the target of the branch might
                 interfere with that instruction.  */
-             || (prev_insn.insn_mo->pinfo
+             || (prev_pinfo
                  & (INSN_LOAD_COPROC_DELAY
                     | INSN_COPROC_MOVE_DELAY
                     | INSN_WRITE_COND_CODE
                     | INSN_READ_LO
                     | INSN_READ_HI))
              || (mips_isa < 2
-                 && (prev_insn.insn_mo->pinfo
+                 && (prev_pinfo
                      & (INSN_LOAD_MEMORY_DELAY
                         | INSN_COPROC_MEMORY_DELAY)))
              /* We can not swap with a branch instruction.  */
-             || (prev_insn.insn_mo->pinfo
+             || (prev_pinfo
                  & (INSN_UNCOND_BRANCH_DELAY
                     | INSN_COND_BRANCH_DELAY
                     | INSN_COND_BRANCH_LIKELY))
              /* We do not swap with a trap instruction, since it
                 complicates trap handlers to have the trap
                 instruction be in a delay slot.  */
-             || (prev_insn.insn_mo->pinfo & INSN_TRAP)
+             || (prev_pinfo & INSN_TRAP)
              /* If the branch reads a register that the previous
                 instruction sets, we can not swap.  */
-             || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T)
+             || ((prev_pinfo & INSN_WRITE_GPR_T)
                  && insn_uses_reg (ip,
                                    ((prev_insn.insn_opcode >> OP_SH_RT)
                                     & OP_MASK_RT),
                                    0))
-             || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D)
+             || ((prev_pinfo & INSN_WRITE_GPR_D)
                  && insn_uses_reg (ip,
                                    ((prev_insn.insn_opcode >> OP_SH_RD)
                                     & OP_MASK_RD),
@@ -779,31 +817,31 @@ append_insn (ip, address_expr, reloc_type)
              /* If the branch writes a register that the previous
                 instruction sets, we can not swap (we know that
                 branches write only to RD or to $31).  */
-             || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T)
-                 && (((ip->insn_mo->pinfo & INSN_WRITE_GPR_D)
+             || ((prev_pinfo & INSN_WRITE_GPR_T)
+                 && (((pinfo & INSN_WRITE_GPR_D)
                       && (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT)
                           == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
-                     || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31)
+                     || ((pinfo & INSN_WRITE_GPR_31)
                          && (((prev_insn.insn_opcode >> OP_SH_RT)
                               & OP_MASK_RT)
                              == 31))))
-             || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D)
-                 && (((ip->insn_mo->pinfo & INSN_WRITE_GPR_D)
+             || ((prev_pinfo & INSN_WRITE_GPR_D)
+                 && (((pinfo & INSN_WRITE_GPR_D)
                       && (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD)
                           == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
-                     || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31)
+                     || ((pinfo & INSN_WRITE_GPR_31)
                          && (((prev_insn.insn_opcode >> OP_SH_RD)
                               & OP_MASK_RD)
                              == 31))))
              /* If the branch writes a register that the previous
                 instruction reads, we can not swap (we know that
                 branches only write to RD or to $31).  */
-             || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_D)
+             || ((pinfo & INSN_WRITE_GPR_D)
                  && insn_uses_reg (&prev_insn,
                                    ((ip->insn_opcode >> OP_SH_RD)
                                     & OP_MASK_RD),
                                    0))
-             || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31)
+             || ((pinfo & INSN_WRITE_GPR_31)
                  && insn_uses_reg (&prev_insn, 31, 0))
              /* If the previous previous instruction has a load
                 delay, and sets a register that the branch reads, we
@@ -854,13 +892,13 @@ append_insn (ip, address_expr, reloc_type)
 
          /* If that was an unconditional branch, forget the previous
             insn information.  */
-         if (ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
+         if (pinfo & INSN_UNCOND_BRANCH_DELAY)
            {
              prev_prev_insn.insn_mo = &dummy_opcode;
              prev_insn.insn_mo = &dummy_opcode;
            }
        }
-      else if (ip->insn_mo->pinfo & INSN_COND_BRANCH_LIKELY)
+      else if (pinfo & INSN_COND_BRANCH_LIKELY)
        {
          /* We don't yet optimize a branch likely.  What we should do
             is look at the target, copy the instruction found there
index dca09a894b669a7320c56afdb52805aa2a1fb2b4..4aba7447545ce220b26e8fa2cb24d087adf63b32 100644 (file)
@@ -95,3 +95,8 @@ extern void mips_define_label PARAMS ((struct symbol *));
 
 #define TC_CONS_FIX_NEW cons_fix_new_mips
 extern void cons_fix_new_mips ();
+
+/* Register mask variables.  These are set by the MIPS assembly code
+   and used by ECOFF and possibly other object file formats.  */
+extern unsigned long mips_gprmask;
+extern unsigned long mips_cprmask[4];