gas/testsuite/
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 3d472f90cbb830407e68c4ab43777932fa7024f2..c819865cba53225a90921e25bd0ad9370aef2c48 100644 (file)
@@ -216,8 +216,10 @@ struct mips_set_options
   int ase_smartmips;
   int ase_dsp;
   int ase_dspr2;
+  int ase_eva;
   int ase_mt;
   int ase_mcu;
+  int ase_virt;
   /* Whether we are assembling for the mips16 processor.  0 if we are
      not, 1 if we are, and -1 if the value has not been initialized.
      Changed by `.set mips16' and `.set nomips16', and the -mips16 and
@@ -291,11 +293,13 @@ static int file_mips_single_float = 0;
 static struct mips_set_options mips_opts =
 {
   /* isa */ ISA_UNKNOWN, /* ase_mips3d */ -1, /* ase_mdmx */ -1,
-  /* ase_smartmips */ 0, /* ase_dsp */ -1, /* ase_dspr2 */ -1, /* ase_mt */ -1,
-  /* ase_mcu */ -1, /* mips16 */ -1, /* micromips */ -1, /* noreorder */ 0,
-  /* at */ ATREG, /* warn_about_macros */ 0, /* nomove */ 0, /* nobopt */ 0,
-  /* noautoextend */ 0, /* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN,
-  /* sym32 */ FALSE, /* soft_float */ FALSE, /* single_float */ FALSE
+  /* ase_smartmips */ 0, /* ase_dsp */ -1, /* ase_dspr2 */ -1,
+  /* ase_eva */ -1, /* ase_mt */ -1, /* ase_mcu */ -1,
+  /* ase_virt */ -1, /* mips16 */ -1, /* micromips */ -1,
+  /* noreorder */ 0,  /* at */ ATREG, /* warn_about_macros */ 0,
+  /* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* gp32 */ 0,
+  /* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
+  /* soft_float */ FALSE, /* single_float */ FALSE
 };
 
 /* These variables are filled in with the masks of registers used.
@@ -363,6 +367,14 @@ static int file_ase_dspr2;
                                || mips_opts.isa == ISA_MIPS64R2        \
                                || mips_opts.micromips)
 
+/* True if -meva was passed or implied by arguments passed on the
+   command line (e.g., by -march).  */
+static int file_ase_eva;
+
+#define ISA_SUPPORTS_EVA_ASE (mips_opts.isa == ISA_MIPS32R2            \
+                             || mips_opts.isa == ISA_MIPS64R2          \
+                             || mips_opts.micromips)
+
 /* True if -mmt was passed or implied by arguments passed on the
    command line (e.g., by -march).  */
 static int file_ase_mt;
@@ -374,6 +386,18 @@ static int file_ase_mt;
                              || mips_opts.isa == ISA_MIPS64R2          \
                              || mips_opts.micromips)
 
+/* True if -mvirt was passed or implied by arguments passed on the
+   command line (e.g., by -march). */
+static int file_ase_virt;
+
+#define ISA_SUPPORTS_VIRT_ASE (mips_opts.isa == ISA_MIPS32R2           \
+                              || mips_opts.isa == ISA_MIPS64R2         \
+                              || mips_opts.micromips)
+
+#define ISA_SUPPORTS_VIRT64_ASE (mips_opts.isa == ISA_MIPS64R2         \
+                                || (mips_opts.micromips                \
+                                    && ISA_HAS_64BIT_REGS (mips_opts.isa)))
+
 /* The argument of the -march= flag.  The architecture we are assembling.  */
 static int file_mips_arch = CPU_UNKNOWN;
 static const char *mips_arch_string;
@@ -1203,6 +1227,10 @@ static int mips_relax_branch;
 #define IS_SEXT_12BIT_NUM(x)                                           \
   (((((x) & 0xfff) ^ 0x800LL) - 0x800LL) == (x))
 
+/* Is the given value a sign-extended 9-bit value?  */
+#define IS_SEXT_9BIT_NUM(x)                                            \
+  (((((x) & 0x1ff) ^ 0x100LL) - 0x100LL) == (x))
+
 /* Is the given value a zero-extended 32-bit value?  Or a negated one?  */
 #define IS_ZEXT_32BIT_NUM(x)                                           \
   (((x) &~ (offsetT) 0xffffffff) == 0                                  \
@@ -1357,6 +1385,7 @@ static void s_tpreldword (int);
 static void s_gpvalue (int);
 static void s_gpword (int);
 static void s_gpdword (int);
+static void s_ehword (int);
 static void s_cpadd (int);
 static void s_insn (int);
 static void md_obj_begin (void);
@@ -1395,6 +1424,8 @@ struct mips_cpu_info
 #define MIPS_CPU_ASE_MDMX      0x0020  /* CPU implements MDMX ASE */
 #define MIPS_CPU_ASE_DSPR2     0x0040  /* CPU implements DSP R2 ASE */
 #define MIPS_CPU_ASE_MCU       0x0080  /* CPU implements MCU ASE */
+#define MIPS_CPU_ASE_VIRT      0x0100  /* CPU implements Virtualization ASE */
+#define MIPS_CPU_ASE_EVA       0x0200  /* CPU implements EVA ASE */
 
 static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
 static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
@@ -1438,6 +1469,7 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"gpvalue", s_gpvalue, 0},
   {"gpword", s_gpword, 0},
   {"gpdword", s_gpdword, 0},
+  {"ehword", s_ehword, 0},
   {"cpadd", s_cpadd, 0},
   {"insn", s_insn, 0},
 
