Multi-target: NEWS and user manual
[deliverable/binutils-gdb.git] / bfd / xtensa-isa.c
index 30ad80cfd6b6dfaec779c82f4f221de67a0cf3f6..bc55d71360ff5339183e852d3b0529e96c348756 100644 (file)
@@ -1,11 +1,11 @@
 /* Configurable Xtensa ISA support.
 /* Configurable Xtensa ISA support.
-   Copyright 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "xtensa-isa.h"
 #include "xtensa-isa-internal.h"
 #include "libbfd.h"
 #include "xtensa-isa.h"
 #include "xtensa-isa-internal.h"
@@ -63,6 +64,7 @@ xtensa_isa_error_msg (xtensa_isa isa __attribute__ ((unused)))
       } \
   } while (0)
 
       } \
   } while (0)
 
+
 \f
 /* Instruction buffers.  */
 
 \f
 /* Instruction buffers.  */
 
@@ -120,7 +122,9 @@ byte_to_bit_index (int byte_index)
    both.  */
 
 int
    both.  */
 
 int
-xtensa_insnbuf_to_chars (xtensa_isa isa, const xtensa_insnbuf insn, char *cp,
+xtensa_insnbuf_to_chars (xtensa_isa isa,
+                        const xtensa_insnbuf insn,
+                        unsigned char *cp,
                         int num_chars)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
                         int num_chars)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
@@ -176,9 +180,11 @@ xtensa_insnbuf_to_chars (xtensa_isa isa, const xtensa_insnbuf insn, char *cp,
 /* Inward conversion from byte stream to xtensa_insnbuf.  See
    xtensa_insnbuf_to_chars for a discussion of why this is complicated
    by endianness.  */
 /* Inward conversion from byte stream to xtensa_insnbuf.  See
    xtensa_insnbuf_to_chars for a discussion of why this is complicated
    by endianness.  */
-    
+
 void
 void
-xtensa_insnbuf_from_chars (xtensa_isa isa, xtensa_insnbuf insn, const char *cp,
+xtensa_insnbuf_from_chars (xtensa_isa isa,
+                          xtensa_insnbuf insn,
+                          const unsigned char *cp,
                           int num_chars)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
                           int num_chars)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
@@ -217,7 +223,7 @@ xtensa_insnbuf_from_chars (xtensa_isa isa, xtensa_insnbuf insn, const char *cp,
       int word_inx = byte_to_word_index (i);
       int bit_inx = byte_to_bit_index (i);
 
       int word_inx = byte_to_word_index (i);
       int bit_inx = byte_to_bit_index (i);
 
-      insn[word_inx] |= (*cp & 0xff) << bit_inx;
+      insn[word_inx] |= (unsigned) (*cp & 0xff) << bit_inx;
     }
 }
 
     }
 }
 
@@ -286,11 +292,12 @@ xtensa_isa_init (xtensa_isa_status *errno_p, char **error_msg_p)
       xtensa_sysreg_internal *sreg = &isa->sysregs[n];
       is_user = sreg->is_user;
 
       xtensa_sysreg_internal *sreg = &isa->sysregs[n];
       is_user = sreg->is_user;
 
-      isa->sysreg_table[is_user][sreg->number] = n;
+      if (sreg->number >= 0)
+       isa->sysreg_table[is_user][sreg->number] = n;
     }
 
   /* Set up the interface lookup table.  */
     }
 
   /* Set up the interface lookup table.  */
-  isa->interface_lookup_table = 
+  isa->interface_lookup_table =
     bfd_malloc (isa->num_interfaces * sizeof (xtensa_lookup_entry));
   CHECK_ALLOC_FOR_INIT (isa->interface_lookup_table, NULL, errno_p,
                        error_msg_p);
     bfd_malloc (isa->num_interfaces * sizeof (xtensa_lookup_entry));
   CHECK_ALLOC_FOR_INIT (isa->interface_lookup_table, NULL, errno_p,
                        error_msg_p);
@@ -303,7 +310,7 @@ xtensa_isa_init (xtensa_isa_status *errno_p, char **error_msg_p)
         sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
 
   /* Set up the funcUnit lookup table.  */
         sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
 
   /* Set up the funcUnit lookup table.  */
-  isa->funcUnit_lookup_table = 
+  isa->funcUnit_lookup_table =
     bfd_malloc (isa->num_funcUnits * sizeof (xtensa_lookup_entry));
   CHECK_ALLOC_FOR_INIT (isa->funcUnit_lookup_table, NULL, errno_p,
                        error_msg_p);
     bfd_malloc (isa->num_funcUnits * sizeof (xtensa_lookup_entry));
   CHECK_ALLOC_FOR_INIT (isa->funcUnit_lookup_table, NULL, errno_p,
                        error_msg_p);
