Add MTE register set support for core files
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
index 7541b74d23034a10fa79bc00925a0d022d805323..78e8e80eed92a31d5f9ca64b8be4e4f5e2a72674 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction printing code for the ARC.
-   Copyright (C) 1994-2017 Free Software Foundation, Inc.
+   Copyright (C) 1994-2021 Free Software Foundation, Inc.
 
    Contributed by Claudiu Zissulescu (claziss@synopsys.com)
 
@@ -61,7 +61,7 @@ struct arc_disassemble_info
   unsigned insn_len;
 
   /* TRUE if we have limm.  */
-  bfd_boolean limm_p;
+  bool limm_p;
 
   /* LIMM value, if exists.  */
   unsigned limm;
@@ -90,7 +90,7 @@ static const char * const regnames[64] =
   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
   "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
-  "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
+  "r56", "r57", "r58", "r59", "lp_count", "reserved", "LIMM", "pcl"
 };
 
 static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
@@ -123,7 +123,7 @@ static linkclass decodelist = NULL;
 static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
 
 /* True if we want to print using only hex numbers.  */
-static bfd_boolean print_hex = FALSE;
+static bool print_hex = false;
 
 /* Macros section.  */
 
@@ -137,24 +137,23 @@ static bfd_boolean print_hex = FALSE;
   (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))   \
    : bfd_getb32 (buf))
 
-#define BITS(word,s,e)  (((word) << (sizeof (word) * 8 - 1 - e)) >>    \
-                        (s + (sizeof (word) * 8 - 1 - e)))
+#define BITS(word,s,e)  (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
 #define OPCODE_32BIT_INSN(word)        (BITS ((word), 27, 31))
 
 /* Functions implementation.  */
 
 /* Initialize private data.  */
-static bfd_boolean
+static bool
 init_arc_disasm_info (struct disassemble_info *info)
 {
   struct arc_disassemble_info *arc_infop
     = calloc (sizeof (*arc_infop), 1);
 
   if (arc_infop == NULL)
-    return FALSE;
+    return false;
 
   info->private_data = arc_infop;
-  return TRUE;
+  return true;
 }
 
 /* Add a new element to the decode list.  */
@@ -174,15 +173,17 @@ add_to_decodelist (insn_class_t     insn_class,
 /* Return TRUE if we need to skip the opcode from being
    disassembled.  */
 
-static bfd_boolean
+static bool
 skip_this_opcode (const struct arc_opcode *opcode)
 {
   linkclass t = decodelist;
 
   /* Check opcode for major 0x06, return if it is not in.  */
   if (arc_opcode_len (opcode) == 4
-      && OPCODE_32BIT_INSN (opcode->opcode) != 0x06)
-    return FALSE;
+      && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
+         /* Can be an APEX extensions.  */
+         && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
+    return false;
 
   /* or not a known truble class.  */
   switch (opcode->insn_class)
@@ -190,20 +191,21 @@ skip_this_opcode (const struct arc_opcode *opcode)
     case FLOAT:
     case DSP:
     case ARITH:
+    case MPY:
       break;
     default:
-      return FALSE;
+      return false;
     }
 
   while (t != NULL)
     {
       if ((t->insn_class == opcode->insn_class)
          && (t->subclass == opcode->subclass))
-       return FALSE;
+       return false;
       t = t->nxt;
     }
 
-  return TRUE;
+  return true;
 }
 
 static bfd_vma
@@ -216,7 +218,7 @@ bfd_getm32 (unsigned int data)
   return value;
 }
 
-static bfd_boolean
+static bool
 special_flag_p (const char *opname,
                const char *flgname)
 {
@@ -238,10 +240,10 @@ special_flag_p (const char *opname,
            break; /* End of the array.  */
 
          if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
-           return TRUE;
+           return true;
        }
     }
