gas/
[external/binutils.git] / gas / config / tc-mips.c
index 22ba44a..4e878c8 100644 (file)
@@ -272,6 +272,9 @@ static int file_mips_soft_float = 0;
 /* 1 if -msingle-float, 0 if -mdouble-float.  The default is 0.   */
 static int file_mips_single_float = 0;
 
+/* True if -mnan=2008, false if -mnan=legacy.  */
+static bfd_boolean mips_flag_nan2008 = FALSE;
+
 static struct mips_set_options mips_opts =
 {
   /* isa */ ISA_UNKNOWN, /* ase */ 0, /* mips16 */ -1, /* micromips */ -1,
@@ -1310,6 +1313,7 @@ static void s_gpdword (int);
 static void s_ehword (int);
 static void s_cpadd (int);
 static void s_insn (int);
+static void s_nan (int);
 static void md_obj_begin (void);
 static void md_obj_end (void);
 static void s_mips_ent (int);
@@ -1441,6 +1445,7 @@ enum options
     OPTION_PDR,
     OPTION_NO_PDR,
     OPTION_MVXWORKS_PIC,
+    OPTION_NAN,
     OPTION_END_OF_ENUM
   };
 
@@ -1556,6 +1561,7 @@ struct option md_longopts[] =
   {"mpdr", no_argument, NULL, OPTION_PDR},
   {"mno-pdr", no_argument, NULL, OPTION_NO_PDR},
   {"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC},
+  {"mnan", required_argument, NULL, OPTION_NAN},
 
   {NULL, no_argument, NULL, 0}
 };
@@ -1680,6 +1686,7 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"ehword", s_ehword, 0},
   {"cpadd", s_cpadd, 0},
   {"insn", s_insn, 0},
+  {"nan", s_nan, 0},
 
   /* Relatively generic pseudo-ops that happen to be used on MIPS
      chips.  */
@@ -1803,17 +1810,18 @@ mips_mark_labels (void)
 \f
 static char *expr_end;
 
-/* Expressions which appear in instructions.  These are set by
-   mips_ip.  */
+/* Expressions which appear in macro instructions.  These are set by
+   mips_ip and read by macro.  */
 
 static expressionS imm_expr;
 static expressionS imm2_expr;
-static expressionS offset_expr;
 
-/* Relocs associated with imm_expr and offset_expr.  */
+/* The relocatable field in an instruction and the relocs associated
+   with it.  These variables are used for instructions like LUI and
+   JAL as well as true offsets.  They are also used for address
+   operands in macros.  */
 
-static bfd_reloc_code_real_type imm_reloc[3]
-  = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
+static expressionS offset_expr;
 static bfd_reloc_code_real_type offset_reloc[3]
   = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
 
@@ -2963,9 +2971,6 @@ md_assemble (char *str)
   imm_expr.X_op = O_absent;
   imm2_expr.X_op = O_absent;
   offset_expr.X_op = O_absent;
-  imm_reloc[0] = BFD_RELOC_UNUSED;
-  imm_reloc[1] = BFD_RELOC_UNUSED;
-  imm_reloc[2] = BFD_RELOC_UNUSED;
   offset_reloc[0] = BFD_RELOC_UNUSED;
   offset_reloc[1] = BFD_RELOC_UNUSED;
   offset_reloc[2] = BFD_RELOC_UNUSED;
@@ -2995,9 +3000,7 @@ md_assemble (char *str)
     }
   else
     {
-      if (imm_expr.X_op != O_absent)
-       append_insn (&insn, &imm_expr, imm_reloc, FALSE);
-      else if (offset_expr.X_op != O_absent)
+      if (offset_expr.X_op != O_absent)
        append_insn (&insn, &offset_expr, offset_reloc, FALSE);
       else
        append_insn (&insn, NULL, unused_reloc, FALSE);
@@ -5556,12 +5559,12 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
 
        case 'C':
          gas_assert (!mips_opts.micromips);
-         INSERT_OPERAND (0, COPZ, insn, va_arg (args, unsigned long));
+         INSERT_OPERAND (0, COPZ, insn, va_arg (args, int));
          continue;
 
        case 'k':
          INSERT_OPERAND (mips_opts.micromips,
-                         CACHE, insn, va_arg (args, unsigned long));
+                         CACHE, insn, va_arg (args, int));
          continue;
 
        case '|':