@@ -392,7 +399,7 @@ xtensa_isa_maxlength (xtensa_isa isa)
 
 
 int
 
 
 int
-xtensa_isa_length_from_chars (xtensa_isa isa, const char *cp)
+xtensa_isa_length_from_chars (xtensa_isa isa, const unsigned char *cp)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
   return (intisa->length_decode_fn) (cp);
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
   return (intisa->length_decode_fn) (cp);
@@ -400,12 +407,17 @@ xtensa_isa_length_from_chars (xtensa_isa isa, const char *cp)
 
 
 int
 
 
 int
-xtensa_isa_num_pipe_stages (xtensa_isa isa) 
+xtensa_isa_num_pipe_stages (xtensa_isa isa)
 {
 {
-  int num_opcodes, num_uses;
   xtensa_opcode opcode;
   xtensa_funcUnit_use *use;
   xtensa_opcode opcode;
   xtensa_funcUnit_use *use;
-  int i, stage, max_stage = XTENSA_UNDEFINED;
+  int num_opcodes, num_uses;
+  int i, stage;
+  static int max_stage = XTENSA_UNDEFINED;
+
+  /* Only compute the value once.  */
+  if (max_stage != XTENSA_UNDEFINED)
+    return max_stage + 1;
 
   num_opcodes = xtensa_isa_num_opcodes (isa);
   for (opcode = 0; opcode < num_opcodes; opcode++)
 
   num_opcodes = xtensa_isa_num_opcodes (isa);
   for (opcode = 0; opcode < num_opcodes; opcode++)
@@ -533,7 +545,7 @@ xtensa_format_lookup (xtensa_isa isa, const char *fmtname)
       if (strcasecmp (fmtname, intisa->formats[fmt].name) == 0)
        return fmt;
     }
       if (strcasecmp (fmtname, intisa->formats[fmt].name) == 0)
        return fmt;
     }
-  
+
   xtisa_errno = xtensa_isa_bad_format;
   sprintf (xtisa_error_msg, "format \"%s\" not recognized", fmtname);
   return XTENSA_UNDEFINED;
   xtisa_errno = xtensa_isa_bad_format;
   sprintf (xtisa_error_msg, "format \"%s\" not recognized", fmtname);
   return XTENSA_UNDEFINED;
@@ -649,7 +661,7 @@ xtensa_opcode
 xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
 xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
-  xtensa_lookup_entry entry, *result;
+  xtensa_lookup_entry entry, *result = 0;
 
   if (!opname || !*opname)
     {
 
   if (!opname || !*opname)
     {
@@ -658,9 +670,13 @@ xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
       return XTENSA_UNDEFINED;
     }
 
       return XTENSA_UNDEFINED;
     }
 