@@ -1472,7 +1504,9 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"section", s_change_section, 0},
   {"short", s_cons, 1},
   {"single", s_float_cons, 'f'},
+  {"stabd", s_mips_stab, 'd'},
   {"stabn", s_mips_stab, 'n'},
+  {"stabs", s_mips_stab, 's'},
   {"text", s_change_sec, 't'},
   {"word", s_cons, 2},
 
@@ -2231,33 +2265,40 @@ reglist_lookup (char **s, unsigned int types, unsigned int *reglistp)
   return ok && reglist != 0;
 }
 
-/* Return TRUE if opcode MO is valid on the currently selected ISA and
-   architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
+/* Return TRUE if opcode MO is valid on the currently selected ISA, ASE
+   and architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
 
 static bfd_boolean
 is_opcode_valid (const struct mips_opcode *mo)
 {
   int isa = mips_opts.isa;
+  int ase = 0;
   int fp_s, fp_d;
 
   if (mips_opts.ase_mdmx)
-    isa |= INSN_MDMX;
+    ase |= ASE_MDMX;
   if (mips_opts.ase_dsp)
-    isa |= INSN_DSP;
+    ase |= ASE_DSP;
   if (mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
-    isa |= INSN_DSP64;
+    ase |= ASE_DSP64;
   if (mips_opts.ase_dspr2)
-    isa |= INSN_DSPR2;
+    ase |= ASE_DSPR2;
+  if (mips_opts.ase_eva)
+    ase |= ASE_EVA;
   if (mips_opts.ase_mt)
-    isa |= INSN_MT;
+    ase |= ASE_MT;
   if (mips_opts.ase_mips3d)
-    isa |= INSN_MIPS3D;
+    ase |= ASE_MIPS3D;
   if (mips_opts.ase_smartmips)
-    isa |= INSN_SMARTMIPS;
+    ase |= ASE_SMARTMIPS;
   if (mips_opts.ase_mcu)
-    isa |= INSN_MCU;
+    ase |= ASE_MCU;
+  if (mips_opts.ase_virt)
+    ase |= ASE_VIRT;
+  if (mips_opts.ase_virt && ISA_SUPPORTS_VIRT64_ASE)
+    ase |= ASE_VIRT64;
 
-  if (!opcode_is_member (mo, isa, mips_opts.arch))
+  if (!opcode_is_member (mo, isa, ase, mips_opts.arch))
     return FALSE;
 
   /* Check whether the instruction or macro requires single-precision or
@@ -2289,7 +2330,7 @@ is_opcode_valid (const struct mips_opcode *mo)
 static bfd_boolean
 is_opcode_valid_16 (const struct mips_opcode *mo)
 {
-  return opcode_is_member (mo, mips_opts.isa, mips_opts.arch);
+  return opcode_is_member (mo, mips_opts.isa, 0, mips_opts.arch);
 }
 
 /* Return TRUE if the size of the microMIPS opcode MO matches one
@@ -2742,6 +2783,28 @@ jalr_reloc_p (bfd_reloc_code_real_type reloc)
   return reloc == BFD_RELOC_MIPS_JALR || reloc == BFD_RELOC_MICROMIPS_JALR;
 }
 
+/* Return true if RELOC is a PC-relative relocation that does not have
+   full address range.  */
+
+static inline bfd_boolean
+limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  switch (reloc)
+    {
+    case BFD_RELOC_16_PCREL_S2:
+    case BFD_RELOC_MICROMIPS_7_PCREL_S1:
+    case BFD_RELOC_MICROMIPS_10_PCREL_S1:
+    case BFD_RELOC_MICROMIPS_16_PCREL_S1:
+      return TRUE;
+
+    case BFD_RELOC_32_PCREL:
+      return HAVE_64BIT_ADDRESSES;
+
+    default:
+      return FALSE;
+    }
+}
+
 /* Return true if the given relocation might need a matching %lo().
    This is only "might" because SVR4 R_MIPS_GOT16 relocations only
    need a matching %lo() when applied to local symbols.  */
@@ -4327,22 +4390,19 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   branch_disp = method == APPEND_SWAP ? insn_length (history) : 0;
 
 #ifdef OBJ_ELF
-  /* The value passed to dwarf2_emit_insn is the distance between
-     the beginning of the current instruction and the address that
-     should be recorded in the debug tables.  This is normally the
-     current address.
-
-     For MIPS16/microMIPS debug info we want to use ISA-encoded
-     addresses, so we use -1 for an address higher by one than the
-     current one.
-
-     If the instruction produced is a branch that we will swap with
-     the preceding instruction, then we add the displacement by which
-     the branch will be moved backwards.  This is more appropriate
-     and for MIPS16/microMIPS code also prevents a debugger from
-     placing a breakpoint in the middle of the branch (and corrupting
-     code if software breakpoints are used).  */
-  dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + branch_disp);
+  dwarf2_emit_insn (0);
+  /* We want MIPS16 and microMIPS debug info to use ISA-encoded addresses,
+     so "move" the instruction address accordingly.
+
+     Also, it doesn't seem appropriate for the assembler to reorder .loc
+     entries.  If this instruction is a branch that we are going to swap
+     with the previous instruction, the two instructions should be
+     treated as a unit, and the debug information for both instructions
+     should refer to the start of the branch sequence.  Using the
+     current position is certainly wrong when swapping a 32-bit branch
+     and a 16-bit delay slot, since the current position would then be
+     in the middle of a branch.  */
+  dwarf2_move_insn ((HAVE_CODE_COMPRESSION ? 1 : 0) - branch_disp);
 #endif
 
   relax32 = (mips_relax_branch
@@ -4351,9 +4411,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                out that the branch was out-of-range, we'll get an error.  */
             && !mips_opts.warn_about_macros
             && (mips_opts.at || mips_pic == NO_PIC)
-            /* Don't relax BPOSGE32/64 as they have no complementing
-               branches.  */
-            && !(ip->insn_mo->membership & (INSN_DSP64 | INSN_DSP)));
+            /* Don't relax BPOSGE32/64 or BC1ANY2T/F and BC1ANY4T/F
+               as they have no complementing branches.  */
+            && !(ip->insn_mo->ase & (ASE_MIPS3D | ASE_DSP64 | ASE_DSP)));
 
   if (!HAVE_CODE_COMPRESSION
       && address_expr
@@ -5012,6 +5072,11 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
                              INSMSB, insn, va_arg (args, int));
              continue;
 
