ubsan: nios2: left shift cannot be represented in type 'int'
[deliverable/binutils-gdb.git] / cpu / or1k.opc
index 1d55fbc2841126f20ba59f6e09f659d274fd2e49..f0adcbb00a5b94ade4949d8b3594eb030e5b66ae 100644 (file)
 #undef  CGEN_DIS_HASH
 #define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
 
+/* Check applicability of instructions against machines.  */
+#define CGEN_VALIDATE_INSN_SUPPORTED
+
+extern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
+
 /* -- */
 
 /* -- opc.c */
+
+/* Special check to ensure that instruction exists for given machine.  */
+
+int
+or1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
+{
+  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
+
+  /* No mach attribute?  Assume it's supported for all machs.  */
+  if (machs == 0)
+    return 1;
+
+  return ((machs & cd->machs) != 0);
+}
+
 /* -- */
 
 /* -- asm.c */
@@ -57,156 +77,251 @@ 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 = str + 5;
+      reloc = BFD_RELOC_OR1K_PLTA26;
+    }
+  else if (strncasecmp (str, "plt(", 4) == 0)
+    {
+      *strp = str + 4;
+      reloc = BFD_RELOC_OR1K_PLT26;
+    }
 
-      *strp += 4;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
-                                  & result_type, & value);
+  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
+
+  if (reloc != BFD_RELOC_OR1K_REL_26)
+    {
       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;
+       errmsg = MISSING_CLOSING_PARENTHESIS;
+      else
+       ++*strp;
+    }
+
+  return errmsg;
+}
+
+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 (strncasecmp (str, "got(", 4) == 0)
+    {
+      *strp = str + 4;
+      reloc = BFD_RELOC_OR1K_GOT_PG21;
+    }
+  else if (strncasecmp (str, "tlsgd(", 6) == 0)
+    {
+      *strp = str + 6;
+      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
+    }
+  else if (strncasecmp (str, "tlsldm(", 7) == 0)
+    {
+      *strp = str + 7;
+      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
+    }
+  else if (strncasecmp (str, "gottp(", 6) == 0)
+    {
+      *strp = str + 6;
+      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
+    }
+
+  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
+
+  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
+    {
+      if (**strp != ')')
+       errmsg = MISSING_CLOSING_PARENTHESIS;
+      else
+       ++*strp;
     }
-  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
+
+  return errmsg;
 }
 
-enum
+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,
+};
+
+enum or1k_rtype
 {
   RTYPE_LO = 0,
-  RTYPE_HI = 1,
-  RTYPE_AHI = 2,
-  RTYPE_SLO = 3,
-
-  RTYPE_GOT      = (1 << 2),
-  RTYPE_GOTPC    = (2 << 2),
-  RTYPE_GOTOFF   = (3 << 2),
-  RTYPE_TLSGD    = (4 << 2),
-  RTYPE_TLSLDM   = (5 << 2),
-  RTYPE_DTPOFF   = (6 << 2),
-  RTYPE_GOTTPOFF = (7 << 2),
-  RTYPE_TPOFF    = (8 << 2),
+  RTYPE_SLO = 1,
+  RTYPE_PO = 2,
+  RTYPE_SPO = 3,
+  RTYPE_HI = 4,
+  RTYPE_AHI = 5,
 };
 
-static const bfd_reloc_code_real_type or1k_imm16_relocs[][4] = {
+#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_SLO16 },
+    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_OR1K_GOTPC_HI16,
     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_GOTOFF_SLO16 },
+    BFD_RELOC_HI16_S_GOTOFF },
   { BFD_RELOC_OR1K_TLS_GD_LO16,
-    BFD_RELOC_OR1K_TLS_GD_HI16,
     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_OR1K_TLS_LDM_HI16,
     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_OR1K_TLS_LDO_HI16,
     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_UNUSED },