@@ -5576,12 +5579,12 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
 
        case '\\':
          INSERT_OPERAND (mips_opts.micromips,
-                         3BITPOS, insn, va_arg (args, unsigned int));
+                         3BITPOS, insn, va_arg (args, int));
          continue;
 
        case '~':
          INSERT_OPERAND (mips_opts.micromips,
-                         OFFSET12, insn, va_arg (args, unsigned long));
+                         OFFSET12, insn, va_arg (args, int));
          continue;
 
        case 'N':
@@ -5685,16 +5688,6 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
          MIPS16_INSERT_OPERAND (REGR32, insn, va_arg (*args, int));
          continue;
 
-       case 'Y':
-         {
-           int regno;
-
-           regno = va_arg (*args, int);
-           regno = ((regno & 7) << 2) | ((regno & 0x18) >> 3);
-           MIPS16_INSERT_OPERAND (REG32R, insn, regno);
-         }
-         continue;
-
        case '<':
        case '>':
        case '4':
@@ -8177,26 +8170,17 @@ macro (struct mips_cl_insn *ip, char *str)
 
     case M_MSGSND:
       gas_assert (!mips_opts.micromips);
-      {
-       unsigned long temp = (treg << 16) | (0x01);
-       macro_build (NULL, "c2", "C", temp);
-      }
+      macro_build (NULL, "c2", "C", (treg << 16) | 0x01);
       break;
 
     case M_MSGLD:
       gas_assert (!mips_opts.micromips);
-      {
-       unsigned long temp = (0x02);
-       macro_build (NULL, "c2", "C", temp);
-      }
+      macro_build (NULL, "c2", "C", 0x02);
       break;
 
     case M_MSGLD_T:
       gas_assert (!mips_opts.micromips);
-      {
-       unsigned long temp = (treg << 16) | (0x02);
-       macro_build (NULL, "c2", "C", temp);
-      }
+      macro_build (NULL, "c2", "C", (treg << 16) | 0x02);
       break;
 
     case M_MSGWAIT:
@@ -8206,10 +8190,7 @@ macro (struct mips_cl_insn *ip, char *str)
 
     case M_MSGWAIT_T:
       gas_assert (!mips_opts.micromips);
-      {
-       unsigned long temp = (treg << 16) | 0x03;
-       macro_build (NULL, "c2", "C", temp);
-      }
+      macro_build (NULL, "c2", "C", (treg << 16) | 0x03);
       break;
 
     case M_J_A:
@@ -8831,7 +8812,7 @@ macro (struct mips_cl_insn *ip, char *str)
                macro_build (NULL, s, fmt, treg, breg);
              else
                macro_build (NULL, s, fmt, treg,
-                            (unsigned long) offset_expr.X_add_number, breg);
+                            (int) offset_expr.X_add_number, breg);
            }
          else
            {
@@ -8843,7 +8824,7 @@ macro (struct mips_cl_insn *ip, char *str)
              if (offbits == 0)
                macro_build (NULL, s, fmt, treg, tempreg);
              else
-               macro_build (NULL, s, fmt, treg, 0L, tempreg);
+               macro_build (NULL, s, fmt, treg, 0, tempreg);
            }
          break;
        }
@@ -8890,7 +8871,7 @@ macro (struct mips_cl_insn *ip, char *str)
            macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, tempreg);
          else
            macro_build (NULL, s, fmt, treg,
-                        (unsigned long) offset_expr.X_add_number, tempreg);
+                        (int) offset_expr.X_add_number, tempreg);
        }
       else if (offbits != 16)
        {
@@ -8904,7 +8885,7 @@ macro (struct mips_cl_insn *ip, char *str)
          if (offbits == 0)
            macro_build (NULL, s, fmt, treg, tempreg);
          else
-           macro_build (NULL, s, fmt, treg, 0L, tempreg);
+           macro_build (NULL, s, fmt, treg, 0, tempreg);
        }
       else if (mips_pic == NO_PIC)
        {
@@ -9760,7 +9741,7 @@ macro (struct mips_cl_insn *ip, char *str)
       gas_assert (!mips_opts.micromips);
       /* For now we just do C (same as Cz).  The parameter will be
          stored in insn_opcode by mips_ip.  */
-      macro_build (NULL, s, "C", ip->insn_opcode);
+      macro_build (NULL, s, "C", (int) ip->insn_opcode);
       break;
 
     case M_MOVE:
@@ -10459,8 +10440,7 @@ macro (struct mips_cl_insn *ip, char *str)
       if (!target_big_endian)
        ep->X_add_number += off;
       if (offbits == 12)
-       macro_build (NULL, s, "t,~(b)",
-                    tempreg, (unsigned long) ep->X_add_number, breg);
+       macro_build (NULL, s, "t,~(b)", tempreg, (int) ep->X_add_number, breg);
       else
        macro_build (ep, s, "t,o(b)", tempreg, -1,
                     offset_reloc[0], offset_reloc[1], offset_reloc[2], breg);
@@ -10471,7 +10451,7 @@ macro (struct mips_cl_insn *ip, char *str)
        ep->X_add_number += off;
       if (offbits == 12)
        macro_build (NULL, s2, "t,~(b)",
-                    tempreg, (unsigned long) ep->X_add_number, breg);
+                    tempreg, (int) ep->X_add_number, breg);
       else
        macro_build (ep, s2, "t,o(b)", tempreg, -1,
                     offset_reloc[0], offset_reloc[1], offset_reloc[2], breg);
