include/opcode/
authorRichard Sandiford <rdsandiford@googlemail.com>
Sat, 3 Aug 2013 10:49:48 +0000 (10:49 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Sat, 3 Aug 2013 10:49:48 +0000 (10:49 +0000)
* mips.h (mips_pcrel_operand): Inherit from mips_int_operand.
(mips_int_operand_min, mips_int_operand_max): New functions.
(mips_decode_pcrel_operand): Use mips_decode_int_operand.

opcodes/
* mips-formats.h (PCREL): Reorder parameters and update the definition
to match new mips_pcrel_operand layout.
(JUMP, JALX, BRANCH): Update accordingly.
* mips16-opc.c (decode_mips16_operand): Likewise.

gas/
* config/tc-mips.c (match_int_operand): Use mips_int_operand_min
and mips_int_operand_max.
(mips16_immed_operand, mips16_immed_operands, MIPS16_NUM_IMMED):
Delete.
(mips16_immed_operand, mips16_immed_in_range_p): New functions.
(mips16_immed, mips16_extended_frag): Use them.  Use mips_int_operand
instead of mips16_immed_operand.

gas/ChangeLog
gas/config/tc-mips.c
include/opcode/ChangeLog
include/opcode/mips.h
opcodes/ChangeLog
opcodes/mips-formats.h
opcodes/mips16-opc.c

index 868fb87..b201962 100644 (file)
@@ -1,5 +1,15 @@
 2013-08-03  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * config/tc-mips.c (match_int_operand): Use mips_int_operand_min
+       and mips_int_operand_max.
+       (mips16_immed_operand, mips16_immed_operands, MIPS16_NUM_IMMED):
+       Delete.
+       (mips16_immed_operand, mips16_immed_in_range_p): New functions.
+       (mips16_immed, mips16_extended_frag): Use them.  Use mips_int_operand
+       instead of mips16_immed_operand.
+
+2013-08-03  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * config/tc-mips.c (mips16_macro): Don't use move_register.
        (mips16_ip): Allow macros to use 'p'.
 
index bdfcc3a..73b7b4e 100644 (file)
@@ -4218,18 +4218,17 @@ match_int_operand (struct mips_arg_info *arg,
                   const struct mips_operand *operand_base)
 {
   const struct mips_int_operand *operand;
-  unsigned int uval, mask;
+  unsigned int uval;
   int min_val, max_val, factor;
   offsetT sval;
   bfd_boolean print_hex;
 
   operand = (const struct mips_int_operand *) operand_base;
   factor = 1 << operand->shift;
-  mask = (1 << operand_base->size) - 1;
-  max_val = (operand->max_val + operand->bias) << operand->shift;
-  min_val = max_val - (mask << operand->shift);
+  min_val = mips_int_operand_min (operand);
+  max_val = mips_int_operand_max (operand);
   if (arg->lax_max)
-    max_val = mask << operand->shift;
+    max_val = ((1 << operand_base->size) - 1) << operand->shift;
 
   if (arg->token->type == OT_CHAR && arg->token->u.ch == '(')
     /* Assume we have an elided offset.  The later match will fail
@@ -12826,61 +12825,6 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
     }
 }
 
-/* This structure holds information we know about a mips16 immediate
-   argument type.  */
-
-struct mips16_immed_operand
-{
-  /* The type code used in the argument string in the opcode table.  */
-  int type;
-  /* The number of bits in the short form of the opcode.  */
-  int nbits;
-  /* The number of bits in the extended form of the opcode.  */
-  int extbits;
-  /* The amount by which the short form is shifted when it is used;
-     for example, the sw instruction has a shift count of 2.  */
-  int shift;
-  /* The amount by which the short form is shifted when it is stored
-     into the instruction code.  */
-  int op_shift;
-  /* Non-zero if the short form is unsigned.  */
-  int unsp;
-  /* Non-zero if the extended form is unsigned.  */
-  int extu;
-  /* Non-zero if the value is PC relative.  */
-  int pcrel;
-};
-
-/* The mips16 immediate operand types.  */
-
-static const struct mips16_immed_operand mips16_immed_operands[] =
-{
-  { '<',  3,  5, 0, MIPS16OP_SH_RZ,   1, 1, 0 },
-  { '>',  3,  5, 0, MIPS16OP_SH_RX,   1, 1, 0 },
-  { '[',  3,  6, 0, MIPS16OP_SH_RZ,   1, 1, 0 },
-  { ']',  3,  6, 0, MIPS16OP_SH_RX,   1, 1, 0 },
-  { '4',  4, 15, 0, MIPS16OP_SH_IMM4, 0, 0, 0 },
-  { '5',  5, 16, 0, MIPS16OP_SH_IMM5, 1, 0, 0 },
-  { 'H',  5, 16, 1, MIPS16OP_SH_IMM5, 1, 0, 0 },
-  { 'W',  5, 16, 2, MIPS16OP_SH_IMM5, 1, 0, 0 },
-  { 'D',  5, 16, 3, MIPS16OP_SH_IMM5, 1, 0, 0 },
-  { 'j',  5, 16, 0, MIPS16OP_SH_IMM5, 0, 0, 0 },
-  { '8',  8, 16, 0, MIPS16OP_SH_IMM8, 1, 0, 0 },
-  { 'V',  8, 16, 2, MIPS16OP_SH_IMM8, 1, 0, 0 },
-  { 'C',  8, 16, 3, MIPS16OP_SH_IMM8, 1, 0, 0 },
-  { 'U',  8, 16, 0, MIPS16OP_SH_IMM8, 1, 1, 0 },
-  { 'k',  8, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 0 },
-  { 'K',  8, 16, 3, MIPS16OP_SH_IMM8, 0, 0, 0 },
-  { 'p',  8, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 1 },
-  { 'q', 11, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 1 },
-  { 'A',  8, 16, 2, MIPS16OP_SH_IMM8, 1, 0, 1 },
-  { 'B',  5, 16, 3, MIPS16OP_SH_IMM5, 1, 0, 1 },
-  { 'E',  5, 16, 2, MIPS16OP_SH_IMM5, 1, 0, 1 }
-};
-
-#define MIPS16_NUM_IMMED \
-  (sizeof mips16_immed_operands / sizeof mips16_immed_operands[0])
-
 /* Marshal immediate value VAL for an extended MIPS16 instruction.
    NBITS is the number of significant bits in VAL.  */
 
@@ -12906,6 +12850,43 @@ mips16_immed_extend (offsetT val, unsigned int nbits)
   return (extval << 16) | val;
 }
 
+/* Like decode_mips16_operand, but require the operand to be defined and
+   require it to be an integer.  */
+
+static const struct mips_int_operand *
+mips16_immed_operand (int type, bfd_boolean extended_p)
+{
+  const struct mips_operand *operand;
+
+  operand = decode_mips16_operand (type, extended_p);
+  if (!operand || (operand->type != OP_INT && operand->type != OP_PCREL))
+    abort ();
+  return (const struct mips_int_operand *) operand;
+}
+
+/* Return true if SVAL fits OPERAND.  RELOC is as for mips16_immed.  */
+
+static bfd_boolean
+mips16_immed_in_range_p (const struct mips_int_operand *operand,
+                        bfd_reloc_code_real_type reloc, offsetT sval)
+{
+  int min_val, max_val;
+
+  min_val = mips_int_operand_min (operand);
+  max_val = mips_int_operand_max (operand);
+  if (reloc != BFD_RELOC_UNUSED)
+    {
+      if (min_val < 0)
+       sval = SEXT_16BIT (sval);
+      else
+       sval &= 0xffff;
+    }
+
+  return (sval >= min_val
+         && sval <= max_val
+         && (sval & ((1 << operand->shift) - 1)) == 0);
+}
+
 /* Install immediate value VAL into MIPS16 instruction *INSN,
    extending it if necessary.  The instruction in *INSN may
    already be extended.
@@ -12922,46 +12903,11 @@ mips16_immed (char *file, unsigned int line, int type,
              bfd_reloc_code_real_type reloc, offsetT val,
              unsigned int user_insn_length, unsigned long *insn)
 {
-  const struct mips16_immed_operand *op;
-  int mintiny, maxtiny;
-
-  op = mips16_immed_operands;
-  while (op->type != type)
-    {
-      ++op;
-      gas_assert (op < mips16_immed_operands + MIPS16_NUM_IMMED);
-    }
-
-  if (op->unsp)
-    {
-      if (type == '<' || type == '>' || type == '[' || type == ']')
-       {
-         mintiny = 1;
-         maxtiny = 1 << op->nbits;
-       }
-      else
-       {
-         mintiny = 0;
-         maxtiny = (1 << op->nbits) - 1;
-       }
-      if (reloc != BFD_RELOC_UNUSED)
-       val &= 0xffff;
-    }
-  else
-    {
-      mintiny = - (1 << (op->nbits - 1));
-      maxtiny = (1 << (op->nbits - 1)) - 1;
-      if (reloc != BFD_RELOC_UNUSED)
-       val = SEXT_16BIT (val);
-    }
-
-  /* Branch offsets have an implicit 0 in the lowest bit.  */
-  if (type == 'p' || type == 'q')
-    val /= 2;
+  const struct mips_int_operand *operand;
+  unsigned int uval, length;
 
-  if ((val & ((1 << op->shift) - 1)) != 0
-      || val < (mintiny << op->shift)
-      || val > (maxtiny << op->shift))
+  operand = mips16_immed_operand (type, FALSE);
+  if (!mips16_immed_in_range_p (operand, reloc, val))
     {
       /* We need an extended instruction.  */
       if (user_insn_length == 2)
@@ -12978,37 +12924,19 @@ mips16_immed (char *file, unsigned int line, int type,
                     _("extended operand requested but not required"));
     }
 
-  if (mips16_opcode_length (*insn) == 2)
+  length = mips16_opcode_length (*insn);
+  if (length == 4)
     {
-      int insnval;
-
-      insnval = ((val >> op->shift) & ((1 << op->nbits) - 1));
-      insnval <<= op->op_shift;
-      *insn |= insnval;
+      operand = mips16_immed_operand (type, TRUE);
+      if (!mips16_immed_in_range_p (operand, reloc, val))
+       as_bad_where (file, line,
+                     _("operand value out of range for instruction"));
     }
+  uval = ((unsigned int) val >> operand->shift) - operand->bias;
+  if (length == 2)
+    *insn = mips_insert_operand (&operand->root, *insn, uval);
   else
-    {
-      long minext, maxext;
-
-      if (reloc == BFD_RELOC_UNUSED)
-       {
-         if (op->extu)
-           {
-             minext = 0;
-             maxext = (1 << op->extbits) - 1;
-           }
-         else
-           {
-             minext = - (1 << (op->extbits - 1));
-             maxext = (1 << (op->extbits - 1)) - 1;
-           }
-         if (val < minext || val > maxext)
-           as_bad_where (file, line,
-                         _("operand value out of range for instruction"));
-       }
-
-      *insn |= mips16_immed_extend (val, op->extbits);
-    }
+    *insn |= mips16_immed_extend (uval, operand->root.size);
 }
 \f
 struct percent_op_match