-  return FALSE;
+  return false;
 }
 
 /* Find opcode from ARC_TABLE given the instruction described by INSN and
@@ -253,19 +255,19 @@ find_format_from_table (struct disassemble_info *info,
                         unsigned long long insn,
                        unsigned int insn_len,
                         unsigned isa_mask,
-                       bfd_boolean *has_limm,
-                       bfd_boolean overlaps)
+                       bool *has_limm,
+                       bool overlaps)
 {
   unsigned int i = 0;
   const struct arc_opcode *opcode = NULL;
   const struct arc_opcode *t_op = NULL;
   const unsigned char *opidx;
   const unsigned char *flgidx;
-  bfd_boolean warn_p = FALSE;
+  bool warn_p = false;
 
   do
     {
-      bfd_boolean invalid = FALSE;
+      bool invalid = false;
 
       opcode = &arc_table[i++];
 
@@ -278,7 +280,7 @@ find_format_from_table (struct disassemble_info *info,
       if ((insn & opcode->mask) != opcode->opcode)
        continue;
 
-      *has_limm = FALSE;
+      *has_limm = false;
 
       /* Possible candidate, check the operands.  */
       for (opidx = opcode->operands; *opidx; opidx++)
@@ -292,7 +294,7 @@ find_format_from_table (struct disassemble_info *info,
          if (operand->extract)
            value = (*operand->extract) (insn, &invalid);
          else
-           value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+           value = (insn >> operand->shift) & ((1ull << operand->bits) - 1);
 
          /* Check for LIMM indicator.  If it is there, then make sure
             we pick the right format.  */
@@ -303,14 +305,14 @@ find_format_from_table (struct disassemble_info *info,
              if ((value == 0x3E && insn_len == 4)
                  || (value == limmind && insn_len == 2))
                {
-                 invalid = TRUE;
+                 invalid = true;
                  break;
                }
            }
 
          if (operand->flags & ARC_OPERAND_LIMM
              && !(operand->flags & ARC_OPERAND_DUPLICATE))
-           *has_limm = TRUE;
+           *has_limm = true;
        }
 
       /* Check the flags.  */
@@ -349,7 +351,7 @@ find_format_from_table (struct disassemble_info *info,
 
          if (!foundA && foundB)
            {
-             invalid = TRUE;
+             invalid = true;
              break;
            }
        }
@@ -360,7 +362,7 @@ find_format_from_table (struct disassemble_info *info,
       if (insn_len == 4
          && overlaps)
        {
-         warn_p = TRUE;
+         warn_p = true;
          t_op = opcode;
          if (skip_this_opcode (opcode))
            continue;
@@ -408,7 +410,7 @@ find_format_from_table (struct disassemble_info *info,
    that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
    operands.  */
 
-static bfd_boolean
+static bool
 find_format (bfd_vma                       memaddr,
             unsigned long long            insn,
             unsigned int *                insn_len,
@@ -418,7 +420,7 @@ find_format (bfd_vma                       memaddr,
              struct arc_operand_iterator * iter)
 {
   const struct arc_opcode *opcode = NULL;
-  bfd_boolean needs_limm;
+  bool needs_limm = false;
   const extInstruction_t *einsn, *i;
   unsigned limm = 0;
   struct arc_disassemble_info *arc_infop = info->private_data;
@@ -434,23 +436,24 @@ find_format (bfd_vma                       memaddr,
          opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
          if (opcode == NULL)
            {
-             (*info->fprintf_func) (info->stream, "\
-An error occured while generating the extension instruction operations");
+             (*info->fprintf_func) (info->stream,
+                                    _("An error occurred while generating the "
+                                      "extension instruction operations"));
              *opcode_result = NULL;
-             return FALSE;
+             return false;
            }
 
          opcode = find_format_from_table (info, opcode, insn, *insn_len,
-                                          isa_mask, &needs_limm, FALSE);
+                                          isa_mask, &needs_limm, false);
        }
     }
 
   /* Then, try finding the first match in the opcode table.  */
   if (opcode == NULL)
     opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
-                                    isa_mask, &needs_limm, TRUE);
+                                    isa_mask, &needs_limm, true);
 
-  if (needs_limm && opcode != NULL)
+  if (opcode != NULL && needs_limm)
     {
       bfd_byte buffer[4];
       int status;
@@ -480,10 +483,10 @@ An error occured while generating the extension instruction operations");
 
   /* Update private data.  */
   arc_infop->opcode = opcode;
-  arc_infop->limm = (needs_limm) ? limm : 0;
+  arc_infop->limm = limm;
   arc_infop->limm_p = needs_limm;
 
-  return TRUE;
+  return true;
 }
 
 static void
@@ -669,7 +672,7 @@ arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
       break;
 
     default:
-      abort ();
+      return 0;
     }
 }
 
