(root)/
binutils-2.41/
opcodes/
cgen-opc.c
       1  /* CGEN generic opcode support.
       2  
       3     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       4  
       5     This file is part of libopcodes.
       6  
       7     This library is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3, or (at your option)
      10     any later version.
      11  
      12     It is distributed in the hope that it will be useful, but WITHOUT
      13     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      14     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      15     License for more details.
      16  
      17     You should have received a copy of the GNU General Public License along
      18     with this program; if not, write to the Free Software Foundation, Inc.,
      19     51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
      20  
      21  #include "sysdep.h"
      22  #include <stdio.h>
      23  #include "ansidecl.h"
      24  #include "libiberty.h"
      25  #include "safe-ctype.h"
      26  #include "bfd.h"
      27  #include "symcat.h"
      28  #include "opcode/cgen.h"
      29  
      30  static unsigned int hash_keyword_name
      31    (const CGEN_KEYWORD *, const char *, int);
      32  static unsigned int hash_keyword_value
      33    (const CGEN_KEYWORD *, unsigned int);
      34  static void build_keyword_hash_tables
      35    (CGEN_KEYWORD *);
      36  
      37  /* Return number of hash table entries to use for N elements.  */
      38  #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
      39  
      40  /* Look up *NAMEP in the keyword table KT.
      41     The result is the keyword entry or NULL if not found.  */
      42  
      43  const CGEN_KEYWORD_ENTRY *
      44  cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
      45  {
      46    const CGEN_KEYWORD_ENTRY *ke;
      47    const char *p,*n;
      48  
      49    if (kt->name_hash_table == NULL)
      50      build_keyword_hash_tables (kt);
      51  
      52    ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
      53  
      54    /* We do case insensitive comparisons.
      55       If that ever becomes a problem, add an attribute that denotes
      56       "do case sensitive comparisons".  */
      57  
      58    while (ke != NULL)
      59      {
      60        n = name;
      61        p = ke->name;
      62  
      63        while (*p
      64  	     && (*p == *n
      65  		 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
      66  	++n, ++p;
      67  
      68        if (!*p && !*n)
      69  	return ke;
      70  
      71        ke = ke->next_name;
      72      }
      73  
      74    if (kt->null_entry)
      75      return kt->null_entry;
      76    return NULL;
      77  }
      78  
      79  /* Look up VALUE in the keyword table KT.
      80     The result is the keyword entry or NULL if not found.  */
      81  
      82  const CGEN_KEYWORD_ENTRY *
      83  cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
      84  {
      85    const CGEN_KEYWORD_ENTRY *ke;
      86  
      87    if (kt->name_hash_table == NULL)
      88      build_keyword_hash_tables (kt);
      89  
      90    ke = kt->value_hash_table[hash_keyword_value (kt, value)];
      91  
      92    while (ke != NULL)
      93      {
      94        if (value == ke->value)
      95  	return ke;
      96        ke = ke->next_value;
      97      }
      98  
      99    return NULL;
     100  }
     101  
     102  /* Add an entry to a keyword table.  */
     103  
     104  void
     105  cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
     106  {
     107    unsigned int hash;
     108    size_t i;
     109  
     110    if (kt->name_hash_table == NULL)
     111      build_keyword_hash_tables (kt);
     112  
     113    hash = hash_keyword_name (kt, ke->name, 0);
     114    ke->next_name = kt->name_hash_table[hash];
     115    kt->name_hash_table[hash] = ke;
     116  
     117    hash = hash_keyword_value (kt, ke->value);
     118    ke->next_value = kt->value_hash_table[hash];
     119    kt->value_hash_table[hash] = ke;
     120  
     121    if (ke->name[0] == 0)
     122      kt->null_entry = ke;
     123  
     124    for (i = 1; i < strlen (ke->name); i++)
     125      if (! ISALNUM (ke->name[i])
     126  	&& ! strchr (kt->nonalpha_chars, ke->name[i]))
     127        {
     128  	size_t idx = strlen (kt->nonalpha_chars);
     129  
     130  	/* If you hit this limit, please don't just
     131  	   increase the size of the field, instead
     132  	   look for a better algorithm.  */
     133  	if (idx >= sizeof (kt->nonalpha_chars) - 1)
     134  	  abort ();
     135  	kt->nonalpha_chars[idx] = ke->name[i];
     136  	kt->nonalpha_chars[idx+1] = 0;
     137        }
     138  }
     139  
     140  /* FIXME: Need function to return count of keywords.  */
     141  
     142  /* Initialize a keyword table search.
     143     SPEC is a specification of what to search for.
     144     A value of NULL means to find every keyword.
     145     Currently NULL is the only acceptable value [further specification
     146     deferred].
     147     The result is an opaque data item used to record the search status.
     148     It is passed to each call to cgen_keyword_search_next.  */
     149  
     150  CGEN_KEYWORD_SEARCH
     151  cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
     152  {
     153    CGEN_KEYWORD_SEARCH search;
     154  
     155    /* FIXME: Need to specify format of params.  */
     156    if (spec != NULL)
     157      abort ();
     158  
     159    if (kt->name_hash_table == NULL)
     160      build_keyword_hash_tables (kt);
     161  
     162    search.table = kt;
     163    search.spec = spec;
     164    search.current_hash = 0;
     165    search.current_entry = NULL;
     166    return search;
     167  }
     168  
     169  /* Return the next keyword specified by SEARCH.
     170     The result is the next entry or NULL if there are no more.  */
     171  
     172  const CGEN_KEYWORD_ENTRY *
     173  cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
     174  {
     175    /* Has search finished?  */
     176    if (search->current_hash == search->table->hash_table_size)
     177      return NULL;
     178  
     179    /* Search in progress?  */
     180    if (search->current_entry != NULL
     181        /* Anything left on this hash chain?  */
     182        && search->current_entry->next_name != NULL)
     183      {
     184        search->current_entry = search->current_entry->next_name;
     185        return search->current_entry;
     186      }
     187  
     188    /* Move to next hash chain [unless we haven't started yet].  */
     189    if (search->current_entry != NULL)
     190      ++search->current_hash;
     191  
     192    while (search->current_hash < search->table->hash_table_size)
     193      {
     194        search->current_entry = search->table->name_hash_table[search->current_hash];
     195        if (search->current_entry != NULL)
     196  	return search->current_entry;
     197        ++search->current_hash;
     198      }
     199  
     200    return NULL;
     201  }
     202  
     203  /* Return first entry in hash chain for NAME.
     204     If CASE_SENSITIVE_P is non-zero, return a case sensitive hash.  */
     205  
     206  static unsigned int
     207  hash_keyword_name (const CGEN_KEYWORD *kt,
     208  		   const char *name,
     209  		   int case_sensitive_p)
     210  {
     211    unsigned int hash;
     212  
     213    if (case_sensitive_p)
     214      for (hash = 0; *name; ++name)
     215        hash = (hash * 97) + (unsigned char) *name;
     216    else
     217      for (hash = 0; *name; ++name)
     218        hash = (hash * 97) + (unsigned char) TOLOWER (*name);
     219    return hash % kt->hash_table_size;
     220  }
     221  
     222  /* Return first entry in hash chain for VALUE.  */
     223  
     224  static unsigned int
     225  hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
     226  {
     227    return value % kt->hash_table_size;
     228  }
     229  
     230  /* Build a keyword table's hash tables.
     231     We probably needn't build the value hash table for the assembler when
     232     we're using the disassembler, but we keep things simple.  */
     233  
     234  static void
     235  build_keyword_hash_tables (CGEN_KEYWORD *kt)
     236  {
     237    int i;
     238    /* Use the number of compiled in entries as an estimate for the
     239       typical sized table [not too many added at runtime].  */
     240    unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries);
     241  
     242    kt->hash_table_size = size;
     243    kt->name_hash_table = (CGEN_KEYWORD_ENTRY **)
     244      xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
     245    memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
     246    kt->value_hash_table = (CGEN_KEYWORD_ENTRY **)
     247      xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
     248    memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
     249  
     250    /* The table is scanned backwards as we want keywords appearing earlier to
     251       be prefered over later ones.  */
     252    for (i = kt->num_init_entries - 1; i >= 0; --i)
     253      cgen_keyword_add (kt, &kt->init_entries[i]);
     254  }
     255  
     256  /* Hardware support.  */
     257  
     258  /* Lookup a hardware element by its name.
     259     Returns NULL if NAME is not supported by the currently selected
     260     mach/isa.  */
     261  
     262  const CGEN_HW_ENTRY *
     263  cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
     264  {
     265    unsigned int i;
     266    const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
     267  
     268    for (i = 0; i < cd->hw_table.num_entries; ++i)
     269      if (hw[i] && strcmp (name, hw[i]->name) == 0)
     270        return hw[i];
     271  
     272    return NULL;
     273  }
     274  
     275  /* Lookup a hardware element by its number.
     276     Hardware elements are enumerated, however it may be possible to add some
     277     at runtime, thus HWNUM is not an enum type but rather an int.
     278     Returns NULL if HWNUM is not supported by the currently selected mach.  */
     279  
     280  const CGEN_HW_ENTRY *
     281  cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
     282  {
     283    unsigned int i;
     284    const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
     285  
     286    /* ??? This can be speeded up.  */
     287    for (i = 0; i < cd->hw_table.num_entries; ++i)
     288      if (hw[i] && hwnum == hw[i]->type)
     289        return hw[i];
     290  
     291    return NULL;
     292  }
     293  
     294  /* Operand support.  */
     295  
     296  /* Lookup an operand by its name.
     297     Returns NULL if NAME is not supported by the currently selected
     298     mach/isa.  */
     299  
     300  const CGEN_OPERAND *
     301  cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
     302  {
     303    unsigned int i;
     304    const CGEN_OPERAND **op = cd->operand_table.entries;
     305  
     306    for (i = 0; i < cd->operand_table.num_entries; ++i)
     307      if (op[i] && strcmp (name, op[i]->name) == 0)
     308        return op[i];
     309  
     310    return NULL;
     311  }
     312  
     313  /* Lookup an operand by its number.
     314     Operands are enumerated, however it may be possible to add some
     315     at runtime, thus OPNUM is not an enum type but rather an int.
     316     Returns NULL if OPNUM is not supported by the currently selected
     317     mach/isa.  */
     318  
     319  const CGEN_OPERAND *
     320  cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
     321  {
     322    return cd->operand_table.entries[opnum];
     323  }
     324  
     325  /* Instruction support.  */
     326  
     327  /* Return number of instructions.  This includes any added at runtime.  */
     328  
     329  int
     330  cgen_insn_count (CGEN_CPU_DESC cd)
     331  {
     332    int count = cd->insn_table.num_init_entries;
     333    CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
     334  
     335    for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
     336      ++count;
     337  
     338    return count;
     339  }
     340  
     341  /* Return number of macro-instructions.
     342     This includes any added at runtime.  */
     343  
     344  int
     345  cgen_macro_insn_count (CGEN_CPU_DESC cd)
     346  {
     347    int count = cd->macro_insn_table.num_init_entries;
     348    CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
     349  
     350    for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
     351      ++count;
     352  
     353    return count;
     354  }
     355  
     356  /* Cover function to read and properly byteswap an insn value.  */
     357  
     358  CGEN_INSN_INT
     359  cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length,
     360                       int endian)
     361  {
     362    int big_p = (endian == CGEN_ENDIAN_BIG);
     363    int insn_chunk_bitsize = cd->insn_chunk_bitsize;
     364    CGEN_INSN_INT value = 0;
     365  
     366    if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
     367      {
     368        /* We need to divide up the incoming value into insn_chunk_bitsize-length
     369  	 segments, and endian-convert them, one at a time. */
     370        int i;
     371  
     372        /* Enforce divisibility. */
     373        if ((length % insn_chunk_bitsize) != 0)
     374  	abort ();
     375  
     376        for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
     377  	{
     378  	  int bit_index;
     379  	  bfd_vma this_value;
     380  
     381  	  bit_index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
     382  	  this_value = bfd_get_bits (& buf[bit_index / 8], insn_chunk_bitsize, big_p);
     383  	  value = (value << insn_chunk_bitsize) | this_value;
     384  	}
     385      }
     386    else
     387      {
     388        value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG);
     389      }
     390  
     391    return value;
     392  }
     393  
     394  /* Cover function to store an insn value properly byteswapped.  */
     395  
     396  void
     397  cgen_put_insn_value (CGEN_CPU_DESC cd,
     398  		     unsigned char *buf,
     399  		     int length,
     400  		     CGEN_INSN_INT value,
     401                       int endian)
     402  {
     403    int big_p = (endian == CGEN_ENDIAN_BIG);
     404    int insn_chunk_bitsize = cd->insn_chunk_bitsize;
     405  
     406    if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
     407      {
     408        /* We need to divide up the incoming value into insn_chunk_bitsize-length
     409  	 segments, and endian-convert them, one at a time. */
     410        int i;
     411  
     412        /* Enforce divisibility. */
     413        if ((length % insn_chunk_bitsize) != 0)
     414  	abort ();
     415  
     416        for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
     417  	{
     418  	  int bit_index;
     419  
     420  	  bit_index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
     421  	  bfd_put_bits ((bfd_vma) value, & buf[bit_index / 8], insn_chunk_bitsize, big_p);
     422  	  value >>= insn_chunk_bitsize;
     423  	}
     424      }
     425    else
     426      {
     427        bfd_put_bits ((bfd_vma) value, buf, length, big_p);
     428      }
     429  }
     430  
     431  /* Look up instruction INSN_*_VALUE and extract its fields.
     432     INSN_INT_VALUE is used if CGEN_INT_INSN_P.
     433     Otherwise INSN_BYTES_VALUE is used.
     434     INSN, if non-null, is the insn table entry.
     435     Otherwise INSN_*_VALUE is examined to compute it.
     436     LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
     437     0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
     438     If INSN != NULL, LENGTH must be valid.
     439     ALIAS_P is non-zero if alias insns are to be included in the search.
     440  
     441     The result is a pointer to the insn table entry, or NULL if the instruction
     442     wasn't recognized.  */
     443  
     444  /* ??? Will need to be revisited for VLIW architectures.  */
     445  
     446  const CGEN_INSN *
     447  cgen_lookup_insn (CGEN_CPU_DESC cd,
     448  		  const CGEN_INSN *insn,
     449  		  CGEN_INSN_INT insn_int_value,
     450  		  /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
     451  		  unsigned char *insn_bytes_value,
     452  		  int length,
     453  		  CGEN_FIELDS *fields,
     454  		  int alias_p)
     455  {
     456    CGEN_EXTRACT_INFO ex_info;
     457    CGEN_EXTRACT_INFO *info;
     458  
     459    if (cd->int_insn_p)
     460      {
     461        info = NULL;
     462        insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
     463        cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value,
     464                             cd->insn_endian);
     465      }
     466    else
     467      {
     468        info = &ex_info;
     469        ex_info.dis_info = NULL;
     470        ex_info.insn_bytes = insn_bytes_value;
     471        ex_info.valid = -1;
     472        insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length,
     473                                              cd->insn_endian);
     474      }
     475  
     476    if (!insn)
     477      {
     478        const CGEN_INSN_LIST *insn_list;
     479  
     480        /* The instructions are stored in hash lists.
     481  	 Pick the first one and keep trying until we find the right one.  */
     482  
     483        insn_list = cgen_dis_lookup_insn (cd, (char *) insn_bytes_value,
     484  					insn_int_value);
     485        while (insn_list != NULL)
     486  	{
     487  	  insn = insn_list->insn;
     488  
     489  	  if (alias_p
     490  	      /* FIXME: Ensure ALIAS attribute always has same index.  */
     491  	      || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
     492  	    {
     493  	      /* Basic bit mask must be correct.  */
     494  	      /* ??? May wish to allow target to defer this check until the
     495  		 extract handler.  */
     496  	      if ((insn_int_value & CGEN_INSN_BASE_MASK (insn))
     497  		  == CGEN_INSN_BASE_VALUE (insn))
     498  		{
     499  		  /* ??? 0 is passed for `pc' */
     500  		  int elength = CGEN_EXTRACT_FN (cd, insn)
     501  		    (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
     502  		  if (elength > 0)
     503  		    {
     504  		      /* sanity check */
     505  		      if (length != 0 && length != elength)
     506  			abort ();
     507  		      break;
     508  		    }
     509  		}
     510  	    }
     511  
     512  	  insn_list = insn_list->next;
     513  	}
     514      }
     515    else
     516      {
     517        /* Sanity check: can't pass an alias insn if ! alias_p.  */
     518        if (! alias_p
     519  	  && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
     520  	abort ();
     521        /* Sanity check: length must be correct.  */
     522        if (length != CGEN_INSN_BITSIZE (insn))
     523  	abort ();
     524  
     525        /* ??? 0 is passed for `pc' */
     526        length = CGEN_EXTRACT_FN (cd, insn)
     527  	(cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
     528        /* Sanity check: must succeed.
     529  	 Could relax this later if it ever proves useful.  */
     530        if (length == 0)
     531  	abort ();
     532      }
     533  
     534    if (cd->int_insn_p)
     535      free (insn_bytes_value);
     536  
     537    return insn;
     538  }
     539  
     540  /* Fill in the operand instances used by INSN whose operands are FIELDS.
     541     INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
     542     in.  */
     543  
     544  void
     545  cgen_get_insn_operands (CGEN_CPU_DESC cd,
     546  			const CGEN_INSN *insn,
     547  			const CGEN_FIELDS *fields,
     548  			int *indices)
     549  {
     550    const CGEN_OPINST *opinst;
     551    int i;
     552  
     553    if (insn->opinst == NULL)
     554      abort ();
     555    for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
     556      {
     557        enum cgen_operand_type op_type = opinst->op_type;
     558        if (op_type == CGEN_OPERAND_NIL)
     559  	indices[i] = opinst->index;
     560        else
     561  	indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
     562      }
     563  }
     564  
     565  /* Cover function to cgen_get_insn_operands when either INSN or FIELDS
     566     isn't known.
     567     The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
     568     cgen_lookup_insn unchanged.
     569     INSN_INT_VALUE is used if CGEN_INT_INSN_P.
     570     Otherwise INSN_BYTES_VALUE is used.
     571  
     572     The result is the insn table entry or NULL if the instruction wasn't
     573     recognized.  */
     574  
     575  const CGEN_INSN *
     576  cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
     577  			       const CGEN_INSN *insn,
     578  			       CGEN_INSN_INT insn_int_value,
     579  			       /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
     580  			       unsigned char *insn_bytes_value,
     581  			       int length,
     582  			       int *indices,
     583  			       CGEN_FIELDS *fields)
     584  {
     585    /* Pass non-zero for ALIAS_P only if INSN != NULL.
     586       If INSN == NULL, we want a real insn.  */
     587    insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
     588  			   length, fields, insn != NULL);
     589    if (! insn)
     590      return NULL;
     591  
     592    cgen_get_insn_operands (cd, insn, fields, indices);
     593    return insn;
     594  }
     595  
     596  /* Allow signed overflow of instruction fields.  */
     597  void
     598  cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
     599  {
     600    cd->signed_overflow_ok_p = 1;
     601  }
     602  
     603  /* Generate an error message if a signed field in an instruction overflows.  */
     604  void
     605  cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
     606  {
     607    cd->signed_overflow_ok_p = 0;
     608  }
     609  
     610  /* Will an error message be generated if a signed field in an instruction overflows ? */
     611  unsigned int
     612  cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
     613  {
     614    return cd->signed_overflow_ok_p;
     615  }