+           case 'J':
+             gas_assert (!mips_opts.micromips);
+             INSERT_OPERAND (0, CODE10, insn, va_arg (args, int));
+             continue;
+
            case 'C':
            case 'G':
            case 'H':
@@ -5028,6 +5093,10 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
              INSERT_OPERAND (0, SEQI, insn, va_arg (args, int));
              continue;
 
+           case 'j':
+             INSERT_OPERAND (mips_opts.micromips, EVAOFFSET, insn, va_arg (args, int));
+             continue;
+
            default:
              abort ();
            }
@@ -6405,7 +6474,7 @@ macro (struct mips_cl_insn *ip)
   const char *fmt;
   int likely = 0;
   int coproc = 0;
-  int off12 = 0;
+  int offbits = 16;
   int call = 0;
   int jals = 0;
   int dbl = 0;
@@ -6413,7 +6482,6 @@ macro (struct mips_cl_insn *ip)
   int ust = 0;
   int lp = 0;
   int ab = 0;
-  int off0 = 0;
   int off;
   offsetT maxnum;
   bfd_reloc_code_real_type r;
@@ -8053,13 +8121,111 @@ macro (struct mips_cl_insn *ip)
 
       break;
 
+    case M_LBUE_AB:
+      ab = 1;
+    case M_LBUE_OB:
+      s = "lbue";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LHUE_AB:
+      ab = 1;
+    case M_LHUE_OB:
+      s = "lhue";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LBE_AB:
+      ab = 1;
+    case M_LBE_OB:
+      s = "lbe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LHE_AB:
+      ab = 1;
+    case M_LHE_OB:
+      s = "lhe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LLE_AB:
+      ab = 1;
+    case M_LLE_OB:
+      s = "lle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWE_AB:
+      ab = 1;
+    case M_LWE_OB:
+      s = "lwe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWLE_AB:
+      ab = 1;
+    case M_LWLE_OB:
+      s = "lwle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWRE_AB:
+      ab = 1;
+    case M_LWRE_OB:
+      s = "lwre";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SBE_AB:
+      ab = 1;
+    case M_SBE_OB:
+      s = "sbe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SCE_AB:
+      ab = 1;
+    case M_SCE_OB:
+      s = "sce";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SHE_AB:
+      ab = 1;
+    case M_SHE_OB:
+      s = "she";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWE_AB:
+      ab = 1;
+    case M_SWE_OB:
+      s = "swe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWLE_AB:
+      ab = 1;
+    case M_SWLE_OB:
+      s = "swle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWRE_AB:
+      ab = 1;
+    case M_SWRE_OB:
+      s = "swre";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
     case M_ACLR_AB:
       ab = 1;
     case M_ACLR_OB:
       s = "aclr";
       treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
       fmt = "\\,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_ASET_AB:
       ab = 1;
@@ -8067,7 +8233,7 @@ macro (struct mips_cl_insn *ip)
       s = "aset";
       treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
       fmt = "\\,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_LB_AB:
       ab = 1;
@@ -8114,7 +8280,7 @@ macro (struct mips_cl_insn *ip)
     case M_LWC2_OB:
       s = "lwc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8131,14 +8297,14 @@ macro (struct mips_cl_insn *ip)
     case M_LWL_OB:
       s = "lwl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LWR_AB:
       ab = 1;
     case M_LWR_OB:
       s = "lwr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LDC1_AB:
       ab = 1;
@@ -8152,7 +8318,14 @@ macro (struct mips_cl_insn *ip)
     case M_LDC2_OB:
       s = "ldc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      /* Itbl support may require additional care here.  */
+      coproc = 1;
+      goto ld_st;
+    case M_LQC2_AB:
+      ab = 1;
+      s = "lqc2";
+      fmt = "E,o(b)";
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8168,35 +8341,35 @@ macro (struct mips_cl_insn *ip)
     case M_LDL_OB:
       s = "ldl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LDR_AB:
       ab = 1;
     case M_LDR_OB:
       s = "ldr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LL_AB:
       ab = 1;
     case M_LL_OB:
       s = "ll";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LLD_AB:
       ab = 1;
     case M_LLD_OB:
       s = "lld";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LWU_AB:
       ab = 1;
     case M_LWU_OB:
       s = "lwu";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LWP_AB:
       ab = 1;
@@ -8204,7 +8377,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "lwp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       lp = 1;
       goto ld;
     case M_LDP_AB:
@@ -8213,7 +8386,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "ldp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       lp = 1;
       goto ld;
     case M_LWM_AB:
@@ -8222,7 +8395,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "lwm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_LDM_AB:
       ab = 1;
@@ -8230,11 +8403,12 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "ldm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
 
     ld:
-      if (breg == treg + lp)
+      /* We don't want to use $0 as tempreg.  */
+      if (breg == treg + lp || treg + lp == ZERO)
        goto ld_st;
       else
        tempreg = treg + lp;
@@ -8275,7 +8449,7 @@ macro (struct mips_cl_insn *ip)
     case M_SWC2_OB:
       s = "swc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8292,42 +8466,56 @@ macro (struct mips_cl_insn *ip)
     case M_SWL_OB:
       s = "swl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SWR_AB:
       ab = 1;
     case M_SWR_OB:
       s = "swr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SC_AB:
       ab = 1;
     case M_SC_OB:
       s = "sc";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SCD_AB:
       ab = 1;
     case M_SCD_OB:
       s = "scd";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_CACHE_AB:
       ab = 1;
     case M_CACHE_OB:
       s = "cache";
       fmt = mips_opts.micromips ? "k,~(b)" : "k,o(b)";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      goto ld_st;
+    case M_CACHEE_AB:
+      ab = 1;
+    case M_CACHEE_OB:
+      s = "cachee";
+      fmt = "k,+j(b)";
+      offbits = 9;
       goto ld_st;
     case M_PREF_AB:
       ab = 1;
     case M_PREF_OB:
       s = "pref";
       fmt = !mips_opts.micromips ? "k,o(b)" : "k,~(b)";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      goto ld_st;
+    case M_PREFE_AB:
+      ab = 1;
+    case M_PREFE_OB:
+      s = "prefe";
+      fmt = "k,+j(b)";
+      offbits = 9;
       goto ld_st;
     case M_SDC1_AB:
       ab = 1;
@@ -8341,7 +8529,14 @@ macro (struct mips_cl_insn *ip)
     case M_SDC2_OB:
       s = "sdc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      /* Itbl support may require additional care here.  */
+      coproc = 1;
+      goto ld_st;
+    case M_SQC2_AB:
+      ab = 1;
+      s = "sqc2";
+      fmt = "E,o(b)";
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8358,14 +8553,14 @@ macro (struct mips_cl_insn *ip)
     case M_SDL_OB:
       s = "sdl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SDR_AB:
       ab = 1;
     case M_SDR_OB:
       s = "sdr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SWP_AB:
       ab = 1;
@@ -8373,7 +8568,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "swp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SDP_AB:
       ab = 1;
@@ -8381,7 +8576,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "sdp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SWM_AB:
       ab = 1;
@@ -8389,7 +8584,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "swm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SDM_AB:
       ab = 1;
@@ -8397,7 +8592,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "sdm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
 
     ld_st:
       tempreg = AT;
@@ -8427,18 +8622,25 @@ macro (struct mips_cl_insn *ip)
 
          expr1.X_add_number = offset_expr.X_add_number;
          normalize_address_expr (&expr1);
-         if (!off12 && !IS_SEXT_16BIT_NUM (expr1.X_add_number))
+         if ((offbits == 0 || offbits == 16)
+             && !IS_SEXT_16BIT_NUM (expr1.X_add_number))
            {
              expr1.X_add_number = ((expr1.X_add_number + 0x8000)
                                    & ~(bfd_vma) 0xffff);
              hipart = 1;
            }
-         else if (off12 && !IS_SEXT_12BIT_NUM (expr1.X_add_number))
+         else if (offbits == 12 && !IS_SEXT_12BIT_NUM (expr1.X_add_number))
            {
              expr1.X_add_number = ((expr1.X_add_number + 0x800)
                                    & ~(bfd_vma) 0xfff);
              hipart = 1;
            }
+         else if (offbits == 9 && !IS_SEXT_9BIT_NUM (expr1.X_add_number))
+           {
+             expr1.X_add_number = ((expr1.X_add_number + 0x100)
+                                   & ~(bfd_vma) 0x1ff);
+             hipart = 1;
+           }
          if (hipart)
            {
              load_register (tempreg, &expr1, HAVE_64BIT_ADDRESSES);
@@ -8447,7 +8649,7 @@ macro (struct mips_cl_insn *ip)
                             tempreg, tempreg, breg);
              breg = tempreg;
            }
-         if (off0)
+         if (offbits == 0)
            {
              if (offset_expr.X_add_number == 0)
                tempreg = breg;
@@ -8456,20 +8658,20 @@ macro (struct mips_cl_insn *ip)
                             "t,r,j", tempreg, breg, BFD_RELOC_LO16);
              macro_build (NULL, s, fmt, treg, tempreg);
            }
-         else if (!off12)
+         else if (offbits == 16)
            macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, breg);
          else
            macro_build (NULL, s, fmt,
                         treg, (unsigned long) offset_expr.X_add_number, breg);
        }
-      else if (off12 || off0)
+      else if (offbits != 16)
        {
-         /* A 12-bit or 0-bit offset field is too narrow to be used
-            for a low-part relocation, so load the whole address into
-            the auxillary register.  In the case of "A(b)" addresses,
-            we first load absolute address "A" into the register and
-            then add base register "b".  In the case of "o(b)" addresses,
-            we simply need to add 16-bit offset "o" to base register "b", and
+         /* The offset field is too narrow to be used for a low-part
+            relocation, so load the whole address into the auxillary
+            register.  In the case of "A(b)" addresses, we first load
+            absolute address "A" into the register and then add base
+            register "b".  In the case of "o(b)" addresses, we simply
+            need to add 16-bit offset "o" to base register "b", and
             offset_reloc already contains the relocations associated
             with "o".  */
          if (ab)
@@ -8484,7 +8686,7 @@ macro (struct mips_cl_insn *ip)
                         tempreg, breg, -1,
                         offset_reloc[0], offset_reloc[1], offset_reloc[2]);
          expr1.X_add_number = 0;