-  entry.key = opname;
-  result = bsearch (&entry, intisa->opname_lookup_table, intisa->num_opcodes,
-                   sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+  if (intisa->num_opcodes != 0)
+    {
+      entry.key = opname;
+      result = bsearch (&entry, intisa->opname_lookup_table,
+                       intisa->num_opcodes, sizeof (xtensa_lookup_entry),
+                       xtensa_isa_name_compare);
+    }
 
   if (!result)
     {
 
   if (!result)
     {
@@ -687,12 +703,12 @@ xtensa_opcode_decode (xtensa_isa isa, xtensa_format fmt, int slot,
   slot_id = intisa->formats[fmt].slot_id[slot];
 
   opc = (intisa->slots[slot_id].opcode_decode_fn) (slotbuf);
   slot_id = intisa->formats[fmt].slot_id[slot];
 
   opc = (intisa->slots[slot_id].opcode_decode_fn) (slotbuf);
-  if (opc == XTENSA_UNDEFINED)
-    {
-      xtisa_errno = xtensa_isa_bad_opcode;
-      strcpy (xtisa_error_msg, "cannot decode opcode");
-    }
-  return opc;
+  if (opc != XTENSA_UNDEFINED)
+    return opc;
+
+  xtisa_errno = xtensa_isa_bad_opcode;
+  strcpy (xtisa_error_msg, "cannot decode opcode");
+  return XTENSA_UNDEFINED;
 }
 
 
 }
 
 
@@ -1013,15 +1029,14 @@ xtensa_operand_encode (xtensa_isa isa, xtensa_opcode opc, int opnd,
   uint32 test_val, orig_val;
 
   intop = get_operand (intisa, opc, opnd);
   uint32 test_val, orig_val;
 
   intop = get_operand (intisa, opc, opnd);
-  if (!intop) return -1;
+  if (!intop)
+    return -1;
 
   if (!intop->encode)
     {
       /* This is a default operand for a field.  How can we tell if the
         value fits in the field?  Write the value into the field,
         read it back, and then make sure we get the same value.  */
 
   if (!intop->encode)
     {
       /* This is a default operand for a field.  How can we tell if the
         value fits in the field?  Write the value into the field,
         read it back, and then make sure we get the same value.  */
-
-      xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
       static xtensa_insnbuf tmpbuf = 0;
       int slot_id;
 
       static xtensa_insnbuf tmpbuf = 0;
       int slot_id;
 
@@ -1066,9 +1081,9 @@ xtensa_operand_encode (xtensa_isa isa, xtensa_opcode opc, int opnd,
      was successfully encoded is to decode it and check if it matches
      the original value.  */
   orig_val = *valp;
      was successfully encoded is to decode it and check if it matches
      the original value.  */
   orig_val = *valp;
-  if ((*intop->encode) (valp) ||
-      (test_val = *valp, (*intop->decode) (&test_val)) ||
-      test_val != orig_val)
+  if ((*intop->encode) (valp)
+      || (test_val = *valp, (*intop->decode) (&test_val))
+      || test_val != orig_val)
     {
       xtisa_errno = xtensa_isa_bad_value;
       sprintf (xtisa_error_msg, "cannot encode operand value 0x%08x", *valp);
     {
       xtisa_errno = xtensa_isa_bad_value;
       sprintf (xtisa_error_msg, "cannot encode operand value 0x%08x", *valp);
@@ -1284,6 +1299,7 @@ xtensa_stateOperand_inout (xtensa_isa isa, xtensa_opcode opc, int stOp)
   return iclass->stateOperands[stOp].inout;
 }
 
   return iclass->stateOperands[stOp].inout;
 }
 
+
 \f
 /* Interface Operands.  */
 
 \f
 /* Interface Operands.  */
 
@@ -1349,7 +1365,7 @@ xtensa_regfile_lookup (xtensa_isa isa, const char *name)
   /* The expected number of regfiles is small; use a linear search.  */
   for (n = 0; n < intisa->num_regfiles; n++)
     {
   /* The expected number of regfiles is small; use a linear search.  */
   for (n = 0; n < intisa->num_regfiles; n++)
     {
-      if (!strcmp (intisa->regfiles[n].name, name))
+      if (!filename_cmp (intisa->regfiles[n].name, name))
        return n;
     }
 
        return n;
     }
 
@@ -1379,7 +1395,7 @@ xtensa_regfile_lookup_shortname (xtensa_isa isa, const char *shortname)
         as their parents.  */
       if (intisa->regfiles[n].parent != n)
        continue;
         as their parents.  */
       if (intisa->regfiles[n].parent != n)
        continue;
-      if (!strcmp (intisa->regfiles[n].shortname, shortname))
+      if (!filename_cmp (intisa->regfiles[n].shortname, shortname))
        return n;
     }
 
        return n;
     }
 
@@ -1434,6 +1450,7 @@ xtensa_regfile_num_entries (xtensa_isa isa, xtensa_regfile rf)
   return intisa->regfiles[rf].num_entries;
 }
 
   return intisa->regfiles[rf].num_entries;
 }
 
+
 \f
 /* Processor States.  */
 
 \f
 /* Processor States.  */
 
@@ -1453,7 +1470,7 @@ xtensa_state
 xtensa_state_lookup (xtensa_isa isa, const char *name)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
 xtensa_state_lookup (xtensa_isa isa, const char *name)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
-  xtensa_lookup_entry entry, *result;
+  xtensa_lookup_entry entry, *result = 0;
 
   if (!name || !*name)
     {
 
   if (!name || !*name)
     {
@@ -1462,9 +1479,12 @@ xtensa_state_lookup (xtensa_isa isa, const char *name)
       return XTENSA_UNDEFINED;
     }
 
       return XTENSA_UNDEFINED;
     }
 
-  entry.key = name;
-  result = bsearch (&entry, intisa->state_lookup_table, intisa->num_states,
-                   sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+  if (intisa->num_states != 0)
+    {
+      entry.key = name;
+      result = bsearch (&entry, intisa->state_lookup_table, intisa->num_states,
+                       sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+    }
 
   if (!result)
     {
 
   if (!result)
     {
@@ -1505,6 +1525,18 @@ xtensa_state_is_exported (xtensa_isa isa, xtensa_state st)
   return 0;
 }
 
   return 0;
 }
 
+
+int
+xtensa_state_is_shared_or (xtensa_isa isa, xtensa_state st)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  CHECK_STATE (intisa, st, XTENSA_UNDEFINED);
+  if ((intisa->states[st].flags & XTENSA_STATE_IS_SHARED_OR) != 0)
+    return 1;
+  return 0;
+}
+
+
 \f
 /* Sysregs.  */
 
 \f
 /* Sysregs.  */
 
@@ -1544,7 +1576,7 @@ xtensa_sysreg
 xtensa_sysreg_lookup_name (xtensa_isa isa, const char *name)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
 xtensa_sysreg_lookup_name (xtensa_isa isa, const char *name)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
-  xtensa_lookup_entry entry, *result;
+  xtensa_lookup_entry entry, *result = 0;
 
   if (!name || !*name)
     {
 
   if (!name || !*name)
     {
@@ -1553,9 +1585,13 @@ xtensa_sysreg_lookup_name (xtensa_isa isa, const char *name)
       return XTENSA_UNDEFINED;
     }
 
       return XTENSA_UNDEFINED;
     }
 
-  entry.key = name;
-  result = bsearch (&entry, intisa->sysreg_lookup_table, intisa->num_sysregs,
-                   sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+  if (intisa->num_sysregs != 0)
+    {
+      entry.key = name;
+      result = bsearch (&entry, intisa->sysreg_lookup_table,
+                       intisa->num_sysregs, sizeof (xtensa_lookup_entry),
+                       xtensa_isa_name_compare);
+    }
 
   if (!result)
     {
 
   if (!result)
     {
@@ -1596,6 +1632,7 @@ xtensa_sysreg_is_user (xtensa_isa isa, xtensa_sysreg sysreg)
   return 0;
 }
 
   return 0;
 }
 
+
 \f
 /* Interfaces.  */
 
 \f
 /* Interfaces.  */
 
@@ -1615,7 +1652,7 @@ xtensa_interface
 xtensa_interface_lookup (xtensa_isa isa, const char *ifname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
 xtensa_interface_lookup (xtensa_isa isa, const char *ifname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
-  xtensa_lookup_entry entry, *result;
+  xtensa_lookup_entry entry, *result = 0;
 
   if (!ifname || !*ifname)
     {
 
   if (!ifname || !*ifname)
     {
@@ -1624,10 +1661,13 @@ xtensa_interface_lookup (xtensa_isa isa, const char *ifname)
       return XTENSA_UNDEFINED;
     }
 
       return XTENSA_UNDEFINED;
     }
 
-  entry.key = ifname;
-  result = bsearch (&entry, intisa->interface_lookup_table,
-                   intisa->num_interfaces,
-                   sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+  if (intisa->num_interfaces != 0)
+    {
+      entry.key = ifname;
+      result = bsearch (&entry, intisa->interface_lookup_table,
+                       intisa->num_interfaces, sizeof (xtensa_lookup_entry),
+                       xtensa_isa_name_compare);
+    }
 
   if (!result)
     {
 
   if (!result)
     {
@@ -1677,6 +1717,16 @@ xtensa_interface_has_side_effect (xtensa_isa isa, xtensa_interface intf)
   return 0;
 }
 
   return 0;
 }
 
+
+int
+xtensa_interface_class_id (xtensa_isa isa, xtensa_interface intf)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  CHECK_INTERFACE (intisa, intf, XTENSA_UNDEFINED);
+  return intisa->interfaces[intf].class_id;
+}
+
+
 \f
 /* Functional Units.  */
 
 \f
 /* Functional Units.  */
 
@@ -1696,7 +1746,7 @@ xtensa_funcUnit
 xtensa_funcUnit_lookup (xtensa_isa isa, const char *fname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
 xtensa_funcUnit_lookup (xtensa_isa isa, const char *fname)
 {
   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
-  xtensa_lookup_entry entry, *result;
+  xtensa_lookup_entry entry, *result = 0;
 
   if (!fname || !*fname)
     {
 
   if (!fname || !*fname)
     {
@@ -1705,10 +1755,13 @@ xtensa_funcUnit_lookup (xtensa_isa isa, const char *fname)
       return XTENSA_UNDEFINED;
     }
 
       return XTENSA_UNDEFINED;
     }
 
-  entry.key = fname;
-  result = bsearch (&entry, intisa->funcUnit_lookup_table,
-                   intisa->num_funcUnits,
-                   sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+  if (intisa->num_funcUnits != 0)
+    {
+      entry.key = fname;
+      result = bsearch (&entry, intisa->funcUnit_lookup_table,
+                       intisa->num_funcUnits, sizeof (xtensa_lookup_entry),
+                       xtensa_isa_name_compare);
+    }
 
   if (!result)
     {
 
   if (!result)
     {
This page took 0.030149 seconds and 4 git commands to generate.