More signed overflow fixes
[deliverable/binutils-gdb.git] / opcodes / or1k-asm.c
index 98be97bda5efd71c282cf7a587f6e0959d8390fc..55668afee5e6dc72f8d8fc7b6178050268d1e077 100644 (file)
@@ -1,10 +1,11 @@
+/* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
 /* Assembler interface for targets using CGEN. -*- C -*-
    CGEN: Cpu tools GENerator
 
    THIS FILE IS MACHINE GENERATED WITH CGEN.
    - the resultant file is machine generated, cgen-asm.in isn't
 
-   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   Copyright (C) 1996-2019 Free Software Foundation, Inc.
 
    This file is part of libopcodes.
 
@@ -51,6 +52,8 @@ static const char * parse_insn_normal
 /* -- asm.c */
 
 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
+static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
+static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
 
 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
 
@@ -58,341 +61,317 @@ static const char *
 parse_disp26 (CGEN_CPU_DESC cd,
              const char ** strp,
              int opindex,
-             int opinfo,
+             int opinfo ATTRIBUTE_UNUSED,
              enum cgen_parse_operand_result * resultp,
              bfd_vma * valuep)
 {
+  const char *str = *strp;
   const char *errmsg = NULL;
-  enum cgen_parse_operand_result result_type;
+  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
 
-  if (strncasecmp (*strp, "plt(", 4) == 0)
+  if (strncasecmp (str, "plta(", 5) == 0)
     {
-      bfd_vma value;
-
-      *strp += 4;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
-                                  & result_type, & value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 2) & 0xffff;
-      *valuep = value;
-      return errmsg;
+      *strp = str + 5;
+      reloc = BFD_RELOC_OR1K_PLTA26;
+    }
+  else if (strncasecmp (str, "plt(", 4) == 0)
+    {
+      *strp = str + 4;
+      reloc = BFD_RELOC_OR1K_PLT26;
     }
-  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
-}
-
-static const char *
-parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
-{
-  const char *errmsg;
-  enum cgen_parse_operand_result result_type;
-  long ret;
 
-  if (**strp == '#')
-    ++*strp;
+  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
 
-  if (strncasecmp (*strp, "hi(", 3) == 0)
+  if (reloc != BFD_RELOC_OR1K_REL_26)
     {
-      bfd_vma value;
-
-      *strp += 3;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
-                                  & result_type, & value);
       if (**strp != ')')
        errmsg = MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-
-      ret = value;
-
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       {
-         ret >>= 16;
-         ret &= 0xffff;
-         ret = (ret ^ 0x8000) - 0x8000;
-       }
+      else
+       ++*strp;
     }
-  else if (strncasecmp (*strp, "lo(", 3) == 0)
-    {
-      bfd_vma value;
 
-      *strp += 3;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
-                                  & result_type, & value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
+  return errmsg;
+}
 
-      ret = value;
+static const char *
+parse_disp21 (CGEN_CPU_DESC cd,
+             const char ** strp,
+             int opindex,
+             int opinfo ATTRIBUTE_UNUSED,
+             enum cgen_parse_operand_result * resultp,
+             bfd_vma * valuep)
+{
+  const char *str = *strp;
+  const char *errmsg = NULL;
+  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
 
-      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       {
-         ret &= 0xffff;
-         ret = (ret ^ 0x8000) - 0x8000;
-       }
-    }
-  else if (strncasecmp (*strp, "got(", 4) == 0)
+  if (strncasecmp (str, "got(", 4) == 0)
     {
-      bfd_vma value;
-
-      *strp += 4;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
-                                  & result_type, & value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
+      *strp = str + 4;
+      reloc = BFD_RELOC_OR1K_GOT_PG21;
     }
-  else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
+  else if (strncasecmp (str, "tlsgd(", 6) == 0)
     {
-      bfd_vma value;
-
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_GOTPC_HI16,
-                                  & result_type, & value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
+      *strp = str + 6;
+      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
     }
-  else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
+  else if (strncasecmp (str, "tlsldm(", 7) == 0)
     {
-      bfd_vma value;
-
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_GOTPC_LO16,
-                                  &result_type, &value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
+      *strp = str + 7;
+      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
     }