@@ -15744,9 +15672,8 @@ static int
 mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
 {
   int type;
-  const struct mips16_immed_operand *op;
+  const struct mips_int_operand *operand;
   offsetT val;
-  int mintiny, maxtiny;
   segT symsec;
   fragS *sym_frag;
 
@@ -15756,39 +15683,17 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
     return 1;
 
   type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
-  op = mips16_immed_operands;
-  while (op->type != type)
-    {
-      ++op;
-      gas_assert (op < mips16_immed_operands + MIPS16_NUM_IMMED);
-    }
-
-  if (op->unsp)
-    {
-      if (type == '<' || type == '>' || type == '[' || type == ']')
-       {
-         mintiny = 1;
-         maxtiny = 1 << op->nbits;
-       }
-      else
-       {
-         mintiny = 0;
-         maxtiny = (1 << op->nbits) - 1;
-       }
-    }
-  else
-    {
-      mintiny = - (1 << (op->nbits - 1));
-      maxtiny = (1 << (op->nbits - 1)) - 1;
-    }
+  operand = mips16_immed_operand (type, FALSE);
 
   sym_frag = symbol_get_frag (fragp->fr_symbol);
   val = S_GET_VALUE (fragp->fr_symbol);
   symsec = S_GET_SEGMENT (fragp->fr_symbol);
 
-  if (op->pcrel)
+  if (operand->root.type == OP_PCREL)
     {
+      const struct mips_pcrel_operand *pcrel_op;
       addressT addr;
+      offsetT maxtiny;
 
       /* We won't have the section when we are called from
          mips_relax_frag.  However, we will always have been called
@@ -15796,6 +15701,7 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
          branch to a different section, we mark it as such.  If SEC is
          NULL, and the frag is not marked, then it must be a branch to
          the same section.  */
+      pcrel_op = (const struct mips_pcrel_operand *) operand;
       if (sec == NULL)
        {
          if (RELAX_MIPS16_LONG_BRANCH (fragp->fr_subtype))
@@ -15865,7 +15771,7 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
          PC relative load or add is the instruction itself, but if it
          is in a delay slot (in which case it can not be extended) use
          the address of the instruction whose delay slot it is in.  */
-      if (type == 'p' || type == 'q')
+      if (pcrel_op->include_isa_bit)
        {
          addr += 2;
 
@@ -15877,26 +15783,21 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
 
          /* Ignore the low bit in the target, since it will be set
              for a text label.  */
-         if ((val & 1) != 0)
-           --val;
+         val &= -2;
        }
       else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
        addr -= 4;
       else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
        addr -= 2;
 
-      val -= addr & ~ ((1 << op->shift) - 1);
-
-      /* Branch offsets have an implicit 0 in the lowest bit.  */
-      if (type == 'p' || type == 'q')
-       val /= 2;
+      val -= addr & -(1 << pcrel_op->align_log2);
 
       /* If any of the shifted bits are set, we must use an extended
          opcode.  If the address depends on the size of this
          instruction, this can lead to a loop, so we arrange to always
          use an extended opcode.  We only check this when we are in
          the main relaxation loop, when SEC is NULL.  */
-      if ((val & ((1 << op->shift) - 1)) != 0 && sec == NULL)
+      if ((val & ((1 << operand->shift) - 1)) != 0 && sec == NULL)
        {
          fragp->fr_subtype =
            RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);
@@ -15904,8 +15805,8 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
        }
 
       /* If we are about to mark a frag as extended because the value
-         is precisely maxtiny + 1, then there is a chance of an
-         infinite loop as in the following code:
+         is precisely the next value above maxtiny, then there is a
+         chance of an infinite loop as in the following code:
             la $4,foo
             .skip      1020
             .align     2
@@ -15914,8 +15815,9 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
         away, so the la can be shrunk, but then foo is 0x400 away, so
         the la must be extended.  To avoid this loop, we mark the
         frag as extended if it was small, and is about to become
-        extended with a value of maxtiny + 1.  */
-      if (val == ((maxtiny + 1) << op->shift)
+        extended with the next value above maxtiny.  */
+      maxtiny = mips_int_operand_max (operand);
+      if (val == maxtiny + (1 << operand->shift)
          && ! RELAX_MIPS16_EXTENDED (fragp->fr_subtype)
          && sec == NULL)
        {
@@ -15927,12 +15829,7 @@ mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
   else if (symsec != absolute_section && sec != NULL)
     as_bad_where (fragp->fr_file, fragp->fr_line, _("unsupported relocation"));
 
-  if ((val & ((1 << op->shift) - 1)) != 0
-      || val < (mintiny << op->shift)
-      || val > (maxtiny << op->shift))
-    return 1;
-  else
-    return 0;
+  return !mips16_immed_in_range_p (operand, BFD_RELOC_UNUSED, val);
 }
 
 /* Compute the length of a branch sequence, and adjust the
@@ -16820,7 +16717,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
       int type;
-      const struct mips16_immed_operand *op;
+      const struct mips_int_operand *operand;
       offsetT val;
       char *buf;
       unsigned int user_length, length;
@@ -16828,42 +16725,41 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
       bfd_boolean ext;
 
       type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
-      op = mips16_immed_operands;
-      while (op->type != type)
-       ++op;
+      operand = mips16_immed_operand (type, FALSE);
 
       ext = RELAX_MIPS16_EXTENDED (fragp->fr_subtype);
       val = resolve_symbol_value (fragp->fr_symbol);
-      if (op->pcrel)
+      if (operand->root.type == OP_PCREL)
        {
+         const struct mips_pcrel_operand *pcrel_op;
          addressT addr;
 
+         pcrel_op = (const struct mips_pcrel_operand *) operand;
          addr = fragp->fr_address + fragp->fr_fix;
 
          /* The rules for the base address of a PC relative reloc are
              complicated; see mips16_extended_frag.  */
-         if (type == 'p' || type == 'q')
+         if (pcrel_op->include_isa_bit)
            {
              addr += 2;
              if (ext)
                addr += 2;
              /* Ignore the low bit in the target, since it will be
                  set for a text label.  */
-             if ((val & 1) != 0)
-               --val;
+             val &= -2;
            }
          else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
            addr -= 4;
          else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
            addr -= 2;
 
-         addr &= ~ (addressT) ((1 << op->shift) - 1);
+         addr &= -(1 << pcrel_op->align_log2);
          val -= addr;
 
          /* Make sure the section winds up with the alignment we have
              assumed.  */
-         if (op->shift > 0)
-           record_alignment (asec, op->shift);
+         if (operand->shift > 0)
+           record_alignment (asec, operand->shift);
        }
 
       if (ext
index 4ef1fda..9952cf8 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-03  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * mips.h (mips_pcrel_operand): Inherit from mips_int_operand.
+       (mips_int_operand_min, mips_int_operand_max): New functions.
+       (mips_decode_pcrel_operand): Use mips_decode_int_operand.
+
 2013-08-01  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * mips.h (mips_decode_reg_operand): New function.
index b299bd8..e82e4c2 100644 (file)
@@ -537,16 +537,13 @@ struct mips_reg_pair_operand
    but the rules for MIPS16 instructions like ADDIUPC are more complicated.  */
 struct mips_pcrel_operand
 {
-  struct mips_operand root;
+  /* Encodes the offset.  */
+  struct mips_int_operand root;
 
-  /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC'.  */
+  /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC',
+     which is then added to the offset encoded by ROOT.  */
   unsigned int align_log2 : 8;
 
-  /* The operand is shifted left SHIFT places and added to PC'.
-     The operand is signed if IS_SIGNED.  */
-  unsigned int shift : 8;
-  unsigned int is_signed : 1;
-
   /* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then
      reinstated.  This is true for jumps and branches and false for
      PC-relative data instructions.  */
@@ -604,6 +601,25 @@ mips_decode_int_operand (const struct mips_int_operand *operand,
   return uval;
 }
 
+/* Return the maximum value that can be encoded by OPERAND.  */
+
+static inline int
+mips_int_operand_max (const struct mips_int_operand *operand)
+{
+  return (operand->max_val + operand->bias) << operand->shift;
+}
+
+/* Return the minimum value that can be encoded by OPERAND.  */
+
+static inline int
+mips_int_operand_min (const struct mips_int_operand *operand)
+{
+  unsigned int mask;
+
+  mask = (1 << operand->root.size) - 1;
+  return mips_int_operand_max (operand) - (mask << operand->shift);
+}
+
 /* Return the register that OPERAND encodes as UVAL.  */
 
 static inline int
@@ -625,10 +641,7 @@ mips_decode_pcrel_operand (const struct mips_pcrel_operand *operand,
   bfd_vma addr;
 
   addr = base_pc & -(1 << operand->align_log2);
-  if (operand->is_signed)
-    addr += mips_signed_operand (&operand->root, uval) * (1 << operand->shift);
-  else
-    addr += uval << operand->shift;
+  addr += mips_decode_int_operand (&operand->root, uval);
   if (operand->include_isa_bit)
     addr |= base_pc & 1;
   if (operand->flip_isa_bit)
index 0d67105..2b8a9b9 100644 (file)
@@ -1,3 +1,10 @@
+2013-08-03  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * mips-formats.h (PCREL): Reorder parameters and update the definition
+       to match new mips_pcrel_operand layout.
+       (JUMP, JALX, BRANCH): Update accordingly.
+       * mips16-opc.c (decode_mips16_operand): Likewise.
+
 2013-08-01  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * micromips-opc.c (WR_s): Delete.
index c55bb27..49a0623 100644 (file)
     return &op.root; \
   }
 
-#define PCREL(SIZE, LSB, ALIGN_LOG2, SHIFT, IS_SIGNED, INCLUDE_ISA_BIT, \
+#define PCREL(SIZE, LSB, IS_SIGNED, SHIFT, ALIGN_LOG2, INCLUDE_ISA_BIT, \
               FLIP_ISA_BIT) \
   { \
     static const struct mips_pcrel_operand op = { \
-      { OP_PCREL, SIZE, LSB }, ALIGN_LOG2, SHIFT, IS_SIGNED, \
-      INCLUDE_ISA_BIT, FLIP_ISA_BIT \
+      { { OP_PCREL, SIZE, LSB }, \
+       (1 << ((SIZE) - (IS_SIGNED))) - 1, 0, SHIFT, TRUE }, \
+      ALIGN_LOG2, INCLUDE_ISA_BIT, FLIP_ISA_BIT \
     }; \
-    return &op.root; \
+    return &op.root.root; \
   }
 
 #define JUMP(SIZE, LSB, SHIFT) \
-  PCREL (SIZE, LSB, SIZE + SHIFT, SHIFT, FALSE, TRUE, FALSE)
+  PCREL (SIZE, LSB, FALSE, SHIFT, SIZE + SHIFT, TRUE, FALSE)
 
 #define JALX(SIZE, LSB, SHIFT) \
-  PCREL (SIZE, LSB, SIZE + SHIFT, SHIFT, FALSE, TRUE, TRUE)
+  PCREL (SIZE, LSB, FALSE, SHIFT, SIZE + SHIFT, TRUE, TRUE)
 
 #define BRANCH(SIZE, LSB, SHIFT) \
-  PCREL (SIZE, LSB, 0, SHIFT, TRUE, TRUE, FALSE)
+  PCREL (SIZE, LSB, TRUE, SHIFT, 0, TRUE, FALSE)
 
 #define SPECIAL(SIZE, LSB, TYPE) \
   { \
index f386962..9948741 100644 (file)
@@ -86,11 +86,11 @@ decode_mips16_operand (char type, bfd_boolean extended_p)
       case '6': SINT (16, 0);
       case '8': SINT (16, 0);
 
-      case 'A': PCREL (16, 0, 2, 0, TRUE, FALSE, FALSE);
-      case 'B': PCREL (16, 0, 3, 0, TRUE, FALSE, FALSE);
+      case 'A': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
+      case 'B': PCREL (16, 0, TRUE, 0, 3, FALSE, FALSE);
       case 'C': SINT (16, 0);
       case 'D': SINT (16, 0);
-      case 'E': PCREL (16, 0, 2, 0, TRUE, FALSE, FALSE);
+      case 'E': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
       case 'H': SINT (16, 0);
       case 'K': SINT (16, 0);
       case 'U': UINT (16, 0);
@@ -115,11 +115,11 @@ decode_mips16_operand (char type, bfd_boolean extended_p)
       case '6': UINT (6, 5);
       case '8': UINT (8, 0);
 
-      case 'A': PCREL (8, 0, 2, 2, FALSE, FALSE, FALSE);
-      case 'B': PCREL (5, 0, 3, 3, FALSE, FALSE, FALSE);
+      case 'A': PCREL (8, 0, FALSE, 2, 2, FALSE, FALSE);
+      case 'B': PCREL (5, 0, FALSE, 3, 3, FALSE, FALSE);
       case 'C': INT_ADJ (8, 0, 255, 3, FALSE); /* (0 .. 255) << 3 */
       case 'D': INT_ADJ (5, 0, 31, 3, FALSE);  /* (0 .. 31) << 3 */
-      case 'E': PCREL (5, 0, 2, 2, FALSE, FALSE, FALSE);
+      case 'E': PCREL (5, 0, FALSE, 2, 2, FALSE, FALSE);
       case 'H': INT_ADJ (5, 0, 31, 1, FALSE);  /* (0 .. 31) << 1 */
       case 'K': INT_ADJ (8, 0, 127, 3, FALSE); /* (-128 .. 127) << 3 */
       case 'U': UINT (8, 0);