@@ -691,7 +694,7 @@ extract_operand_value (const struct arc_operand *operand,
   else
     {
       if (operand->extract)
-        value = (*operand->extract) (insn, (int *) NULL);
+       value = (*operand->extract) (insn, (bool *) NULL);
       else
         {
           if (operand->flags & ARC_OPERAND_ALIGNED32)
@@ -721,7 +724,7 @@ extract_operand_value (const struct arc_operand *operand,
    into VALUE.  If there is no operand returned then OPERAND and VALUE are
    unchanged.  */
 
-static bfd_boolean
+static bool
 operand_iterator_next (struct arc_operand_iterator *iter,
                        const struct arc_operand **operand,
                        int *value)
@@ -729,14 +732,14 @@ operand_iterator_next (struct arc_operand_iterator *iter,
   if (*iter->opidx == 0)
     {
       *operand = NULL;
-      return FALSE;
+      return false;
     }
 
   *operand = &arc_operands[*iter->opidx];
   *value = extract_operand_value (*operand, iter->insn, iter->limm);
   iter->opidx++;
 
-  return TRUE;
+  return true;
 }
 
 /* Helper for parsing the options.  */
@@ -764,6 +767,23 @@ parse_option (const char *option)
   else if (disassembler_options_cmp (option, "fpuda") == 0)
     add_to_decodelist (FLOAT, DPA);
 
+  else if (disassembler_options_cmp (option, "nps400") == 0)
+    {
+      add_to_decodelist (ACL, NPS400);
+      add_to_decodelist (ARITH, NPS400);
+      add_to_decodelist (BITOP, NPS400);
+      add_to_decodelist (BMU, NPS400);
+      add_to_decodelist (CONTROL, NPS400);
+      add_to_decodelist (DMA, NPS400);
+      add_to_decodelist (DPI, NPS400);
+      add_to_decodelist (MEMORY, NPS400);
+      add_to_decodelist (MISC, NPS400);
+      add_to_decodelist (NET, NPS400);
+      add_to_decodelist (PMU, NPS400);
+      add_to_decodelist (PROTOCOL_DECODE, NPS400);
+      add_to_decodelist (ULTRAIP, NPS400);
+    }
+
   else if (disassembler_options_cmp (option, "fpus") == 0)
     {
       add_to_decodelist (FLOAT, SP);
@@ -775,10 +795,11 @@ parse_option (const char *option)
       add_to_decodelist (FLOAT, DP);
       add_to_decodelist (FLOAT, CVT);
     }
-  else if (CONST_STRNEQ (option, "hex"))
-    print_hex = TRUE;
+  else if (startswith (option, "hex"))
+    print_hex = true;
   else
-    fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
+    /* xgettext:c-format */
+    opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
 }
 
 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)                  \
@@ -820,7 +841,8 @@ parse_cpu_option (const char *option)
        }
     }
 
-  fprintf (stderr, _("Unrecognised disassembler CPU option: %s\n"), option);
+  /* xgettext:c-format */
+  opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
   return ARC_OPCODE_NONE;
 }
 