-  else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
+  else if (strncasecmp (str, "gottp(", 6) == 0)
     {
-      bfd_vma value;
+      *strp = str + 6;
+      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
+    }
 
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_GOTOFF_HI16,
-                                  & result_type, & value);
+  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
+  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
     {
-      bfd_vma value;
-
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_GOTOFF_LO16,
-                                  &result_type, &value);
       if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
+       errmsg = MISSING_CLOSING_PARENTHESIS;
+      else
+       ++*strp;
     }
-  else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
-    {
-      bfd_vma value;
 
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_GD_HI16,
-                                  & result_type, & value);
+  return errmsg;
+}
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
-    {
-      bfd_vma value;
+enum or1k_rclass
+{
+  RCLASS_DIRECT   = 0,
+  RCLASS_GOT      = 1,
+  RCLASS_GOTPC    = 2,
+  RCLASS_GOTOFF   = 3,
+  RCLASS_TLSGD    = 4,
+  RCLASS_TLSLDM   = 5,
+  RCLASS_DTPOFF   = 6,
+  RCLASS_GOTTPOFF = 7,
+  RCLASS_TPOFF    = 8,
+};
 
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_GD_LO16,
-                                  &result_type, &value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
-    {
-      bfd_vma value;
+enum or1k_rtype
+{
+  RTYPE_LO = 0,
+  RTYPE_SLO = 1,
+  RTYPE_PO = 2,
+  RTYPE_SPO = 3,
+  RTYPE_HI = 4,
+  RTYPE_AHI = 5,
+};
 
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LDM_HI16,
-                                  & result_type, & value);
+#define RCLASS_SHIFT 3
+#define RTYPE_MASK   7
+
+static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
+  { BFD_RELOC_LO16,
+    BFD_RELOC_OR1K_SLO16,
+    BFD_RELOC_OR1K_LO13,
+    BFD_RELOC_OR1K_SLO13,
+    BFD_RELOC_HI16,
+    BFD_RELOC_HI16_S, },
+  { BFD_RELOC_OR1K_GOT16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_GOT_LO13,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED },
+  { BFD_RELOC_OR1K_GOTPC_LO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_GOTPC_HI16,
+    BFD_RELOC_UNUSED },
+  { BFD_RELOC_LO16_GOTOFF,
+    BFD_RELOC_OR1K_GOTOFF_SLO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_HI16_GOTOFF,
+    BFD_RELOC_HI16_S_GOTOFF },
+  { BFD_RELOC_OR1K_TLS_GD_LO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_GD_LO13,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_GD_HI16,
+    BFD_RELOC_UNUSED },
+  { BFD_RELOC_OR1K_TLS_LDM_LO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_LDM_LO13,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_LDM_HI16,
+    BFD_RELOC_UNUSED },
+  { BFD_RELOC_OR1K_TLS_LDO_LO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_LDO_HI16,
+    BFD_RELOC_UNUSED },
+  { BFD_RELOC_OR1K_TLS_IE_LO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_IE_LO13,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_IE_HI16,
+    BFD_RELOC_OR1K_TLS_IE_AHI16 },
+  { BFD_RELOC_OR1K_TLS_LE_LO16,
+    BFD_RELOC_OR1K_TLS_LE_SLO16,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_UNUSED,
+    BFD_RELOC_OR1K_TLS_LE_HI16,
+    BFD_RELOC_OR1K_TLS_LE_AHI16 },
+};
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
-    {
-      bfd_vma value;
+static int
+parse_reloc (const char **strp)
+{
+    const char *str = *strp;
+    enum or1k_rclass cls = RCLASS_DIRECT;
+    enum or1k_rtype typ;
 
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LDM_LO16,
-                                  &result_type, &value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
-    {
-      bfd_vma value;
+    if (strncasecmp (str, "got(", 4) == 0)
+      {
+       *strp = str + 4;
+       return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
+      }
+    if (strncasecmp (str, "gotpo(", 6) == 0)
+      {
+       *strp = str + 6;
+       return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
+      }
+    if (strncasecmp (str, "gottppo(", 8) == 0)
+      {
+       *strp = str + 8;
+       return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
+      }
+
+    if (strncasecmp (str, "gotpc", 5) == 0)
+      {
+       str += 5;
+       cls = RCLASS_GOTPC;
+      }
+    else if (strncasecmp (str, "gotoff", 6) == 0)
+      {
+       str += 6;
+       cls = RCLASS_GOTOFF;
+      }
+    else if (strncasecmp (str, "tlsgd", 5) == 0)
+      {
+       str += 5;
+       cls = RCLASS_TLSGD;
+      }
+    else if (strncasecmp (str, "tlsldm", 6) == 0)
+      {
+       str += 6;
+       cls = RCLASS_TLSLDM;
+      }
+    else if (strncasecmp (str, "dtpoff", 6) == 0)
+      {
+       str += 6;
+       cls = RCLASS_DTPOFF;
+      }
+    else if (strncasecmp (str, "gottpoff", 8) == 0)
+      {
+       str += 8;
+       cls = RCLASS_GOTTPOFF;
+      }
+    else if (strncasecmp (str, "tpoff", 5) == 0)
+      {
+       str += 5;
+       cls = RCLASS_TPOFF;
+      }
 
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LDO_HI16,
-                                  & result_type, & value);
+    if (strncasecmp (str, "hi(", 3) == 0)
+      {
+       str += 3;
+       typ = RTYPE_HI;
+      }
+    else if (strncasecmp (str, "lo(", 3) == 0)
+      {
+       str += 3;
+       typ = RTYPE_LO;
+      }
+    else if (strncasecmp (str, "ha(", 3) == 0)
+      {
+       str += 3;
+       typ = RTYPE_AHI;
+      }
+    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
+      {
+       str += 3;
+       typ = RTYPE_PO;
+      }
+    else
+      return -1;
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
-    {
-      bfd_vma value;
+    *strp = str;
+    return (cls << RCLASS_SHIFT) | typ;
+}
 
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LDO_LO16,
-                                  &result_type, &value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
-    {
-      bfd_vma value;
+static const char *
+parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
+            long *valuep, int splitp)
+{
+  const char *errmsg;
+  enum cgen_parse_operand_result result_type;
+  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
+  enum or1k_rtype reloc_type;
+  int reloc_code;
+  bfd_vma ret;
 
-      *strp += 11;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_IE_HI16,
-                                  & result_type, & value);
+  if (**strp == '#')
+    ++*strp;
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
+  reloc_code = parse_reloc (strp);
+  reloc_type = reloc_code & RTYPE_MASK;
+  if (reloc_code >= 0)
     {
-      bfd_vma value;
-
-      *strp += 11;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_IE_LO16,
-                                  &result_type, &value);
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
+      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
+      if (splitp)
+       {
+         if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
+             && reloc_class != RCLASS_GOT)
+           /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
+           reloc_type |= 1;
+         else
+           return INVALID_STORE_RELOC;
+       }
+      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
     }
