Multiarch NUM_REGS for MIPS.
[deliverable/binutils-gdb.git] / opcodes / cgen-opc.c
index ede3adde1153146e1c7398e237bd593d20159cf6..06544ca057d0c1e2d4e0dad07a5e42b2c30df677 100644 (file)
@@ -1,6 +1,7 @@
 /* CGEN generic opcode support.
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils and GDB, the GNU debugger.
 
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "sysdep.h"
-#include <ctype.h>
 #include <stdio.h>
 #include "ansidecl.h"
 #include "libiberty.h"
+#include "safe-ctype.h"
 #include "bfd.h"
 #include "symcat.h"
 #include "opcode/cgen.h"
 
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
 static unsigned int hash_keyword_name
   PARAMS ((const CGEN_KEYWORD *, const char *, int));
 static unsigned int hash_keyword_value
@@ -64,9 +69,7 @@ cgen_keyword_lookup_name (kt, name)
 
       while (*p
             && (*p == *n
-                || (isalpha ((unsigned char) *p)
-                    && (tolower ((unsigned char) *p)
-                        == tolower ((unsigned char) *n)))))
+                || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
        ++n, ++p;
 
       if (!*p && !*n)
@@ -113,6 +116,7 @@ cgen_keyword_add (kt, ke)
      CGEN_KEYWORD_ENTRY *ke;
 {
   unsigned int hash;
+  size_t i;
 
   if (kt->name_hash_table == NULL)
     build_keyword_hash_tables (kt);
@@ -127,6 +131,21 @@ cgen_keyword_add (kt, ke)
 
   if (ke->name[0] == 0)
     kt->null_entry = ke;
+
+  for (i = 1; i < strlen (ke->name); i++)
+    if (! ISALNUM (ke->name[i])
+       && ! strchr (kt->nonalpha_chars, ke->name[i]))
+      {
+       size_t idx = strlen (kt->nonalpha_chars);
+       
+       /* If you hit this limit, please don't just
+          increase the size of the field, instead
+          look for a better algorithm.  */
+       if (idx >= sizeof (kt->nonalpha_chars) - 1)
+         abort ();
+       kt->nonalpha_chars[idx] = ke->name[i];
+       kt->nonalpha_chars[idx+1] = 0;
+      }
 }
 
 /* FIXME: Need function to return count of keywords.  */
@@ -211,7 +230,7 @@ hash_keyword_name (kt, name, case_sensitive_p)
       hash = (hash * 97) + (unsigned char) *name;
   else
     for (hash = 0; *name; ++name)
-      hash = (hash * 97) + (unsigned char) tolower (*name);
+      hash = (hash * 97) + (unsigned char) TOLOWER (*name);
   return hash % kt->hash_table_size;
 }
 
@@ -263,7 +282,7 @@ cgen_hw_lookup_by_name (cd, name)
      CGEN_CPU_DESC cd;
      const char *name;
 {
-  int i;
+  unsigned int i;
   const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
 
   for (i = 0; i < cd->hw_table.num_entries; ++i)
@@ -281,9 +300,9 @@ cgen_hw_lookup_by_name (cd, name)
 const CGEN_HW_ENTRY *
 cgen_hw_lookup_by_num (cd, hwnum)
      CGEN_CPU_DESC cd;
-     int hwnum;
+     unsigned int hwnum;
 {
-  int i;
+  unsigned int i;
   const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
 
   /* ??? This can be speeded up.  */
@@ -305,7 +324,7 @@ cgen_operand_lookup_by_name (cd, name)
      CGEN_CPU_DESC cd;
      const char *name;
 {
-  int i;
+  unsigned int i;
   const CGEN_OPERAND **op = cd->operand_table.entries;
 
   for (i = 0; i < cd->operand_table.num_entries; ++i)
@@ -370,27 +389,32 @@ cgen_get_insn_value (cd, buf, length)
      unsigned char *buf;
      int length;
 {
-  CGEN_INSN_INT value;
+  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
+  int insn_chunk_bitsize = cd->insn_chunk_bitsize;
+  CGEN_INSN_INT value = 0;
 
-  switch (length)
+  if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
     {
-    case 8:
-      value = *buf;
-      break;
-    case 16:
-      if (cd->insn_endian == CGEN_ENDIAN_BIG)
-       value = bfd_getb16 (buf);
-      else
-       value = bfd_getl16 (buf);
-      break;
-    case 32:
-      if (cd->insn_endian == CGEN_ENDIAN_BIG)
-       value = bfd_getb32 (buf);
-      else
-       value = bfd_getl32 (buf);
-      break;
-    default:
-      abort ();
+      /* We need to divide up the incoming value into insn_chunk_bitsize-length
+        segments, and endian-convert them, one at a time. */
+      int i;
+
+      /* Enforce divisibility. */ 
+      if ((length % insn_chunk_bitsize) != 0)
+       abort ();
+
+      for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
+       {
+         int index;
+         bfd_vma this_value;
+         index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
+         this_value = bfd_get_bits (& buf[index / 8], insn_chunk_bitsize, big_p);
+         value = (value << insn_chunk_bitsize) | this_value;
+       }
+    }
+  else
+    {
+      value = bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
     }
 
   return value;
@@ -405,25 +429,30 @@ cgen_put_insn_value (cd, buf, length, value)
      int length;
      CGEN_INSN_INT value;
 {
-  switch (length)
+  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
+  int insn_chunk_bitsize = cd->insn_chunk_bitsize;
+
+  if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
     {
-    case 8:
-      buf[0] = value;
-      break;
-    case 16:
-      if (cd->insn_endian == CGEN_ENDIAN_BIG)
-       bfd_putb16 (value, buf);
-      else
-       bfd_putl16 (value, buf);
-      break;
-    case 32:
-      if (cd->insn_endian == CGEN_ENDIAN_BIG)
-       bfd_putb32 (value, buf);
-      else
-       bfd_putl32 (value, buf);
-      break;
-    default:
-      abort ();
+      /* We need to divide up the incoming value into insn_chunk_bitsize-length
+        segments, and endian-convert them, one at a time. */
+      int i;
+
+      /* Enforce divisibility. */ 
+      if ((length % insn_chunk_bitsize) != 0)
+       abort ();
+
+      for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
+       {
+         int index;
+         index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
+         bfd_put_bits ((bfd_vma) value, & buf[index / 8], insn_chunk_bitsize, big_p);
+         value >>= insn_chunk_bitsize;
+       }
+    }
+  else
+    {
+      bfd_put_bits ((bfd_vma) value, buf, length, big_p);
     }
 }
 \f
This page took 0.031924 seconds and 4 git commands to generate.