@@ -919,13 +941,14 @@ print_insn_arc (bfd_vma memaddr,
   unsigned long long insn = 0;
   unsigned isa_mask = ARC_OPCODE_NONE;
   const struct arc_opcode *opcode;
-  bfd_boolean need_comma;
-  bfd_boolean open_braket;
+  bool need_comma;
+  bool open_braket;
   int size;
   const struct arc_operand *operand;
-  int value;
+  int value, vpcl;
   struct arc_operand_iterator iter;
   struct arc_disassemble_info *arc_infop;
+  bool rpcl = false, rset = false;
 
   if (info->disassembler_options)
     {
@@ -986,7 +1009,6 @@ print_insn_arc (bfd_vma memaddr,
      the number of bytes objdump should display on a single line.  If
      the instruction decoder sets this, it should always set it to
      the same value in order to get reasonable looking output.  */
-
   info->bytes_per_line  = 8;
 
   /* In the next lines, we set two info variables control the way
@@ -994,7 +1016,6 @@ print_insn_arc (bfd_vma memaddr,
      8 and bytes_per_chunk is 4, the output will look like this:
      00:   00000000 00000000
      with the chunks displayed according to "display_endian".  */
-
   if (info->section
       && !(info->section->flags & SEC_CODE))
     {
@@ -1022,6 +1043,7 @@ print_insn_arc (bfd_vma memaddr,
 
   /* Read the insn into a host word.  */
   status = (*info->read_memory_func) (memaddr, buffer, size, info);
+
   if (status != 0)
     {
       (*info->memory_error_func) (status, memaddr, info);
@@ -1048,13 +1070,16 @@ print_insn_arc (bfd_vma memaddr,
          (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
          break;
        default:
-         abort ();
+         return -1;
        }
       return size;
     }
 
   insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
   pr_debug ("instruction length = %d bytes\n", insn_len);
+  if (insn_len == 0)
+    return -1;
+
   arc_infop = info->private_data;
   arc_infop->insn_len = insn_len;
 
@@ -1107,7 +1132,7 @@ print_insn_arc (bfd_vma memaddr,
 
     default:
       /* There is no instruction whose length is not 2, 4, 6, or 8.  */
-      abort ();
+      return -1;
     }
 
   pr_debug ("instruction value = %llx\n", insn);
@@ -1121,7 +1146,7 @@ print_insn_arc (bfd_vma memaddr,
   info->target2                   = 0;
 
   /* FIXME to be moved in dissasemble_init_for_target.  */
-  info->disassembler_needs_relocs = TRUE;
+  info->disassembler_needs_relocs = true;
 
   /* Find the first match in the opcode table.  */
   if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
@@ -1132,27 +1157,31 @@ print_insn_arc (bfd_vma memaddr,
       switch (insn_len)
        {
        case 2:
-         (*info->fprintf_func) (info->stream, ".long %#04llx",
+         (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
                                 insn & 0xffff);
          break;
+
        case 4:
-         (*info->fprintf_func) (info->stream, ".long %#08llx",
+         (*info->fprintf_func) (info->stream, ".word\t%#08llx",
                                 insn & 0xffffffff);
          break;
+
        case 6:
-         (*info->fprintf_func) (info->stream, ".long %#08llx",
+         (*info->fprintf_func) (info->stream, ".long\t%#08llx",
                                 insn & 0xffffffff);
-         (*info->fprintf_func) (info->stream, ".long %#04llx",
+         (*info->fprintf_func) (info->stream, ".long\t%#04llx",
                                 (insn >> 32) & 0xffff);
          break;
+
        case 8:
-         (*info->fprintf_func) (info->stream, ".long %#08llx",
+         (*info->fprintf_func) (info->stream, ".long\t%#08llx",
                                 insn & 0xffffffff);
-         (*info->fprintf_func) (info->stream, ".long %#08llx",
+         (*info->fprintf_func) (info->stream, ".long\t%#08llx",
                                 insn >> 32);
          break;
+
        default:
-         abort ();
+         return -1;
        }
 
       info->insn_type = dis_noninsn;
@@ -1172,18 +1201,19 @@ print_insn_arc (bfd_vma memaddr,
   if (opcode->operands[0] != 0)
     (*info->fprintf_func) (info->stream, "\t");
 
-  need_comma = FALSE;
-  open_braket = FALSE;
+  need_comma = false;
+  open_braket = false;
   arc_infop->operands_count = 0;
 
   /* Now extract and print the operands.  */
   operand = NULL;
+  vpcl = 0;
   while (operand_iterator_next (&iter, &operand, &value))
     {
       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
        {
          (*info->fprintf_func) (info->stream, "]");
-         open_braket = FALSE;
+         open_braket = false;
          continue;
        }
 
@@ -1208,12 +1238,26 @@ print_insn_arc (bfd_vma memaddr,
       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
        {
          (*info->fprintf_func) (info->stream, "[");
-         open_braket = TRUE;
-         need_comma = FALSE;
+         open_braket = true;
+         need_comma = false;
          continue;
        }
 
-      need_comma = TRUE;
+      need_comma = true;
+
+      if (operand->flags & ARC_OPERAND_PCREL)
+       {
+         rpcl = true;
+         vpcl = value;
+         rset = true;
+
+         info->target = (bfd_vma) (memaddr & ~3) + value;
+       }
+      else if (!(operand->flags & ARC_OPERAND_IR))
+       {
+         vpcl = value;
+         rset = true;
+       }
 
       /* Print the operand as directed by the flags.  */
       if (operand->flags & ARC_OPERAND_IR)
@@ -1225,13 +1269,25 @@ print_insn_arc (bfd_vma memaddr,
          if (!rname)
            rname = regnames[value];
          (*info->fprintf_func) (info->stream, "%s", rname);
+
+         /* Check if we have a double register to print.  */
          if (operand->flags & ARC_OPERAND_TRUNCATE)
            {
-             rname = arcExtMap_coreRegName (value + 1);
-             if (!rname)
-               rname = regnames[value + 1];
+             if ((value & 0x01) == 0)
+               {
+                 rname = arcExtMap_coreRegName (value + 1);
+                 if (!rname)
+                   rname = regnames[value + 1];
+               }
+             else
+               rname = _("\nWarning: illegal use of double register "
+                         "pair.\n");
              (*info->fprintf_func) (info->stream, "%s", rname);
            }
+         if (value == 63)
+           rpcl = true;
+         else
+           rpcl = false;
        }
       else if (operand->flags & ARC_OPERAND_LIMM)
        {
@@ -1247,15 +1303,6 @@ print_insn_arc (bfd_vma memaddr,
                info->target = (bfd_vma) value;
            }
        }
-      else if (operand->flags & ARC_OPERAND_PCREL)
-       {
-          /* PCL relative.  */
-         if (info->flags & INSN_HAS_RELOC)
-           memaddr = 0;
-         (*info->print_address_func) ((memaddr & ~3) + value, info);
-
-         info->target = (bfd_vma) (memaddr & ~3) + value;
-       }
       else if (operand->flags & ARC_OPERAND_SIGNED)
        {
          const char *rname = get_auxreg (opcode, value, isa_mask);
@@ -1274,7 +1321,7 @@ print_insn_arc (bfd_vma memaddr,
          const char *addrtype = get_addrtype (value);
          (*info->fprintf_func) (info->stream, "%s", addrtype);
          /* A colon follow an address type.  */
-         need_comma = FALSE;
+         need_comma = false;
        }
       else
        {
@@ -1283,10 +1330,11 @@ print_insn_arc (bfd_vma memaddr,
              && !(operand->flags & ARC_OPERAND_ALIGNED16)
              && value >= 0 && value <= 14)
            {
+             /* Leave/Enter mnemonics.  */
              switch (value)
                {
                case 0:
-                 need_comma = FALSE;
+                 need_comma = false;
                  break;
                case 1:
                  (*info->fprintf_func) (info->stream, "r13");
@@ -1296,6 +1344,8 @@ print_insn_arc (bfd_vma memaddr,
                                         regnames[13 + value - 1]);
                  break;
                }
+             rpcl = false;
+             rset = false;
            }
          else
            {
@@ -1326,6 +1376,21 @@ print_insn_arc (bfd_vma memaddr,
       arc_infop->operands_count ++;
     }
 
+  /* Pretty print extra info for pc-relative operands.  */
+  if (rpcl && rset)
+    {
+      if (info->flags & INSN_HAS_RELOC)
+       /* If the instruction has a reloc associated with it, then the
+          offset field in the instruction will actually be the addend
+          for the reloc.  (We are using REL type relocs).  In such
+          cases, we can ignore the pc when computing addresses, since
+          the addend is not currently pc-relative.  */
+       memaddr = 0;
+
+      (*info->fprintf_func) (info->stream, "\t;");
+      (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
+    }
+
   return insn_len;
 }
 
@@ -1379,6 +1444,8 @@ with -M switch (multiple options should be separated by commas):\n"));
   fprintf (stream, _("\
   fpud            Recognize double precision FPU instructions.\n"));
   fprintf (stream, _("\
+  nps400          Recognize NPS400 instructions.\n"));
+  fprintf (stream, _("\
   hex             Use only hexadecimal number to print immediates.\n"));
 }
 
@@ -1396,7 +1463,7 @@ void arc_insn_decode (bfd_vma addr,
   /* There was an error when disassembling, for example memory read error.  */
   if (disasm_func (addr, info) < 0)
     {
-      insn->valid = FALSE;
+      insn->valid = false;
       return;
     }
 
@@ -1409,11 +1476,11 @@ void arc_insn_decode (bfd_vma addr,
   /* Quick exit if memory at this address is not an instruction.  */
   if (info->insn_type == dis_noninsn)
     {
-      insn->valid = FALSE;
+      insn->valid = false;
       return;
     }
 
-  insn->valid = TRUE;
+  insn->valid = true;
 
   opcode = (const struct arc_opcode *) arc_infop->opcode;
   insn->insn_class = opcode->insn_class;
This page took 0.033683 seconds and 4 git commands to generate.