-  else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
-    {
-      bfd_vma value;
-
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LE_HI16,
-                                  & result_type, & value);
 
-      if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
-      ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value = (value >> 16) & 0xffff;
-      *valuep = value;
-      return errmsg;
-    }
-  else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
+  if (reloc != BFD_RELOC_UNUSED)
     {
       bfd_vma value;
 
-      *strp += 8;
-      errmsg = cgen_parse_address (cd, strp, opindex,
-                                  BFD_RELOC_OR1K_TLS_LE_LO16,
+      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
                                   &result_type, &value);
       if (**strp != ')')
-       return MISSING_CLOSING_PARENTHESIS;
+       errmsg = MISSING_CLOSING_PARENTHESIS;
       ++*strp;
-      if (errmsg == NULL
-         && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       value &= 0xffff;
-      *valuep = value;
-      return errmsg;
+
+      ret = value;
+
+      if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+       switch (reloc_type)
+         {
+         case RTYPE_AHI:
+           ret += 0x8000;
+           /* FALLTHRU */
+         case RTYPE_HI:
+           ret >>= 16;
+           /* FALLTHRU */
+         case RTYPE_LO:
+         case RTYPE_SLO:
+           ret &= 0xffff;
+           ret = (ret ^ 0x8000) - 0x8000;
+           break;
+         case RTYPE_PO:
+         case RTYPE_SPO:
+           ret &= 0x1fff;
+           break;
+         default:
+           errmsg = INVALID_RELOC_TYPE;
+         }
     }
   else
     {
@@ -408,15 +387,88 @@ parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
 }
 
 static const char *
-parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
+parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
+{
+  return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
+}
+
+static const char *
+parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
+                   long *valuep)
 {
-  const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
+  return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
+}
+
+static const char *
+parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
+             unsigned long *valuep)
+{
+  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
+  if (errmsg == NULL)
+    *valuep &= 0xffff;
+  return errmsg;
+}
 