-         if (off0)
+         if (offbits == 0)
            macro_build (NULL, s, fmt, treg, tempreg);
          else
            macro_build (NULL, s, fmt,
@@ -9297,14 +9499,14 @@ macro (struct mips_cl_insn *ip)
       ab = 1;
     case M_SAA_OB:
       s = "saa";
-      off0 = 1;
+      offbits = 0;
       fmt = "t,(b)";
       goto ld_st;
     case M_SAAD_AB:
       ab = 1;
     case M_SAAD_OB:
       s = "saad";
-      off0 = 1;
+      offbits = 0;
       fmt = "t,(b)";
       goto ld_st;
 
@@ -9966,7 +10168,7 @@ macro (struct mips_cl_insn *ip)
     case M_ULW:
       s = "lwl";
       s2 = "lwr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 3;
       goto uld_st;
     case M_ULD_A:
@@ -9974,7 +10176,7 @@ macro (struct mips_cl_insn *ip)
     case M_ULD:
       s = "ldl";
       s2 = "ldr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 7;
       goto uld_st;
     case M_USH_A:
@@ -9990,7 +10192,7 @@ macro (struct mips_cl_insn *ip)
     case M_USW:
       s = "swl";
       s2 = "swr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 3;
       ust = 1;
       goto uld_st;
@@ -9999,7 +10201,7 @@ macro (struct mips_cl_insn *ip)
     case M_USD:
       s = "sdl";
       s2 = "sdr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 7;
       ust = 1;
 
@@ -10021,7 +10223,7 @@ macro (struct mips_cl_insn *ip)
          tempreg = treg;
          ep = &expr1;
        }