@@ -11180,10 +11160,12 @@ expr_const_in_range (expressionS *ep, offsetT min, offsetT max, int bit)
          && ep->X_add_number < max << bit);
 }
 
-/* This routine assembles an instruction into its binary format.  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.  */
+/* Assemble an instruction into its binary format.  If the instruction
+   is a macro, set imm_expr, imm2_expr and offset_expr to the values
+   associated with "I", "+I" and "A" operands respectively.  Otherwise
+   store the value of the relocatable field (if any) in offset_expr.
+   In both cases set offset_reloc to the relocation operators applied
+   to offset_expr.  */
 
 static void
 mips_ip (char *str, struct mips_cl_insn *ip)
@@ -11329,9 +11311,6 @@ mips_ip (char *str, struct mips_cl_insn *ip)
       imm_expr.X_op = O_absent;
       imm2_expr.X_op = O_absent;
       offset_expr.X_op = O_absent;
-      imm_reloc[0] = BFD_RELOC_UNUSED;
-      imm_reloc[1] = BFD_RELOC_UNUSED;
-      imm_reloc[2] = BFD_RELOC_UNUSED;
       offset_reloc[0] = BFD_RELOC_UNUSED;
       offset_reloc[1] = BFD_RELOC_UNUSED;
       offset_reloc[2] = BFD_RELOC_UNUSED;
@@ -12092,6 +12071,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  {
                    int shift = 8;
                    size_t i;
+                   bfd_reloc_code_real_type r[3];
+
                    /* Check whether there is only a single bracketed expression
                       left.  If so, it must be the base register and the
                       constant must be zero.  */
@@ -12101,7 +12082,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                    /* 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);
+                   i = my_getSmallExpression (&imm_expr, r, s);
                    if ((i == 0 && (imm_expr.X_op != O_constant
                                    || imm_expr.X_add_number >= 1 << shift
                                    || imm_expr.X_add_number < -1 << shift))
@@ -12133,6 +12114,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              {
                int shift = *args == '.' ? 9 : 11;
                size_t i;
+               bfd_reloc_code_real_type r[3];
 
                /* Check whether there is only a single bracketed expression
                   left.  If so, it must be the base register and the
@@ -12143,7 +12125,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                /* 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);
+               i = my_getSmallExpression (&imm_expr, r, s);
                if ((i == 0 && (imm_expr.X_op != O_constant
                                || imm_expr.X_add_number >= 1 << shift
                                || imm_expr.X_add_number < -1 << shift))
@@ -12889,8 +12871,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 
            case 'i':           /* 16-bit unsigned immediate.  */
            case 'j':           /* 16-bit signed immediate.  */
-             *imm_reloc = BFD_RELOC_LO16;
-             if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0)
+             *offset_reloc = BFD_RELOC_LO16;
+             if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0)
                {
                  int more;
                  offsetT minval, maxval;
@@ -12908,14 +12890,14 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  else
                    minval = -0x8000, maxval = 0xffff;
 
-                 if (imm_expr.X_op != O_constant
-                     || imm_expr.X_add_number < minval
-                     || imm_expr.X_add_number > maxval)
+                 if (offset_expr.X_op != O_constant
+                     || offset_expr.X_add_number < minval
+                     || offset_expr.X_add_number > maxval)
                    {
                      if (more)
                        break;
-                     if (imm_expr.X_op == O_constant
-                         || imm_expr.X_op == O_big)
+                     if (offset_expr.X_op == O_constant
+                         || offset_expr.X_op == O_big)
                        as_bad (_("Expression out of range"));
                    }
                }
@@ -12956,13 +12938,13 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              continue;
 
            case 'u':           /* Upper 16 bits.  */