+static const char *
+parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
+                   unsigned long *valuep)
+{
+  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
   if (errmsg == NULL)
     *valuep &= 0xffff;
   return errmsg;
 }
 
+/* Parse register pairs with syntax rA,rB to a flag + rA value.  */
+
+static const char *
+parse_regpair (CGEN_CPU_DESC cd, const char **strp,
+              int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
+{
+  long reg1_index;
+  long reg2_index;
+  const char *errmsg;
+
+  /* The first part should just be a register.  */
+  errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
+                              &reg1_index);
+
+  /* If that worked skip the comma separator.  */
+  if (errmsg == NULL)
+    {
+      if (**strp == ',')
+       ++*strp;
+      else
+       errmsg = "Unexpected character, expected ','";
+    }
+
+  /* If that worked the next part is just another register.  */
+  if (errmsg == NULL)
+    errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
+                                &reg2_index);
+
+  /* Validate the register pair is valid and create the output value.  */
+  if (errmsg == NULL)
+    {
+      int regoffset = reg2_index - reg1_index;
+
+      if (regoffset == 1 || regoffset == 2)
+       {
+         unsigned short offsetmask;
+         unsigned short value;
+
+         offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
+         value = offsetmask | reg1_index;
+
+         *valuep = value;
+       }
+      else
+       errmsg = "Invalid register pair, offset not 1 or 2.";
+    }
+
+  return errmsg;
+}
+
 /* -- */
 
 const char * or1k_cgen_parse_operand
@@ -447,6 +499,13 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
 
   switch (opindex)
     {
+    case OR1K_OPERAND_DISP21 :
+      {
+        bfd_vma value = 0;
+        errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL,  & value);
+        fields->f_disp21 = value;
+      }
+      break;
     case OR1K_OPERAND_DISP26 :
       {
         bfd_vma value = 0;
@@ -457,8 +516,14 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
     case OR1K_OPERAND_RA :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
       break;
+    case OR1K_OPERAND_RAD32F :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
+      break;
     case OR1K_OPERAND_RADF :
-      errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
+      errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r2);
+      break;
+    case OR1K_OPERAND_RADI :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
       break;
     case OR1K_OPERAND_RASF :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
@@ -466,8 +531,14 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
     case OR1K_OPERAND_RB :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
       break;
+    case OR1K_OPERAND_RBD32F :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
+      break;
     case OR1K_OPERAND_RBDF :
-      errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
+      errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r3);
+      break;
+    case OR1K_OPERAND_RBDI :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
       break;
     case OR1K_OPERAND_RBSF :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
@@ -475,9 +546,15 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
     case OR1K_OPERAND_RD :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
       break;
+    case OR1K_OPERAND_RDD32F :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
+      break;
     case OR1K_OPERAND_RDDF :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
       break;
+    case OR1K_OPERAND_RDDI :
+      errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
+      break;
     case OR1K_OPERAND_RDSF :
       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
       break;
@@ -485,13 +562,13 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
       break;
     case OR1K_OPERAND_SIMM16_SPLIT :
-      errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
+      errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
       break;
     case OR1K_OPERAND_UIMM16 :
       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
       break;
     case OR1K_OPERAND_UIMM16_SPLIT :
-      errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
+      errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
       break;
     case OR1K_OPERAND_UIMM6 :
       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
@@ -499,7 +576,9 @@ or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
 
     default :
       /* xgettext:c-format */
-      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
+      opcodes_error_handler
+       (_("internal error: unrecognized field %d while parsing"),
+        opindex);
       abort ();
   }
 
This page took 0.031818 seconds and 4 git commands to generate.