* config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext
authorIan Lance Taylor <ian@airs.com>
Mon, 9 Dec 1996 23:26:15 +0000 (23:26 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 9 Dec 1996 23:26:15 +0000 (23:26 +0000)
arguments, and store them.  Adjust other RELAX_MIPS16 macros.
(RELAX_MIPS16_USER_SMALL): Define.
(RELAX_MIPS16_USER_EXT): Define.
(mips16_small, mips16_ext): New static variables.
(append_insn): Pass mips16_small and mips16_ext to
RELAX_MIPS16_ENCODE.
(mips16_ip): Set mips16_small and mips16_ext.
(mips16_immed): Don't check mips16_autoextend.
(mips16_extended_frag): Check USER_SMALL and USER_EXT.

gas/ChangeLog
gas/config/tc-mips.c

index e106825b4d444529149a0f81d547496bb8bac418..03f5bbbefe4a74bd1bfe21bf64bfdc6955b7a215 100644 (file)
@@ -1,5 +1,16 @@
 Mon Dec  9 17:09:42 1996  Ian Lance Taylor  <ian@cygnus.com>
 
+       * config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext
+       arguments, and store them.  Adjust other RELAX_MIPS16 macros.
+       (RELAX_MIPS16_USER_SMALL): Define.
+       (RELAX_MIPS16_USER_EXT): Define.
+       (mips16_small, mips16_ext): New static variables.
+       (append_insn): Pass mips16_small and mips16_ext to
+       RELAX_MIPS16_ENCODE.
+       (mips16_ip): Set mips16_small and mips16_ext.
+       (mips16_immed): Don't check mips16_autoextend.
+       (mips16_extended_frag): Check USER_SMALL and USER_EXT.
+
        * write.c (write_relocs): Print an error for an out of range
        fixup, rather than calling abort.
 
index 9842c1e6868f48e1692d0a5c7e5712478ae7e319..c1a348e4066e98376ff595826c7ec8c79d90fd85 100644 (file)
@@ -453,23 +453,29 @@ static const int mips16_to_32_reg_map[] =
    use the high bit of the subtype field to distinguish these cases.
 
    The information we store for this type of relaxation is simply the
-   argument code found in the opcode file for this relocation.  That
-   tells us the size of the value, and how it should be stored.  We
-   also store whether the fragment is considered to be extended or
+   argument code found in the opcode file for this relocation, and
+   whether the user explicitly requested a small or extended form.
+   That tells us the size of the value, and how it should be stored.
+   We also store whether the fragment is considered to be extended or
    not.  We also store whether this is known to be a branch to a
    different section, whether we have tried to relax this frag yet,
    and whether we have ever extended a PC relative fragment because of
    a shift count.  */
-#define RELAX_MIPS16_ENCODE(type) \
-  (0x80000000 | ((type) & 0xff))
+#define RELAX_MIPS16_ENCODE(type, small, ext)  \
+  (0x80000000                                  \
+   | ((type) & 0xff)                           \
+   | ((small) ? 0x100 : 0)                     \
+   | ((ext) ? 0x200 : 0))
 #define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)
 #define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
-#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x100) != 0)
-#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x100)
-#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x100)
-#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x200) != 0)
-#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x200)
-#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x200)
+#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
+#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
+#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x400) != 0)
+#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x400)
+#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x400)
+#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x800) != 0)
+#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x800)
+#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x800)
 \f
 /* Prototypes for static functions.  */
 
@@ -648,6 +654,10 @@ static bfd_reloc_code_real_type offset_reloc;
 
 static boolean imm_unmatched_hi;
 
+/* These are set by mips16_ip if an explicit extension is used.  */
+
+static boolean mips16_small, mips16_ext;
+
 /*
  * This function is called once, at assembler startup time.  It should
  * set up all the tables, etc. that the MD part of the assembler will need.
@@ -1356,7 +1366,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
       /* We need to set up a variant frag.  */
       assert (mips16 && address_expr != NULL);
       f = frag_var (rs_machine_dependent, 4, 0,
-                   RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED),
+                   RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED,
+                                        mips16_small, mips16_ext),
                    make_expr_symbol (address_expr), (long) 0,
                    (char *) NULL);
     }
@@ -6628,7 +6639,9 @@ mips_ip (str, ip)
 /* This routine assembles an instruction into its binary format when
    assembling for the mips16.  As a side effect, it sets one of the
    global variables imm_reloc or offset_reloc to the type of
-   relocation to do if one of the operands is an address expression.  */
+   relocation to do if one of the operands is an address expression.
+   It also sets mips16_small and mips16_ext if the user explicitly
+   requested a small or extended instruction.  */
 
 static void
 mips16_ip (str, ip)
@@ -6636,7 +6649,6 @@ mips16_ip (str, ip)
      struct mips_cl_insn *ip;
 {
   char *s;
-  boolean small, ext;
   const char *args;
   struct mips_opcode *insn;
   char *argsstart;
@@ -6646,8 +6658,8 @@ mips16_ip (str, ip)
 
   insn_error = NULL;
 
-  small = false;
-  ext = false;
+  mips16_small = false;
+  mips16_ext = false;
 
   for (s = str; islower (*s); ++s)
     ;
@@ -6664,14 +6676,14 @@ mips16_ip (str, ip)
       if (s[1] == 't' && s[2] == ' ')
        {
          *s = '\0';
-         small = true;
+         mips16_small = true;
          s += 3;
          break;
        }
       else if (s[1] == 'e' && s[2] == ' ')
        {
          *s = '\0';
-         ext = true;
+         mips16_ext = true;
          s += 3;
          break;
        }
@@ -6681,6 +6693,9 @@ mips16_ip (str, ip)
       return;
     }
 
+  if (! mips16_autoextend && ! mips16_ext)
+    mips16_small = true;
+
   if ((insn = (struct mips_opcode *) hash_find (mips16_op_hash, str)) == NULL)
     {
       insn_error = "unrecognized opcode";
@@ -6723,9 +6738,9 @@ mips16_ip (str, ip)
                    {
                      mips16_immed ((char *) NULL, 0,
                                    imm_reloc - BFD_RELOC_UNUSED,
-                                   imm_expr.X_add_number, true, small, ext,
-                                   &ip->insn_opcode, &ip->use_extend,
-                                   &ip->extend);
+                                   imm_expr.X_add_number, true, mips16_small,
+                                   mips16_ext, &ip->insn_opcode,
+                                   &ip->use_extend, &ip->extend);
                      imm_expr.X_op = O_absent;
                      imm_reloc = BFD_RELOC_UNUSED;
                    }
@@ -7196,7 +7211,7 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
 
   if (warn && ext && ! needext)
     as_warn_where (file, line, "extended operand requested but not required");
-  if ((small || ! mips16_autoextend) && needext)
+  if (small && needext)
     as_bad_where (file, line, "invalid unextended operand value");
 
   if (small || (! ext && ! needext))
@@ -9011,6 +9026,11 @@ mips16_extended_frag (fragp, sec, stretch)
   int mintiny, maxtiny;
   segT symsec;
 
+  if (RELAX_MIPS16_USER_SMALL (fragp->fr_subtype))
+    return 0;
+  if (RELAX_MIPS16_USER_EXT (fragp->fr_subtype))
+    return 1;
+
   type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
   op = mips16_immed_operands;
   while (op->type != type)