-             *imm_reloc = BFD_RELOC_LO16;
-             if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
-                 && imm_expr.X_op == O_constant
-                 && (imm_expr.X_add_number < 0
-                     || imm_expr.X_add_number >= 0x10000))
+             *offset_reloc = BFD_RELOC_LO16;
+             if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0
+                 && offset_expr.X_op == O_constant
+                 && (offset_expr.X_add_number < 0
+                     || offset_expr.X_add_number >= 0x10000))
                as_bad (_("lui expression (%lu) not in range 0..65535"),
-                       (unsigned long) imm_expr.X_add_number);
+                       (unsigned long) offset_expr.X_add_number);
              s = expr_end;
              continue;
 
@@ -13826,12 +13808,9 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 
 #define SKIP_SPACE_TABS(S) { while (*(S) == ' ' || *(S) == '\t') ++(S); }
 
-/* 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.  It also sets
-   forced_insn_length to the resulting instruction size in bytes if the
-   user explicitly requested a small or extended instruction.  */
+/* As for mips_ip, but used when assembling MIPS16 code.
+   Also set forced_insn_length to the resulting instruction size in
+   bytes if the user explicitly requested a small or extended instruction.  */
 
 static void
 mips16_ip (char *str, struct mips_cl_insn *ip)
@@ -13894,6 +13873,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
   for (;;)
     {
       bfd_boolean ok;
+      char relax_char;
 
       gas_assert (strcmp (insn->name, str) == 0);
 
@@ -13923,14 +13903,12 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
 
       create_insn (ip, insn);
       imm_expr.X_op = O_absent;
-      imm_reloc[0] = BFD_RELOC_UNUSED;
-      imm_reloc[1] = BFD_RELOC_UNUSED;
-      imm_reloc[2] = BFD_RELOC_UNUSED;
       imm2_expr.X_op = O_absent;
       offset_expr.X_op = O_absent;
       offset_reloc[0] = BFD_RELOC_UNUSED;
       offset_reloc[1] = BFD_RELOC_UNUSED;
       offset_reloc[2] = BFD_RELOC_UNUSED;
+      relax_char = 0;
       for (args = insn->args; 1; ++args)
        {
          int c;
@@ -13951,19 +13929,31 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                  offsetT value;
 
                  /* Stuff the immediate value in now, if we can.  */
-                 if (imm_expr.X_op == O_constant
-                     && *imm_reloc > BFD_RELOC_UNUSED
-                     && insn->pinfo != INSN_MACRO
-                     && calculate_reloc (*offset_reloc,
-                                         imm_expr.X_add_number, &value))
+                 if (insn->pinfo == INSN_MACRO)
+                   {
+                     gas_assert (relax_char == 0);
+                     gas_assert (*offset_reloc == BFD_RELOC_UNUSED);
+                   }
+                 else if (relax_char
+                          && offset_expr.X_op == O_constant
+                          && calculate_reloc (*offset_reloc,
+                                              offset_expr.X_add_number,
+                                              &value))
                    {
-                     mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED,
-                                   *offset_reloc, value, forced_insn_length,
-                                   &ip->insn_opcode);
-                     imm_expr.X_op = O_absent;
-                     *imm_reloc = BFD_RELOC_UNUSED;
+                     mips16_immed (NULL, 0, relax_char, *offset_reloc, value,
+                                   forced_insn_length, &ip->insn_opcode);
+                     offset_expr.X_op = O_absent;
                      *offset_reloc = BFD_RELOC_UNUSED;
                    }
+                 else if (relax_char && *offset_reloc != BFD_RELOC_UNUSED)
+                   {
+                     if (forced_insn_length == 2)
+                       as_bad (_("invalid unextended operand value"));
+                     forced_insn_length = 4;
+                     ip->insn_opcode |= MIPS16_EXTEND;
+                   }
+                 else if (relax_char)
+                   *offset_reloc = (int) BFD_RELOC_UNUSED + relax_char;
 
                  return;
                }
@@ -14134,24 +14124,14 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
            case 'U':
            case 'k':
            case 'K':
-             i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+             i = my_getSmallExpression (&offset_expr, offset_reloc, s);
              if (i > 0)
                {
-                 if (imm_expr.X_op != O_constant)
-                   {
-                     forced_insn_length = 4;
-                     ip->insn_opcode |= MIPS16_EXTEND;
-                   }
-                 else
-                   {
-                     /* We need to relax this instruction.  */
-                     *offset_reloc = *imm_reloc;
-                     *imm_reloc = (int) BFD_RELOC_UNUSED + c;
-                   }
+                 relax_char = c;
                  s = expr_end;
                  continue;
                }
-             *imm_reloc = BFD_RELOC_UNUSED;
+             *offset_reloc = BFD_RELOC_UNUSED;
              /* Fall through.  */
            case '<':
            case '>':