-      else if (off12
+      else if (offbits == 12
               && (offset_expr.X_op != O_constant
                   || !IS_SEXT_12BIT_NUM (offset_expr.X_add_number)
                   || !IS_SEXT_12BIT_NUM (offset_expr.X_add_number + off)))
@@ -10047,7 +10249,7 @@ macro (struct mips_cl_insn *ip)
 
       if (!target_big_endian)
        ep->X_add_number += off;
-      if (!off12)
+      if (offbits != 12)
        macro_build (ep, s, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
       else
        macro_build (NULL, s, "t,~(b)",
@@ -10057,7 +10259,7 @@ macro (struct mips_cl_insn *ip)
        ep->X_add_number -= off;
       else
        ep->X_add_number += off;
-      if (!off12)
+      if (offbits != 12)
        macro_build (ep, s2, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
       else
        macro_build (NULL, s2, "t,~(b)",
@@ -10392,6 +10594,7 @@ validate_mips_insn (const struct mips_opcode *opc)
          case 'G': USE_BITS (OP_MASK_EXTMSBD,  OP_SH_EXTMSBD); break;
          case 'H': USE_BITS (OP_MASK_EXTMSBD,  OP_SH_EXTMSBD); break;
          case 'I': break;
+         case 'J': USE_BITS (OP_MASK_CODE10,   OP_SH_CODE10);  break;
          case 't': USE_BITS (OP_MASK_RT,       OP_SH_RT);      break;
          case 'T': USE_BITS (OP_MASK_RT,       OP_SH_RT);
                    USE_BITS (OP_MASK_SEL,      OP_SH_SEL);     break;
@@ -10407,6 +10610,7 @@ validate_mips_insn (const struct mips_opcode *opc)
          case 'a': USE_BITS (OP_MASK_OFFSET_A, OP_SH_OFFSET_A); break;
          case 'b': USE_BITS (OP_MASK_OFFSET_B, OP_SH_OFFSET_B); break;
          case 'c': USE_BITS (OP_MASK_OFFSET_C, OP_SH_OFFSET_C); break;
+         case 'j': USE_BITS (OP_MASK_EVAOFFSET, OP_SH_EVAOFFSET); break;
 
          default:
            as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
@@ -10568,6 +10772,7 @@ validate_micromips_insn (const struct mips_opcode *opc)
          case 'F': USE_BITS (INSMSB);  break;
          case 'G': USE_BITS (EXTMSBD); break;
          case 'H': USE_BITS (EXTMSBD); break;
+         case 'j': USE_BITS (EVAOFFSET);       break;
          default:
            as_bad (_("Internal error: bad mips opcode "
                      "(unknown extension operand type `%c%c'): %s %s"),
@@ -10790,6 +10995,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
   unsigned int destregno = 0;
   unsigned int lastpos = 0;
   unsigned int limlo, limhi;
+  int sizelo;
   char *s_reset;
   offsetT min_range, max_range;
   long opend;
@@ -11314,6 +11520,23 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  }
                  continue;
 
+               case 'J':               /* 10-bit hypcall code.  */
+                 gas_assert (!mips_opts.micromips);
+                 {
+                   unsigned long mask = OP_MASK_CODE10;
+
+                   my_getExpression (&imm_expr, s);
+                   check_absolute_expr (ip, &imm_expr);
+                   if ((unsigned long) imm_expr.X_add_number > mask)
+                     as_warn (_("Code for %s not in range 0..%lu (%lu)"),
+                              ip->insn_mo->name,
+                              mask, (unsigned long) imm_expr.X_add_number);
+                   INSERT_OPERAND (0, CODE10, *ip, imm_expr.X_add_number);
+                   imm_expr.X_op = O_absent;
+                   s = expr_end;
+                 }
+                 continue;
+
                case 'A':               /* ins/ext position, becomes LSB.  */
                  limlo = 0;
                  limhi = 31;
@@ -11374,23 +11597,25 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                case 'C':               /* ext size, becomes MSBD.  */
                  limlo = 1;
                  limhi = 32;
+                 sizelo = 1;
                  goto do_msbd;
                case 'G':
                  limlo = 33;
                  limhi = 64;
+                 sizelo = 33;
                  goto do_msbd;
                case 'H':
                  limlo = 33;
                  limhi = 64;
+                 sizelo = 1;
                  goto do_msbd;
                do_msbd:
                  my_getExpression (&imm_expr, s);
                  check_absolute_expr (ip, &imm_expr);
-                 /* Check for negative input so that small negative numbers
-                    will not succeed incorrectly.  The checks against
-                    (pos+size) transitively check "size" itself,
-                    assuming that "pos" is reasonable.  */
-                 if ((long) imm_expr.X_add_number < 0
+                 /* The checks against (pos+size) don't transitively check
+                    "size" itself, assuming that "pos" is reasonable.
+                    We also need to check the lower bound of "size".  */
+                 if ((long) imm_expr.X_add_number < sizelo
                      || ((unsigned long) imm_expr.X_add_number
                          + lastpos) < limlo
                      || ((unsigned long) imm_expr.X_add_number
@@ -11655,6 +11880,35 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  INSERT_OPERAND (0, FZ, *ip, regno);
                  continue;
 
+               case 'j':
+                 {
+                   int shift = 8;
+                   size_t i;
+                   /* Check whether there is only a single bracketed expression
+                      left.  If so, it must be the base register and the
+                      constant must be zero.  */
+                   if (*s == '(' && strchr (s + 1, '(') == 0)
+                     continue;
+
+                   /* If this value won't fit into the offset, then go find
+                      a macro that will generate a 16- or 32-bit offset code
+                      pattern.  */
+                   i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+                   if ((i == 0 && (imm_expr.X_op != O_constant
+                                   || imm_expr.X_add_number >= 1 << shift
+                                   || imm_expr.X_add_number < -1 << shift))
+                       || i > 0)
+                     {
+                       imm_expr.X_op = O_absent;
+                       break;
+                     }
+                   INSERT_OPERAND (mips_opts.micromips, EVAOFFSET, *ip,
+                                   imm_expr.X_add_number);
+                   imm_expr.X_op = O_absent;
+                   s = expr_end;
+                 }
+                 continue;
+
                default:
                  as_bad (_("Internal error: bad %s opcode "
                            "(unknown extension operand type `+%c'): %s %s"),
@@ -14469,10 +14723,14 @@ enum options
     OPTION_NO_DSP,
     OPTION_MT,
     OPTION_NO_MT,
+    OPTION_VIRT,
+    OPTION_NO_VIRT,
     OPTION_SMARTMIPS,
     OPTION_NO_SMARTMIPS,
     OPTION_DSPR2,
     OPTION_NO_DSPR2,
+    OPTION_EVA,
+    OPTION_NO_EVA,
     OPTION_MICROMIPS,
     OPTION_NO_MICROMIPS,
     OPTION_MCU,
@@ -14569,10 +14827,14 @@ struct option md_longopts[] =
   {"mno-smartmips", no_argument, NULL, OPTION_NO_SMARTMIPS},
   {"mdspr2", no_argument, NULL, OPTION_DSPR2},
   {"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2},
+  {"meva", no_argument, NULL, OPTION_EVA},
+  {"mno-eva", no_argument, NULL, OPTION_NO_EVA},
   {"mmicromips", no_argument, NULL, OPTION_MICROMIPS},
   {"mno-micromips", no_argument, NULL, OPTION_NO_MICROMIPS},
   {"mmcu", no_argument, NULL, OPTION_MCU},
   {"mno-mcu", no_argument, NULL, OPTION_NO_MCU},
+  {"mvirt", no_argument, NULL, OPTION_VIRT},
+  {"mno-virt", no_argument, NULL, OPTION_NO_VIRT},
 
   /* Old-style architecture options.  Don't add more of these.  */
   {"m4650", no_argument, NULL, OPTION_M4650},
@@ -14819,6 +15081,14 @@ md_parse_option (int c, char *arg)
       mips_opts.ase_dsp = 0;
       break;
 
+    case OPTION_EVA:
+      mips_opts.ase_eva = 1;
+      break;
+
+    case OPTION_NO_EVA:
+      mips_opts.ase_eva = 0;
+      break;
+
     case OPTION_MT:
       mips_opts.ase_mt = 1;
       break;
@@ -14850,6 +15120,14 @@ md_parse_option (int c, char *arg)
       mips_no_prev_insn ();
       break;
 
+    case OPTION_VIRT:
+      mips_opts.ase_virt = 1;
+      break;
+
+    case OPTION_NO_VIRT:
+      mips_opts.ase_virt = 0;
+      break;
+
     case OPTION_MIPS16:
       if (mips_opts.micromips == 1)
        {
@@ -15331,6 +15609,12 @@ mips_after_parse_args (void)
     as_warn (_("%s ISA does not support DSP R2 ASE"),
             mips_cpu_info_from_isa (mips_opts.isa)->name);
 
+  if (mips_opts.ase_eva == -1)
+    mips_opts.ase_eva = (arch_info->flags & MIPS_CPU_ASE_EVA) ? 1 : 0;
+  if (mips_opts.ase_eva && !ISA_SUPPORTS_EVA_ASE)
+    as_warn (_("%s ISA does not support EVA ASE"),
+            mips_cpu_info_from_isa (mips_opts.isa)->name);
+
   if (mips_opts.ase_mt == -1)
     mips_opts.ase_mt = (arch_info->flags & MIPS_CPU_ASE_MT) ? 1 : 0;
   if (mips_opts.ase_mt && !ISA_SUPPORTS_MT_ASE)
@@ -15343,13 +15627,21 @@ mips_after_parse_args (void)
       as_warn (_("%s ISA does not support MCU ASE"),
               mips_cpu_info_from_isa (mips_opts.isa)->name);
 
+  if (mips_opts.ase_virt == -1)
+    mips_opts.ase_virt = (arch_info->flags & MIPS_CPU_ASE_VIRT) ? 1 : 0;
+  if (mips_opts.ase_virt && !ISA_SUPPORTS_VIRT_ASE)
+    as_warn (_("%s ISA does not support Virtualization ASE"),
+            mips_cpu_info_from_isa (mips_opts.isa)->name);
+
   file_mips_isa = mips_opts.isa;
   file_ase_mips3d = mips_opts.ase_mips3d;
   file_ase_mdmx = mips_opts.ase_mdmx;
   file_ase_smartmips = mips_opts.ase_smartmips;
   file_ase_dsp = mips_opts.ase_dsp;
   file_ase_dspr2 = mips_opts.ase_dspr2;
+  file_ase_eva = mips_opts.ase_eva;
   file_ase_mt = mips_opts.ase_mt;
+  file_ase_virt = mips_opts.ase_virt;
   mips_opts.gp32 = file_mips_gp32;
   mips_opts.fp32 = file_mips_fp32;
   mips_opts.soft_float = file_mips_soft_float;
@@ -15392,6 +15684,9 @@ md_pcrel_from (fixS *fixP)
       /* Return the address of the delay slot.  */
       return addr + 4;
 
+    case BFD_RELOC_32_PCREL:
+      return addr;
+
     default:
       /* We have no relocation type for PC relative MIPS16 instructions.  */
       if (fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) != now_seg)
@@ -15614,7 +15909,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
   gas_assert (!fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
              || fixP->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
              || fixP->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
-             || fixP->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1);
+             || fixP->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1
+             || fixP->fx_r_type == BFD_RELOC_32_PCREL);
 
   /* Don't treat parts of a composite relocation as done.  There are two
      reasons for this:
@@ -15720,6 +16016,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MICROMIPS_GOT_LO16:
     case BFD_RELOC_MICROMIPS_CALL_HI16:
     case BFD_RELOC_MICROMIPS_CALL_LO16:
+    case BFD_RELOC_MIPS_EH:
       if (fixP->fx_done)
        {
          offsetT value;
@@ -15762,6 +16059,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
     case BFD_RELOC_RVA:
     case BFD_RELOC_32:
+    case BFD_RELOC_32_PCREL:
     case BFD_RELOC_16:
       /* If we are deleting this reloc entry, we must fill in the
         value now.  This can happen if we have a .word which is not
@@ -16401,6 +16699,15 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
       mips_opts.ase_dspr2 = 0;
       mips_opts.ase_dsp = 0;
     }
+  else if (strcmp (name, "eva") == 0)
+    {
+      if (!ISA_SUPPORTS_EVA_ASE)
+       as_warn (_("%s ISA does not support EVA ASE"),
+                mips_cpu_info_from_isa (mips_opts.isa)->name);
+      mips_opts.ase_eva = 1;
+    }
+  else if (strcmp (name, "noeva") == 0)
+    mips_opts.ase_eva = 0;
   else if (strcmp (name, "mt") == 0)
     {
       if (!ISA_SUPPORTS_MT_ASE)
@@ -16414,6 +16721,15 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
     mips_opts.ase_mcu = 1;
   else if (strcmp (name, "nomcu") == 0)
     mips_opts.ase_mcu = 0;
+  else if (strcmp (name, "virt") == 0)
+    {
+      if (!ISA_SUPPORTS_VIRT_ASE)
+       as_warn (_("%s ISA does not support Virtualization ASE"), 
+                mips_cpu_info_from_isa (mips_opts.isa)->name);
+      mips_opts.ase_virt = 1;
+    }
+  else if (strcmp (name, "novirt") == 0)
+    mips_opts.ase_virt = 0;
   else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
     {
       int reset = 0;
@@ -16621,6 +16937,9 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
   /* In ELF, this symbol is implicitly an STT_OBJECT symbol.  */
   symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   macro_build_lui (&ex, mips_gp_register);
   macro_build (&ex, "addiu", "t,r,j", mips_gp_register,
@@ -16630,6 +16949,7 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
                 mips_gp_register, reg);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16706,6 +17026,9 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
   SKIP_WHITESPACE ();
   expression (&ex_sym);
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   if (mips_cpreturn_register == -1)
     {
@@ -16753,6 +17076,7 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
 
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16810,11 +17134,15 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED)
   ex.X_op_symbol = NULL;
   ex.X_add_number = mips_cprestore_offset;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   macro_build_ldst_constoffset (&ex, ADDRESS_STORE_INSN, mips_gp_register,
                                SP, HAVE_64BIT_ADDRESSES);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16845,6 +17173,9 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   if (mips_cpreturn_register == -1)
     {
@@ -16860,6 +17191,7 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
                 mips_cpreturn_register, 0);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -17024,6 +17356,34 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .ehword pseudo-op.  This is used when generating unwinding
+   tables.  It generates a R_MIPS_EH reloc.  */
+
+static void
+s_ehword (int ignore ATTRIBUTE_UNUSED)
+{
+  expressionS ex;
+  char *p;
+
+  mips_emit_delays ();
+
+  expression (&ex);
+  mips_clear_insn_labels ();
+
+  if (ex.X_op != O_symbol || ex.X_add_number != 0)
+    {
+      as_bad (_("Unsupported use of .ehword"));
+      ignore_rest_of_line ();
+    }
+
+  p = frag_more (4);
+  md_number_to_chars (p, 0, 4);
+  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
+              BFD_RELOC_MIPS_EH);
+
+  demand_empty_rest_of_line ();
+}
+
 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
    tables in SVR4 PIC code.  */
 
@@ -17039,12 +17399,16 @@ s_cpadd (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   /* Add $gp to the register named as an argument.  */
   macro_start ();
   reg = tc_get_register (0);
   macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", reg, reg, mips_gp_register);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -17065,18 +17429,24 @@ s_insn (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-/* Handle a .stabn directive.  We need these in order to mark a label
-   as being a mips16 text label correctly.  Sometimes the compiler
-   will emit a label, followed by a .stabn, and then switch sections.
-   If the label and .stabn are in mips16 mode, then the label is
-   really a mips16 text label.  */
+/* Handle a .stab[snd] directive.  Ideally these directives would be
+   implemented in a transparent way, so that removing them would not
+   have any effect on the generated instructions.  However, s_stab
+   internally changes the section, so in practice we need to decide
+   now whether the preceding label marks compressed code.  We do not
+   support changing the compression mode of a label after a .stab*
+   directive, such as in:
+
+   foo:
+       .stabs ...
+       .set mips16
+
+   so the current mode wins.  */
 
 static void
 s_mips_stab (int type)
 {
-  if (type == 'n')
-    mips_mark_labels ();
-
+  mips_mark_labels ();
   s_stab (type);
 }
 
@@ -17783,11 +18153,12 @@ mips_fix_adjustable (fixS *fixp)
     return 0;
 
   /* There is no place to store an in-place offset for JALR relocations.
-     Likewise an in-range offset of PC-relative relocations may overflow
-     the in-place relocatable field if recalculated against the start
-     address of the symbol's containing section.  */
+     Likewise an in-range offset of limited PC-relative relocations may
+     overflow the in-place relocatable field if recalculated against the
+     start address of the symbol's containing section.  */
   if (HAVE_IN_PLACE_ADDENDS
-      && (fixp->fx_pcrel || jalr_reloc_p (fixp->fx_r_type)))
+      && (limited_pcrel_reloc_p (fixp->fx_r_type)
+         || jalr_reloc_p (fixp->fx_r_type)))
     return 0;
 
 #ifdef OBJ_ELF
@@ -17867,7 +18238,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
       gas_assert (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
                  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
                  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
-                 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1);
+                 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1
+                 || fixp->fx_r_type == BFD_RELOC_32_PCREL);
 
       /* At this point, fx_addnumber is "symbol offset - pcrel address".
         Relocations want only the symbol offset.  */
@@ -18003,10 +18375,10 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
              switch ((insn >> 28) & 0xf)
                {
                case 4:
-                 /* bc[0-3][tf]l? and bc1any[24][ft] instructions can
-                    have the condition reversed by tweaking a single
-                    bit, and their opcodes all have 0x4???????.  */
-                 gas_assert ((insn & 0xf1000000) == 0x41000000);
+                 /* bc[0-3][tf]l? instructions can have the condition
+                    reversed by tweaking a single TF bit, and their
+                    opcodes all have 0x4???????.  */
+                 gas_assert ((insn & 0xf3e00000) == 0x41000000);
                  insn ^= 0x00010000;
                  break;
 
@@ -18658,12 +19030,8 @@ mips_elf_final_processing (void)
   if (mips_abicalls)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
 
-  /* Set MIPS ELF flags for ASEs.  */
-  /* We may need to define a new flag for DSP ASE, and set this flag when
-     file_ase_dsp is true.  */
-  /* Same for DSP R2.  */
-  /* We may need to define a new flag for MT ASE, and set this flag when
-     file_ase_mt is true.  */
+  /* Set MIPS ELF flags for ASEs.  Note that not all ASEs have flags
+     defined at present; this might need to change in future.  */
   if (file_ase_mips16)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16;
   if (file_ase_micromips)
@@ -19534,6 +19902,9 @@ MIPS options:\n\
 -mmcu                  generate MCU instructions\n\
 -mno-mcu               do not generate MCU instructions\n"));
   fprintf (stream, _("\
+-mvirt                 generate Virtualization instructions\n\
+-mno-virt              do not generate Virtualization instructions\n"));
+  fprintf (stream, _("\
 -mfix-loongson2f-jump  work around Loongson2F JUMP instructions\n\
 -mfix-loongson2f-nop   work around Loongson2F NOP errata\n\
 -mfix-vr4120           work around certain VR4120 errata\n\
@@ -19552,7 +19923,8 @@ MIPS options:\n\
 -msoft-float           do not allow floating-point instructions\n\
 -msingle-float         only allow 32-bit floating-point operations\n\
 -mdouble-float         allow 32-bit and 64-bit floating-point operations\n\
---[no-]construct-floats [dis]allow floating point values to be constructed\n"
+--[no-]construct-floats        [dis]allow floating point values to be constructed\n\
+--[no-]relax-branch    [dis]allow out-of-range branches to be relaxed\n"
                     ));
 #ifdef OBJ_ELF
   fprintf (stream, _("\
This page took 0.046958 seconds and 4 git commands to generate.