+    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,
-    BFD_RELOC_OR1K_TLS_LE_SLO16 }
+    BFD_RELOC_OR1K_TLS_LE_AHI16 },
 };
 
 static int
 parse_reloc (const char **strp)
 {
     const char *str = *strp;
-    int ret = 0;
+    enum or1k_rclass cls = RCLASS_DIRECT;
+    enum or1k_rtype typ;
 
     if (strncasecmp (str, "got(", 4) == 0)
       {
        *strp = str + 4;
-       return RTYPE_GOT | RTYPE_LO;
+       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;
-       ret = RTYPE_GOTPC;
+       cls = RCLASS_GOTPC;
       }
     else if (strncasecmp (str, "gotoff", 6) == 0)
       {
        str += 6;
-       ret = RTYPE_GOTOFF;
+       cls = RCLASS_GOTOFF;
       }
     else if (strncasecmp (str, "tlsgd", 5) == 0)
       {
        str += 5;
-       ret = RTYPE_TLSGD;
+       cls = RCLASS_TLSGD;
       }
     else if (strncasecmp (str, "tlsldm", 6) == 0)
       {
        str += 6;
-       ret = RTYPE_TLSLDM;
+       cls = RCLASS_TLSLDM;
       }
     else if (strncasecmp (str, "dtpoff", 6) == 0)
       {
        str += 6;
-       ret = RTYPE_DTPOFF;
+       cls = RCLASS_DTPOFF;
       }
     else if (strncasecmp (str, "gottpoff", 8) == 0)
       {
        str += 8;
-       ret = RTYPE_GOTTPOFF;
+       cls = RCLASS_GOTTPOFF;
       }
     else if (strncasecmp (str, "tpoff", 5) == 0)
       {
        str += 5;
-       ret = RTYPE_TPOFF;
+       cls = RCLASS_TPOFF;
       }
 
     if (strncasecmp (str, "hi(", 3) == 0)
       {
        str += 3;
-       ret |= RTYPE_HI;
+       typ = RTYPE_HI;
       }
     else if (strncasecmp (str, "lo(", 3) == 0)
       {
        str += 3;
-       ret |= RTYPE_LO;
+       typ = RTYPE_LO;
       }
     else if (strncasecmp (str, "ha(", 3) == 0)
       {
        str += 3;
-       ret |= RTYPE_AHI;
+       typ = RTYPE_AHI;
+      }
+    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
+      {
+       str += 3;
+       typ = RTYPE_PO;
       }
     else
       return -1;
 
     *strp = str;
-    return ret;
+    return (cls << RCLASS_SHIFT) | typ;
 }
 
 static const char *
@@ -216,23 +331,28 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
-  int reloc_type;
+  enum or1k_rtype reloc_type;
+  int reloc_code;
   bfd_vma ret;
 
   if (**strp == '#')
     ++*strp;
 
-  reloc_type = parse_reloc (strp);
-  if (reloc_type >= 0)
+  reloc_code = parse_reloc (strp);
+  reloc_type = reloc_code & RTYPE_MASK;
+  if (reloc_code >= 0)
     {
+      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
       if (splitp)
        {
-         if ((reloc_type & 3) == RTYPE_LO && reloc_type != RTYPE_GOT)
-           reloc_type |= RTYPE_SLO;
+         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_type >> 2][reloc_type & 3];
+      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
     }
 
   if (reloc != BFD_RELOC_UNUSED)
@@ -248,7 +368,7 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
       ret = value;
 
       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-       switch (reloc_type & 3)
+       switch (reloc_type)
          {
          case RTYPE_AHI:
            ret += 0x8000;
@@ -261,6 +381,10 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
            ret &= 0xffff;
            ret = (ret ^ 0x8000) - 0x8000;
            break;
+         case RTYPE_PO:
+         case RTYPE_SPO:
+           ret &= 0x1fff;
+           break;
          default:
            errmsg = INVALID_RELOC_TYPE;
          }
@@ -311,6 +435,78 @@ parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
   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;
+}
+
+/* -- */
+
+/* -- dis.c */
+
+static void
+print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+              void * dis_info,
+              long value,
+              unsigned int attrs ATTRIBUTE_UNUSED,
+              bfd_vma pc ATTRIBUTE_UNUSED,
+              int length ATTRIBUTE_UNUSED)
+{
+  disassemble_info *info = dis_info;
+  char reg1_index;
+  char reg2_index;
+
+  reg1_index = value & 0x1f;
+  reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
+
+  (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
+}
+
 /* -- */
 
 /* -- ibd.h */
This page took 0.042374 seconds and 4 git commands to generate.