@@ -14159,8 +14139,8 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
            case ']':
            case '4':
            case '8':
-             my_getExpression (&imm_expr, s);
-             if (imm_expr.X_op == O_register)
+             my_getExpression (&offset_expr, s);
+             if (offset_expr.X_op == O_register)
                {
                  /* What we thought was an expression turned out to
                      be a register.  */
@@ -14170,11 +14150,11 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                      /* It looks like the expression was omitted
                         before a register indirection, which means
                         that the expression is implicitly zero.  We
-                        still set up imm_expr, so that we handle
+                        still set up offset_expr, so that we handle
                         explicit extensions correctly.  */
-                     imm_expr.X_op = O_constant;
-                     imm_expr.X_add_number = 0;
-                     *imm_reloc = (int) BFD_RELOC_UNUSED + c;
+                     offset_expr.X_op = O_constant;
+                     offset_expr.X_add_number = 0;
+                     relax_char = c;
                      continue;
                    }
 
@@ -14182,7 +14162,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                }
 
              /* We need to relax this instruction.  */
-             *imm_reloc = (int) BFD_RELOC_UNUSED + c;
+             relax_char = c;
              s = expr_end;
              continue;
 
@@ -14200,7 +14180,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                break;
 
              /* We need to relax this instruction.  */
-             *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+             relax_char = c;
              s = expr_end;
              continue;
 
@@ -14216,6 +14196,16 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
              s = expr_end;
              continue;
 
+           case 'I':
+             my_getExpression (&imm_expr, s);
+             if (imm_expr.X_op != O_big
+                 && imm_expr.X_op != O_constant)
+               insn_error = _("absolute expression required");
+             if (HAVE_32BIT_GPRS)
+               normalize_constant_expr (&imm_expr);
+             s = expr_end;
+             continue;
+
            case 'a':           /* 26 bit address */
            case 'i':
              my_getExpression (&offset_expr, s);
@@ -15262,6 +15252,18 @@ md_parse_option (int c, char *arg)
       mips_pic = VXWORKS_PIC;
       break;
 
+    case OPTION_NAN:
+      if (strcmp (arg, "2008") == 0)
+       mips_flag_nan2008 = TRUE;
+      else if (strcmp (arg, "legacy") == 0)
+       mips_flag_nan2008 = FALSE;
+      else
+       {
+         as_fatal (_("Invalid NaN setting -mnan=%s"), arg);
+         return 0;
+       }
+      break;
+
     default:
       return 0;
     }
@@ -17152,6 +17154,30 @@ s_insn (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .nan pseudo-op.  */
+
+static void
+s_nan (int ignore ATTRIBUTE_UNUSED)
+{
+  static const char str_legacy[] = "legacy";
+  static const char str_2008[] = "2008";
+  size_t i;
+
+  for (i = 0; !is_end_of_line[(unsigned char) input_line_pointer[i]]; i++);
+
+  if (i == sizeof (str_2008) - 1
+      && memcmp (input_line_pointer, str_2008, i) == 0)
+    mips_flag_nan2008 = TRUE;
+  else if (i == sizeof (str_legacy) - 1
+          && memcmp (input_line_pointer, str_legacy, i) == 0)
+    mips_flag_nan2008 = FALSE;
+  else
+    as_bad (_("Bad .nan directive"));
+
+  input_line_pointer += i;
+  demand_empty_rest_of_line ();
+}
+
 /* 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
@@ -18751,6 +18777,9 @@ mips_elf_final_processing (void)
   if (mips_32bitmode)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_32BITMODE;
 
+  if (mips_flag_nan2008)
+    elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NAN2008;
+
 #if 0 /* XXX FIXME */
   /* 32 bit code with 64 bit FP registers.  */
   if (!file_mips_fp32 && ABI_NEEDS_32BIT_REGS (mips_abi))
@@ -19588,8 +19617,16 @@ MIPS options:\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-]relax-branch    [dis]allow out-of-range branches to be relaxed\n"
-                    ));
+--[no-]relax-branch    [dis]allow out-of-range branches to be relaxed\n\
+-mnan=ENCODING         select an IEEE 754 NaN encoding convention, either of:\n"));
+
+  first = 1;
+
+  show (stream, "legacy", &column, &first);
+  show (stream, "2008", &column, &first);
+
+  fputc ('\n', stream);
+
   fprintf (stream, _("\
 -KPIC, -call_shared    generate SVR4 position independent code\n\
 -call_nonpic           generate non-PIC code that can operate with DSOs\n\